From patchwork Thu Jul 21 12:36:37 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: alexandros.frantzis@linaro.org X-Patchwork-Id: 2952 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id C836423F4D for ; Thu, 21 Jul 2011 12:42:44 +0000 (UTC) Received: from mail-qw0-f52.google.com (mail-qw0-f52.google.com [209.85.216.52]) by fiordland.canonical.com (Postfix) with ESMTP id 9678AA1822A for ; Thu, 21 Jul 2011 12:42:44 +0000 (UTC) Received: by mail-qw0-f52.google.com with SMTP id 8so853237qwb.11 for ; Thu, 21 Jul 2011 05:42:44 -0700 (PDT) Received: by 10.224.198.7 with SMTP id em7mr187164qab.112.1311252164375; Thu, 21 Jul 2011 05:42:44 -0700 (PDT) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.229.217.78 with SMTP id hl14cs139510qcb; Thu, 21 Jul 2011 05:42:44 -0700 (PDT) Received: by 10.227.55.66 with SMTP id t2mr154106wbg.109.1311251798477; Thu, 21 Jul 2011 05:36:38 -0700 (PDT) Received: from adelie.canonical.com (adelie.canonical.com [91.189.90.139]) by mx.google.com with ESMTP id 16si2406944wbx.1.2011.07.21.05.36.38; Thu, 21 Jul 2011 05:36:38 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of bounces@canonical.com designates 91.189.90.139 as permitted sender) client-ip=91.189.90.139; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of bounces@canonical.com designates 91.189.90.139 as permitted sender) smtp.mail=bounces@canonical.com Received: from loganberry.canonical.com ([91.189.90.37]) by adelie.canonical.com with esmtp (Exim 4.71 #1 (Debian)) id 1QjsUX-0000sK-QC for ; Thu, 21 Jul 2011 12:36:37 +0000 Received: from loganberry.canonical.com (localhost [127.0.0.1]) by loganberry.canonical.com (Postfix) with ESMTP id BFBD02E84FB for ; Thu, 21 Jul 2011 12:36:37 +0000 (UTC) MIME-Version: 1.0 X-Launchpad-Project: glmark2 X-Launchpad-Branch: ~glmark2-dev/glmark2/trunk X-Launchpad-Message-Rationale: Subscriber X-Launchpad-Branch-Revision-Number: 105 X-Launchpad-Notification-Type: branch-revision To: Linaro Patch Tracker From: noreply@launchpad.net Subject: [Branch ~glmark2-dev/glmark2/trunk] Rev 105: Refactor Model class to correctly read 3ds files with multiple objects. Message-Id: <20110721123637.17019.34821.launchpad@loganberry.canonical.com> Date: Thu, 21 Jul 2011 12:36:37 -0000 Reply-To: noreply@launchpad.net Sender: bounces@canonical.com Errors-To: bounces@canonical.com Precedence: bulk X-Generated-By: Launchpad (canonical.com); Revision="13475"; Instance="initZopeless config overlay" X-Launchpad-Hash: c6d5b14c57ed11b063086f57241869229ae40061 ------------------------------------------------------------ revno: 105 committer: Alexandros Frantzis timestamp: Tue 2011-07-12 12:05:53 +0300 message: Refactor Model class to correctly read 3ds files with multiple objects. modified: src/model.cpp src/model.h --- lp:glmark2 https://code.launchpad.net/~glmark2-dev/glmark2/trunk You are subscribed to branch lp:glmark2. To unsubscribe from this branch go to https://code.launchpad.net/~glmark2-dev/glmark2/trunk/+edit-subscription === modified file 'src/model.cpp' --- src/model.cpp 2011-07-01 15:31:27 +0000 +++ src/model.cpp 2011-07-12 09:05:53 +0000 @@ -24,29 +24,63 @@ #include "model.h" #include "vec.h" #include "log.h" - -long filelength(int f) -{ - struct stat buf; - fstat(f, &buf); - return(buf.st_size); -} - -Model::Model() -{ - mPolygonQty = 0; - mVertexQty = 0; - mVertex = 0; // Set pointer to null - mPolygon = 0; // Set pointer to null -} - -Model::~Model() -{ - delete [] mVertex; - delete [] mPolygon; -} - -void Model::convert_to_mesh(Mesh &mesh) +#include "options.h" + +#include +#include + +#define read_or_fail(file, dst, size) do { \ + file.read(reinterpret_cast((dst)), (size)); \ + if (file.gcount() < (std::streamsize)(size)) { \ + Log::error("%s: %d: Failed to read %zd bytes from 3ds file (read %zd)\n", \ + __FUNCTION__, __LINE__, \ + (size_t)(size), file.gcount()); \ + return false; \ + } \ +} while(0); + +void +Model::append_object_to_mesh(const Object &object, Mesh &mesh, + int p_pos, int n_pos, int t_pos) +{ + size_t face_count = object.faces.size(); + + for(size_t i = 0; i < 3 * face_count; i += 3) + { + const Face &face = object.faces[i / 3]; + const Vertex &a = object.vertices[face.a]; + const Vertex &b = object.vertices[face.b]; + const Vertex &c = object.vertices[face.c]; + + mesh.next_vertex(); + if (p_pos >= 0) + mesh.set_attrib(p_pos, a.v); + if (n_pos >= 0) + mesh.set_attrib(n_pos, a.n); + if (t_pos >= 0) + mesh.set_attrib(t_pos, a.t); + + mesh.next_vertex(); + if (p_pos >= 0) + mesh.set_attrib(p_pos, b.v); + if (n_pos >= 0) + mesh.set_attrib(n_pos, b.n); + if (t_pos >= 0) + mesh.set_attrib(t_pos, b.t); + + mesh.next_vertex(); + if (p_pos >= 0) + mesh.set_attrib(p_pos, c.v); + if (n_pos >= 0) + mesh.set_attrib(n_pos, c.n); + if (t_pos >= 0) + mesh.set_attrib(t_pos, c.t); + } + +} + +void +Model::convert_to_mesh(Mesh &mesh) { std::vector > attribs; @@ -57,8 +91,9 @@ convert_to_mesh(mesh, attribs); } -void Model::convert_to_mesh(Mesh &mesh, - const std::vector > &attribs) +void +Model::convert_to_mesh(Mesh &mesh, + const std::vector > &attribs) { std::vector format; int p_pos = -1; @@ -82,115 +117,79 @@ mesh.set_vertex_format(format); - for(unsigned i = 0; i < 3 * mPolygonQty; i += 3) + for (std::vector::const_iterator iter = objects_.begin(); + iter != objects_.end(); + iter++) { - mesh.next_vertex(); - if (p_pos >= 0) - mesh.set_attrib(p_pos, mVertex[mPolygon[i / 3].mA].v); - if (n_pos >= 0) - mesh.set_attrib(n_pos, mVertex[mPolygon[i / 3].mA].n); - if (t_pos >= 0) - mesh.set_attrib(t_pos, mVertex[mPolygon[i / 3].mA].t); - - mesh.next_vertex(); - if (p_pos >= 0) - mesh.set_attrib(p_pos, mVertex[mPolygon[i / 3].mB].v); - if (n_pos >= 0) - mesh.set_attrib(n_pos, mVertex[mPolygon[i / 3].mB].n); - if (t_pos >= 0) - mesh.set_attrib(t_pos, mVertex[mPolygon[i / 3].mB].t); - - mesh.next_vertex(); - if (p_pos >= 0) - mesh.set_attrib(p_pos, mVertex[mPolygon[i / 3].mC].v); - if (n_pos >= 0) - mesh.set_attrib(n_pos, mVertex[mPolygon[i / 3].mC].n); - if (t_pos >= 0) - mesh.set_attrib(t_pos, mVertex[mPolygon[i / 3].mC].t); + append_object_to_mesh(*iter, mesh, p_pos, n_pos, t_pos); } } -void Model::calculate_normals() +void +Model::calculate_normals() { LibMatrix::vec3 n; - for(unsigned i = 0; i < mPolygonQty; i++) - { - n = LibMatrix::vec3::cross(mVertex[mPolygon[i].mB].v - mVertex[mPolygon[i].mA].v, - mVertex[mPolygon[i].mC].v - mVertex[mPolygon[i].mA].v); - n.normalize(); - mVertex[mPolygon[i].mA].n += n; - mVertex[mPolygon[i].mB].n += n; - mVertex[mPolygon[i].mC].n += n; - } - - for(unsigned i = 0; i < mVertexQty; i++) - mVertex[i].n.normalize(); -} - -void Model::center() -{ - LibMatrix::vec3 max(mVertex[0].v); - LibMatrix::vec3 min(mVertex[0].v); - - for(unsigned i = 1; i < mVertexQty; i++) - { - if(mVertex[i].v.x() > max.x()) max.x(mVertex[i].v.x()); - if(mVertex[i].v.y() > max.y()) max.y(mVertex[i].v.y()); - if(mVertex[i].v.z() > max.z()) max.z(mVertex[i].v.z()); - - if(mVertex[i].v.x() < min.x()) min.x(mVertex[i].v.x()); - if(mVertex[i].v.y() < min.y()) min.y(mVertex[i].v.y()); - if(mVertex[i].v.z() < min.z()) min.z(mVertex[i].v.z()); - } - - LibMatrix::vec3 center(max + min); - center /= 2.0f; - - for(unsigned i = 0; i < mVertexQty; i++) - mVertex[i].v -= center; -} - -void Model::scale(GLfloat pAmount) -{ - for(unsigned i = 1; i < mVertexQty; i++) - mVertex[i].v *= pAmount; -} - -#define fread_or_fail(a, b, c, d) do { \ - size_t nread_; \ - nread_ = fread((a), (b), (c), (d));\ - if (nread_ < (c)) { \ - Log::error("Failed to read %zd bytes from 3ds file (read %zd)\n", \ - (size_t)((c) * (b)), nread_ * (b)); \ - return 0; \ - } \ -} while(0); - -int Model::load_3ds(const char *pFileName) -{ - int i; - FILE *l_file; - unsigned short l_chunk_id; - unsigned int l_chunk_length; - unsigned char l_char; - unsigned short l_qty; - - Log::debug("Loading model from 3ds file '%s'\n", pFileName); - - if ((l_file = fopen (pFileName, "rb")) == NULL) { - Log::error("Could not open 3ds file '%s'\n", pFileName); - return 0; + for (std::vector::iterator iter = objects_.begin(); + iter != objects_.end(); + iter++) + { + Object &object = *iter; + size_t face_count = object.faces.size(); + size_t vertex_count = object.vertices.size(); + + for(unsigned i = 0; i < face_count; i++) + { + const Face &face = object.faces[i]; + Vertex &a = object.vertices[face.a]; + Vertex &b = object.vertices[face.b]; + Vertex &c = object.vertices[face.c]; + + n = LibMatrix::vec3::cross(b.v - a.v, c.v - a.v); + n.normalize(); + a.n += n; + b.n += n; + c.n += n; + } + + for(unsigned i = 0; i < vertex_count; i++) + object.vertices[i].n.normalize(); + } +} + +bool +Model::load_3ds(const std::string &filename) +{ + Object *object; + + Log::debug("Loading model from 3ds file '%s'\n", filename.c_str()); + + std::fstream input_file(filename.c_str()); + if (!input_file) { + Log::error("Could not open 3ds file '%s'\n", filename.c_str()); + return false; } // Loop to scan the whole file - while (ftell (l_file) < filelength (fileno (l_file))) { + while (!input_file.eof()) { + uint16_t chunk_id; + uint32_t chunk_length; + // Read the chunk header - fread_or_fail (&l_chunk_id, 2, 1, l_file); + input_file.read(reinterpret_cast(&chunk_id), 2); + if (input_file.gcount() == 0) { + continue; + } + else if (input_file.gcount() < 2) { + Log::error("%s: %d: Failed to read %zd bytes from 3ds file (read %zd)\n", + __FUNCTION__, __LINE__, 2, input_file.gcount()); + return false; + } + //Read the lenght of the chunk - fread_or_fail (&l_chunk_length, 4, 1, l_file); + read_or_fail(input_file, &chunk_length, 4); - switch (l_chunk_id) + switch (chunk_id) { //----------------- MAIN3DS ----------------- // Description: Main chunk, contains all the other chunks @@ -214,12 +213,18 @@ // Chunk Lenght: len(object name) + sub chunks //------------------------------------------- case 0x4000: - i = 0; - do { - fread_or_fail (&l_char, 1, 1, l_file); - mName[i] = l_char; - i++; - } while(l_char != '\0' && i<20); + { + std::stringstream ss; + unsigned char c = 1; + + for (int i = 0; i < 20 && c != '\0'; i++) { + read_or_fail(input_file, &c, 1); + ss << c; + } + + objects_.push_back(Object(ss.str())); + object = &objects_.back(); + } break; //--------------- OBJ_TRIMESH --------------- @@ -238,15 +243,18 @@ // + sub chunks //------------------------------------------- case 0x4110: - fread_or_fail (&l_qty, sizeof (unsigned short), 1, l_file); - mVertexQty = l_qty; - mVertex = new Vertex[mVertexQty]; - for (i = 0; i < l_qty; i++) { + { + uint16_t qty; + read_or_fail(input_file, &qty, sizeof(uint16_t)); + object->vertices.resize(qty); + + for (uint16_t i = 0; i < qty; i++) { float f[3]; - fread_or_fail (f, sizeof(float), 3, l_file); - mVertex[i].v.x(f[0]); - mVertex[i].v.y(f[1]); - mVertex[i].v.z(f[2]); + read_or_fail(input_file, f, sizeof(float) * 3); + object->vertices[i].v.x(f[0]); + object->vertices[i].v.y(f[1]); + object->vertices[i].v.z(f[2]); + } } break; @@ -258,14 +266,16 @@ // + sub chunks //------------------------------------------- case 0x4120: - fread_or_fail (&l_qty, sizeof (unsigned short), 1, l_file); - mPolygonQty = l_qty; - mPolygon = new Polygon[mPolygonQty]; - for (i = 0; i < l_qty; i++) { - fread_or_fail (&mPolygon[i].mA, sizeof (unsigned short), 1, l_file); - fread_or_fail (&mPolygon[i].mB, sizeof (unsigned short), 1, l_file); - fread_or_fail (&mPolygon[i].mC, sizeof (unsigned short), 1, l_file); - fread_or_fail (&mPolygon[i].mFaceFlags, sizeof (unsigned short), 1, l_file); + { + uint16_t qty; + read_or_fail(input_file, &qty, sizeof(uint16_t)); + object->faces.resize(qty); + for (uint16_t i = 0; i < qty; i++) { + read_or_fail(input_file, &object->faces[i].a, sizeof(uint16_t)); + read_or_fail(input_file, &object->faces[i].b, sizeof(uint16_t)); + read_or_fail(input_file, &object->faces[i].c, sizeof(uint16_t)); + read_or_fail(input_file, &object->faces[i].face_flags, sizeof(uint16_t)); + } } break; @@ -277,12 +287,15 @@ // + sub chunks //------------------------------------------- case 0x4140: - fread_or_fail (&l_qty, sizeof (unsigned short), 1, l_file); - for (i = 0; i < l_qty; i++) { + { + uint16_t qty; + read_or_fail(input_file, &qty, sizeof(uint16_t)); + for (uint16_t i = 0; i < qty; i++) { float f[2]; - fread_or_fail (f, sizeof(float), 2, l_file); - mVertex[i].t.x(f[0]); - mVertex[i].t.y(f[1]); + read_or_fail(input_file, f, sizeof(float) * 2); + object->vertices[i].t.x(f[0]); + object->vertices[i].t.y(f[1]); + } } break; @@ -292,15 +305,19 @@ //to the same level next chunk //------------------------------------------- default: - fseek(l_file, l_chunk_length - 6, SEEK_CUR); - } - } - fclose(l_file); // Closes the file stream - - Log::debug(" Model Information\n" - " Name: %s\n" - " Vertex count: %d\n" - " Polygon count: %d\n", - mName, mVertexQty, mPolygonQty); - return 1; + input_file.seekg(chunk_length - 6, std::ios::cur); + } + } + + if (Options::show_debug) { + for (std::vector::const_iterator iter = objects_.begin(); + iter != objects_.end(); + iter++) + { + Log::debug(" Object name: %s Vertex count: %d Face count: %d\n", + iter->name.c_str(), iter->vertices.size(), iter->faces.size()); + } + } + + return true; } === modified file 'src/model.h' --- src/model.h 2011-07-01 15:31:27 +0000 +++ src/model.h 2011-07-12 09:05:53 +0000 @@ -31,29 +31,11 @@ #include #include -class Polygon -{ -public: - unsigned short mA, mB, mC; - unsigned short mFaceFlags; -}; - -struct Vertex { - LibMatrix::vec3 v; - LibMatrix::vec3 n; - LibMatrix::vec2 t; -}; - // A model as loaded from a 3ds file class Model { public: - unsigned mPolygonQty; - unsigned mVertexQty; - Vertex *mVertex; - Polygon *mPolygon; - char mName[20]; typedef enum { AttribTypePosition = 1, @@ -62,16 +44,37 @@ AttribTypeCustom = 8 } AttribType; - Model(); - ~Model(); + Model() {} + ~Model() {} - int load_3ds(const char *pFileName); + bool load_3ds(const std::string &filename); void calculate_normals(); - void center(); - void scale(GLfloat pAmount); void convert_to_mesh(Mesh &mesh); void convert_to_mesh(Mesh &mesh, const std::vector > &attribs); +private: + struct Face { + uint16_t a, b, c; + uint16_t face_flags; + }; + + struct Vertex { + LibMatrix::vec3 v; + LibMatrix::vec3 n; + LibMatrix::vec2 t; + }; + + struct Object { + Object(const std::string &name) : name(name) {} + std::string name; + std::vector vertices; + std::vector faces; + }; + + void append_object_to_mesh(const Object &object, Mesh &mesh, + int p_pos, int n_pos, int t_pos); + + std::vector objects_; }; #endif