Mercurial > hg > forks > gldragon
diff dmmodel.cpp @ 21:1404dfcee7b8
More work on scenefile and model loading support.
Can now load PLY models and simple scene definition files.
Converted dragon mesh to binary PLY format.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Fri, 22 Nov 2019 03:03:52 +0200 |
parents | a329f0216491 |
children | 03b86b9c2f29 |
line wrap: on
line diff
--- a/dmmodel.cpp Fri Nov 22 00:14:16 2019 +0200 +++ b/dmmodel.cpp Fri Nov 22 03:03:52 2019 +0200 @@ -2,6 +2,7 @@ // // #include "dmmodel.h" +#include <SDL_endian.h> static bool dmError(DMTextFileInfo &info, const std::string &msg) @@ -139,7 +140,10 @@ // Read one line if (!dmReadLine(info)) - return false; + { + return dmError(info, + "Unexpected end of file"); + } // Skip empty lines if (info.line.empty()) @@ -166,71 +170,53 @@ bool dmPLYReadPropertyValueBIN(DMPLYFileInfo &info, const DMPLYPropType ptype, DMPLYPropValue &pval) { - uint8_t tmp[8]; + uint8_t tmpU8; + int8_t tmpS8; uint16_t tmpU16; int16_t tmpS16; uint32_t tmpU32; int32_t tmpS32; + float tmpFloat; switch (ptype) { case PLY_TYPE_INT8: - info.file.read(reinterpret_cast<char *>(&tmp), 1); - pval.v_int = (int8_t) tmp[0]; + info.file.read(reinterpret_cast<char *>(&tmpS8), 1); + pval.v_int = tmpS8; break; case PLY_TYPE_UINT8: - info.file.read(reinterpret_cast<char *>(&tmp), 1); - pval.v_uint = (uint8_t) tmp[0]; + info.file.read(reinterpret_cast<char *>(&tmpU8), 1); + pval.v_uint = tmpU8; break; case PLY_TYPE_INT16: - info.file.read(reinterpret_cast<char *>(&tmp), 2); - tmpS16 = - (tmp[0] << 8) | - (tmp[1]); + info.file.read(reinterpret_cast<char *>(&tmpS16), 2); + tmpS16 = (info.format == PLY_FMT_BIN_LE) ? SDL_SwapLE16(tmpS16) : SDL_SwapBE16(tmpS16); pval.v_int = tmpS16; break; case PLY_TYPE_UINT16: - info.file.read(reinterpret_cast<char *>(&tmp), 2); - tmpU16 = - (tmp[0] << 8) | - (tmp[1]); + info.file.read(reinterpret_cast<char *>(&tmpU16), 2); + tmpU16 = (info.format == PLY_FMT_BIN_LE) ? SDL_SwapLE16(tmpU16) : SDL_SwapBE16(tmpU16); pval.v_uint = tmpU16; break; case PLY_TYPE_INT32: - info.file.read(reinterpret_cast<char *>(&tmp), 4); - tmpS32 = - (tmp[0] << 24) | - (tmp[1] << 16) | - (tmp[2] << 8) | - (tmp[3]); - + info.file.read(reinterpret_cast<char *>(&tmpS32), 4); + tmpS32 = (info.format == PLY_FMT_BIN_LE) ? SDL_SwapLE32(tmpS32) : SDL_SwapBE32(tmpS32); pval.v_int = tmpS32; break; case PLY_TYPE_UINT32: - info.file.read(reinterpret_cast<char *>(&tmp), 4); - tmpU32 = - (tmp[3] << 24) | - (tmp[2] << 16) | - (tmp[1] << 8) | - (tmp[0]); - + info.file.read(reinterpret_cast<char *>(&tmpU32), 4); + tmpU32 = (info.format == PLY_FMT_BIN_LE) ? SDL_SwapLE32(tmpU32) : SDL_SwapBE32(tmpU32); pval.v_uint = tmpU32; break; case PLY_TYPE_FLOAT: - info.file.read(reinterpret_cast<char *>(&tmp), 4); - tmpU32 = - (tmp[0] << 24) | - (tmp[1] << 16) | - (tmp[2] << 8) | - (tmp[3]); - - pval.v_uint = tmpU32; + info.file.read(reinterpret_cast<char *>(&tmpFloat), 4); + pval.v_float = (info.format == PLY_FMT_BIN_LE) ? SDL_SwapFloatLE(tmpFloat) : SDL_SwapFloatBE(tmpFloat); break; default: @@ -548,7 +534,7 @@ else if (element->name == PLY_ELEM_VERTEX) { - DMVertex vert; + DMVector3 vert; vert.x = element->prop_map["x"].value.v_float; vert.y = element->prop_map["y"].value.v_float; vert.z = element->prop_map["z"].value.v_float; @@ -559,7 +545,7 @@ element->checkProp("ny") && element->checkProp("nz")) { - DMVertex normal; + DMVector3 normal; normal.x = element->prop_map["nx"].value.v_float; normal.y = element->prop_map["ny"].value.v_float; normal.z = element->prop_map["nz"].value.v_float; @@ -578,9 +564,91 @@ } +bool dmParseVector(DMTextFileInfo &info, const std::vector<std::string> tokens, const size_t offs, DMVector3 &vec) +{ + if (tokens.size() == offs + 1) + { + vec.x = vec.y = vec.z = std::stof(tokens[offs]); + } + else + if (tokens.size() == offs + 3) + { + vec.x = std::stof(tokens[offs]); + vec.y = std::stof(tokens[offs + 1]); + vec.z = std::stof(tokens[offs + 2]); + } + else + { + return dmSyntaxError(info, + "Expected 1/3 value vector for '"+ *info.key +"'"); + } + + return true; +} + + +bool dmParseVector(DMTextFileInfo &info, const std::vector<std::string> tokens, const size_t offs, DMVector4 &vec) +{ + vec.w = 1.0f; + + if (tokens.size() == offs + 1) + { + vec.x = vec.y = vec.z = std::stof(tokens[offs]); + } + else + if (tokens.size() == offs + 3 || tokens.size() == offs + 4) + { + vec.x = std::stof(tokens[offs]); + vec.y = std::stof(tokens[offs + 1]); + vec.z = std::stof(tokens[offs + 2]); + + if (tokens.size() == offs + 4) + vec.w = std::stof(tokens[offs + 3]); + } + else + { + return dmSyntaxError(info, + "Expected 1/3/4 value vector for '"+ *info.key +"'"); + } + + return true; +} + + +bool dmParseColor(DMTextFileInfo &info, const std::vector<std::string> tokens, const size_t offs, DMColor &color) +{ + color.alpha = 0xff; + + if (tokens.size() == offs + 1) + { + color.r = color.g = color.b = std::stoi(tokens[offs], 0, 0); + } + else + if (tokens.size() == offs + 3 || tokens.size() == offs + 4) + { + color.r = std::stoi(tokens[offs], 0, 0); + color.g = std::stoi(tokens[offs + 1], 0, 0); + color.b = std::stoi(tokens[offs + 2], 0, 0); + + if (tokens.size() == offs + 4) + color.alpha = std::stoi(tokens[offs + 3], 0, 0); + } + else + { + return dmSyntaxError(info, + "Expected color values <value> or <red> <green> <blue> [<alpha>] for '"+ *info.key +"'"); + } + + return true; +} + + bool DMSimpleScene::loadInfo(const std::string &filename) { DMTextFileInfo info; + DMModel *model = 0; + DMLight *light = 0; + DMVector3 *ppos = 0, *ppointAt = 0; info.filename = filename; info.nline = info.state = 0; @@ -613,88 +681,103 @@ // Split key and values std::vector<std::string> tokens = dmStrSplit(info.line); - std::string &key = tokens[0]; + std::string key = tokens[0]; + info.key = &key; - if (key == "color") + if (key == "model") { - DMColor color; - color.alpha = 0xff; - - if (tokens.size() == 2) + DMModel newmodel; + if (tokens.size() != 2) { - color.r = color.g = color.b = std::stoi(tokens[1], 0, 0); - } - else - if (tokens.size() == 4 || tokens.size() == 5) - { - color.r = std::stoi(tokens[1], 0, 0); - color.g = std::stoi(tokens[2], 0, 0); - color.b = std::stoi(tokens[3], 0, 0); - - if (tokens.size() == 5) - color.alpha = std::stoi(tokens[4], 0, 0); - } - else - { - return dmSyntaxError(info, - "Expected color values <value> or <red> <green> <blue> [<alpha>]"); + return dmError(info, + "Keyword model expects a filename argument"); } - model.color = color; + models.push_back(newmodel); + model = &models.back(); + model->modelFile = tokens[1]; + info.state = 1; } else - if (key == "translate" || key == "rotate" || key == "scale" || - key == "camera_pos" || key == "camera_at") + if (info.state == 1 && key == "color") { - DMVertex vec; + if (!dmParseColor(info, tokens, 1, model->color)) + return false; + } + else + if (info.state == 1 && (key == "translate" || key == "rotate" || key == "scale")) + { + DMVector3 vec; - if (tokens.size() == 2) - { - vec.x = vec.y = vec.z = std::stof(tokens[1]); - } - else - if (tokens.size() == 4) - { - vec.x = std::stof(tokens[1]); - vec.y = std::stof(tokens[2]); - vec.z = std::stof(tokens[3]); - } - else - { - return dmSyntaxError(info, - "Expected vector value for '"+ key +"'"); - } + if (!dmParseVector(info, tokens, 1, vec)) + return false; + + if (!model) + return false; if (key == "translate") - model.translate = vec; + model->translate = vec; else if (key == "rotate") - model.rotate = vec; + model->rotate = vec; else if (key == "scale") - model.scale = vec; - else - if (key == "camera_pos") - camera.pos = vec; - else - if (key == "camera_at") - camera.lookAt = vec; + model->scale = vec; } else if (key == "light") { - if (tokens.size() == 4) + DMLight newlight; + + if (lights.size() >= 4) { - DMVertex pos; - pos.x = std::stof(tokens[1]); - pos.y = std::stof(tokens[2]); - pos.z = std::stof(tokens[3]); + printf("ERROR: Too many lights defined.\n"); + return false; } + lights.push_back(newlight); + light = &lights.back(); + ppos = &light->pos; + ppointAt = &light->pointAt; + info.state = 2; + } + else + if (info.state == 2 && (key == "ambient" || key == "diffuse" || key == "specular")) + { + DMVector4 val; + + if (!dmParseVector(info, tokens, 1, val)) + return false; + + if (key == "ambient") + light->ambient = val; else - { - return dmSyntaxError(info, - "Expected light definition as <x> <y> <z> "); - } + if (key == "diffuse") + light->diffuse = val; + else + if (key == "specular") + light->specular = val; + } + else + if (key == "camera") + { + info.state = 3; + + ppos = &camera.pos; + ppointAt = &camera.pointAt; + } + else + if ((info.state == 3 || info.state == 2) && (key == "pos" || key == "point_at")) + { + DMVector3 vec; + + if (!dmParseVector(info, tokens, 1, vec)) + return false; + + if (key == "pos") + *ppos = vec; + else + if (key == "point_at") + *ppointAt = vec; } else { @@ -703,7 +786,5 @@ } } - model.printInfo(); - return true; }