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;
 }