From patchwork Fri Sep 16 12:24:16 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: 4124 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 5121423EFC for ; Fri, 16 Sep 2011 12:24:18 +0000 (UTC) Received: from mail-fx0-f52.google.com (mail-fx0-f52.google.com [209.85.161.52]) by fiordland.canonical.com (Postfix) with ESMTP id 35515A18AB3 for ; Fri, 16 Sep 2011 12:24:18 +0000 (UTC) Received: by fxe23 with SMTP id 23so2271643fxe.11 for ; Fri, 16 Sep 2011 05:24:18 -0700 (PDT) Received: by 10.223.63.8 with SMTP id z8mr1716269fah.84.1316175857983; Fri, 16 Sep 2011 05:24:17 -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.152.11.8 with SMTP id m8cs126436lab; Fri, 16 Sep 2011 05:24:17 -0700 (PDT) Received: by 10.216.132.226 with SMTP id o76mr684154wei.17.1316175856974; Fri, 16 Sep 2011 05:24:16 -0700 (PDT) Received: from indium.canonical.com (indium.canonical.com [91.189.90.7]) by mx.google.com with ESMTPS id r18si10955010wec.84.2011.09.16.05.24.16 (version=TLSv1/SSLv3 cipher=OTHER); Fri, 16 Sep 2011 05:24:16 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of bounces@canonical.com designates 91.189.90.7 as permitted sender) client-ip=91.189.90.7; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of bounces@canonical.com designates 91.189.90.7 as permitted sender) smtp.mail=bounces@canonical.com Received: from ackee.canonical.com ([91.189.89.26]) by indium.canonical.com with esmtp (Exim 4.71 #1 (Debian)) id 1R4XSq-0002e5-DB for ; Fri, 16 Sep 2011 12:24:16 +0000 Received: from ackee.canonical.com (localhost [127.0.0.1]) by ackee.canonical.com (Postfix) with ESMTP id 58F46E06D1 for ; Fri, 16 Sep 2011 12:24:16 +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: 134 X-Launchpad-Notification-Type: branch-revision To: Linaro Patch Tracker From: noreply@launchpad.net Subject: [Branch ~glmark2-dev/glmark2/trunk] Rev 134: Model: Add support for loading models from OBJ geometry files. Message-Id: <20110916122416.29356.52041.launchpad@ackee.canonical.com> Date: Fri, 16 Sep 2011 12:24:16 -0000 Reply-To: noreply@launchpad.net Sender: bounces@canonical.com Errors-To: bounces@canonical.com Precedence: bulk X-Generated-By: Launchpad (canonical.com); Revision="13955"; Instance="initZopeless config overlay" X-Launchpad-Hash: 4d15932829b98ae03a31f5e42e69d56b19115b01 ------------------------------------------------------------ revno: 134 author: Jesse Barker committer: Alexandros Frantzis branch nick: obj2 timestamp: Fri 2011-09-16 14:49:39 +0300 message: Model: Add support for loading models from OBJ geometry files. 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-08-10 13:52:04 +0000 +++ src/model.cpp 2011-09-16 11:49:39 +0000 @@ -26,10 +26,18 @@ #include "log.h" #include "options.h" #include "util.h" +#include "float.h" +#include #include #include +using std::string; +using std::vector; +using LibMatrix::vec3; +using LibMatrix::vec2; +using LibMatrix::uvec3; + #define read_or_fail(file, dst, size) do { \ file.read(reinterpret_cast((dst)), (size)); \ if (file.gcount() < (std::streamsize)(size)) { \ @@ -41,6 +49,47 @@ } while(0); void +Model::compute_bounding_box(const Object& object) +{ + float minX(FLT_MAX); + float maxX(FLT_MIN); + float minY(FLT_MAX); + float maxY(FLT_MIN); + float minZ(FLT_MAX); + float maxZ(FLT_MIN); + for (vector::const_iterator vIt = object.vertices.begin(); vIt != object.vertices.end(); vIt++) + { + const vec3& curVtx = vIt->v; + if (curVtx.x() < minX) + { + minX = curVtx.x(); + } + if (curVtx.x() > maxX) + { + maxX = curVtx.x(); + } + if (curVtx.y() < minY) + { + minY = curVtx.y(); + } + if (curVtx.y() > maxY) + { + maxY = curVtx.y(); + } + if (curVtx.z() < minZ) + { + minZ = curVtx.z(); + } + if (curVtx.z() > maxZ) + { + maxZ = curVtx.z(); + } + } + maxVec_ = vec3(maxX, maxY, maxZ); + minVec_ = vec3(minX, minY, minZ); +} + +void Model::append_object_to_mesh(const Object &object, Mesh &mesh, int p_pos, int n_pos, int t_pos) { @@ -312,6 +361,9 @@ } } + // Compute bounding box for perspective projection + compute_bounding_box(*object); + if (Options::show_debug) { for (std::vector::const_iterator iter = objects_.begin(); iter != objects_.end(); @@ -324,3 +376,227 @@ return true; } + +template T +fromString(const string& asString) +{ + std::stringstream ss(asString); + T retVal; + ss >> retVal; + return retVal; +} + +void +get_values(const string& source, vec3& v) +{ + // Skip the definition type... + string::size_type endPos = source.find(" "); + string::size_type startPos(0); + if (endPos == string::npos) + { + Log::error("Bad element '%s'\n", source.c_str()); + return; + } + // Find the first value... + startPos = endPos + 1; + endPos = source.find(" ", startPos); + if (endPos == string::npos) + { + Log::error("Bad element '%s'\n", source.c_str()); + return; + } + string::size_type numChars(endPos - startPos); + string xs(source, startPos, numChars); + float x = fromString(xs); + // Then the second value... + startPos = endPos + 1; + endPos = source.find(" ", startPos); + if (endPos == string::npos) + { + Log::error("Bad element '%s'\n", source.c_str()); + return; + } + numChars = endPos - startPos; + string ys(source, startPos, numChars); + float y = fromString(ys); + // And the third value (there might be a fourth, but we don't care)... + startPos = endPos + 1; + endPos = source.find(" ", startPos); + if (endPos == string::npos) + { + numChars = endPos; + } + else + { + numChars = endPos - startPos; + } + string zs(source, startPos, endPos - startPos); + float z = fromString(zs); + v.x(x); + v.y(y); + v.z(z); +} + +void +get_values(const string& source, vec2& v) +{ + // Skip the definition type... + string::size_type endPos = source.find(" "); + string::size_type startPos(0); + if (endPos == string::npos) + { + Log::error("Bad element '%s'\n", source.c_str()); + return; + } + // Find the first value... + startPos = endPos + 1; + endPos = source.find(" ", startPos); + if (endPos == string::npos) + { + Log::error("Bad element '%s'\n", source.c_str()); + return; + } + string::size_type numChars(endPos - startPos); + string xs(source, startPos, numChars); + float x = fromString(xs); + // Then the second value (there might be a third, but we don't care)... + startPos = endPos + 1; + endPos = source.find(" ", startPos); + if (endPos == string::npos) + { + numChars = endPos; + } + else + { + numChars = endPos - startPos; + } + string ys(source, startPos, numChars); + float y = fromString(ys); + v.x(x); + v.y(y); +} + +void +get_values(const string& source, uvec3& v) +{ + // Skip the definition type... + string::size_type endPos = source.find(" "); + string::size_type startPos(0); + if (endPos == string::npos) + { + Log::error("Bad element '%s'\n", source.c_str()); + return; + } + // Find the first value... + startPos = endPos + 1; + endPos = source.find(" ", startPos); + if (endPos == string::npos) + { + Log::error("Bad element '%s'\n", source.c_str()); + return; + } + string::size_type numChars(endPos - startPos); + string xs(source, startPos, numChars); + unsigned int x = fromString(xs); + // Then the second value... + startPos = endPos+1; + endPos = source.find(" ", startPos); + if (endPos == string::npos) + { + Log::error("Bad element '%s'\n", source.c_str()); + return; + } + numChars = endPos - startPos; + string ys(source, startPos, numChars); + unsigned int y = fromString(ys); + // And the third value (there might be a fourth, but we don't care)... + startPos = endPos + 1; + endPos = source.find(" ", startPos); + if (endPos == string::npos) + { + numChars = endPos; + } + else + { + numChars = endPos - startPos; + } + string zs(source, startPos, numChars); + unsigned int z = fromString(zs); + v.x(x); + v.y(y); + v.z(z); +} + +bool +Model::load_obj(const std::string &filename) +{ + std::ifstream inputFile(filename.c_str()); + if (!inputFile) + { + Log::error("Failed to open '%s'\n", filename.c_str()); + return false; + } + + vector sourceVec; + string curLine; + while (getline(inputFile, curLine)) + { + sourceVec.push_back(curLine); + } + + // Give ourselves an object to populate. + objects_.push_back(Object(filename)); + Object& object(objects_.back()); + + static const string vertex_definition("v"); + static const string normal_definition("vn"); + static const string texcoord_definition("vt"); + static const string face_definition("f"); + for (vector::const_iterator lineIt = sourceVec.begin(); + lineIt != sourceVec.end(); + lineIt++) + { + const string& curSrc = *lineIt; + // Is it a vertex attribute, a face description, comment or other? + // We only care about the first two, we ignore comments, object names, + // group names, smoothing groups, etc. + string::size_type startPos(0); + string::size_type spacePos = curSrc.find(" ", startPos); + string definitionType(curSrc, startPos, spacePos - startPos); + if (definitionType == vertex_definition) + { + Vertex v; + get_values(curSrc, v.v); + object.vertices.push_back(v); + } + else if (definitionType == normal_definition) + { + // If we encounter an OBJ model with normals, we can update this + // to update object.vertices.n directly + Log::debug("We got a normal...\n"); + } + else if (definitionType == texcoord_definition) + { + // If we encounter an OBJ model with normals, we can update this + // to update object.vertices.t directly + Log::debug("We got a texcoord...\n"); + } + else if (definitionType == face_definition) + { + uvec3 v; + get_values(curSrc, v); + Face f; + // OBJ models index from '1'. + f.a = v.x() - 1; + f.b = v.y() - 1; + f.c = v.z() - 1; + object.faces.push_back(f); + } + } + // Compute bounding box for perspective projection + compute_bounding_box(object); + + Log::debug("Object populated with %u vertices and %u faces.\n", + object.vertices.size(), object.faces.size()); + return true; +} === modified file 'src/model.h' --- src/model.h 2011-07-12 09:05:53 +0000 +++ src/model.h 2011-09-16 11:49:39 +0000 @@ -48,13 +48,16 @@ ~Model() {} bool load_3ds(const std::string &filename); + bool load_obj(const std::string &filename); void calculate_normals(); void convert_to_mesh(Mesh &mesh); void convert_to_mesh(Mesh &mesh, const std::vector > &attribs); + const LibMatrix::vec3& minVec() const { return minVec_; } + const LibMatrix::vec3& maxVec() const { return maxVec_; } private: struct Face { - uint16_t a, b, c; + uint32_t a, b, c; uint16_t face_flags; }; @@ -74,6 +77,10 @@ void append_object_to_mesh(const Object &object, Mesh &mesh, int p_pos, int n_pos, int t_pos); + // For vertices of the bounding box for this model. + void compute_bounding_box(const Object& object); + LibMatrix::vec3 minVec_; + LibMatrix::vec3 maxVec_; std::vector objects_; };