root/OpenSceneGraph/trunk/src/osgPlugins/x/mesh.cpp @ 13041

Revision 13041, 11.2 kB (checked in by robert, 3 years ago)

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1// -*-c++-*-
2
3/*
4 * $Id$
5 *
6 * Loader for DirectX .x files.
7 * Copyright (c)2002-2006 Ulrich Hertlein <u.hertlein@sandbox.de>
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22 */
23
24#if defined(_MSC_VER) && (_MSC_VER <= 1200)
25#pragma warning (disable : 4786)
26#endif
27
28#include "mesh.h"
29#include "directx.h"
30
31#include <iostream>
32#include <string.h>
33#include <stdlib.h>
34
35#include <osg/Notify>
36
37using namespace DX;
38using namespace std;
39
40
41/**********************************************************************
42 *
43 * DirectX mesh.
44 *
45 **********************************************************************/
46
47Mesh::Mesh(Object * obj)
48{
49    _obj = obj;
50    _normals = 0;
51    _textureCoords = 0;
52    _materialList = 0;
53}
54
55void Mesh::clear()
56{
57    if (_normals) {
58        delete _normals;
59        _normals = 0;
60    }
61
62    if (_textureCoords) {
63        delete _textureCoords;
64        _textureCoords = 0;
65    }
66
67    if (_materialList) {
68        delete _materialList;
69        _materialList = 0;
70    }
71}
72
73bool Mesh::generateNormals(float /*creaseAngle*/)
74{
75    //cerr << "*** generateNormals\n";
76
77    // Forget old normals
78    if (_normals) {
79        delete _normals;
80        _normals = 0;
81    }
82
83    /*
84     * Calculate per-face normals from face vertices.
85     */
86    vector<Vector> faceNormals;
87    faceNormals.resize(_faces.size());
88
89    unsigned int fi;
90    for (fi = 0; fi < _faces.size(); fi++) {
91
92        vector<Vector> poly;
93        unsigned int n = _faces[fi].size();
94
95        if (n < 3)
96            continue;
97        for (unsigned int i = 0; i < n; i++) {
98            unsigned int idx = _faces[fi][i];
99            poly.push_back(_vertices[idx]);
100        }
101
102        // Edge vectors
103        Vector e0;
104        e0.x = poly[1].x - poly[0].x;
105        e0.y = poly[1].y - poly[0].y;
106        e0.z = poly[1].z - poly[0].z;
107
108        Vector e1;
109        e1.x = poly[2].x - poly[0].x;
110        e1.y = poly[2].y - poly[0].y;
111        e1.z = poly[2].z - poly[0].z;
112
113        // Cross-product of e0,e1
114        Vector normal;
115        normal.x = e0.y * e1.z - e0.z * e1.y;
116        normal.y = e0.z * e1.x - e0.x * e1.z;
117        normal.z = e0.x * e1.y - e0.y * e1.x;
118        normal.normalize();
119
120        // Add to per-face normals
121        faceNormals[fi] = normal;
122    }
123
124    /*
125     * Calculate per-vertex normals as average of all per-face normals that
126     * share this vertex. The index of the vertex normal is identical to the
127     * vertex index for now. This means each vertex only has a single normal...
128     */
129    _normals = new MeshNormals;
130    _normals->normals.resize(_vertices.size());
131
132    for (unsigned int vi = 0; vi < _vertices.size(); vi++) {
133
134        Vector normal = { 0.0f, 0.0f, 0.0f };
135        unsigned int polyCount = 0;
136
137        // Collect normals of polygons that share this vertex
138        for (unsigned int fi = 0; fi < _faces.size(); fi++)
139            for (unsigned int i = 0; i < _faces[fi].size(); i++) {
140                unsigned int idx = _faces[fi][i];
141                if (idx == vi) {
142                    normal.x += faceNormals[fi].x;
143                    normal.y += faceNormals[fi].y;
144                    normal.z += faceNormals[fi].z;
145                    polyCount++;
146                }
147            }
148
149        //OSG_INFO << "vertex " << vi << " used by " << polyCount << " faces\n";
150        if (polyCount > 1) {
151            float polyCountRecip = 1.0f / (float) polyCount;
152            normal.x *= polyCountRecip;
153            normal.y *= polyCountRecip;
154            normal.z *= polyCountRecip;
155            normal.normalize();
156        }
157
158        // Add vertex normal
159        _normals->normals[vi] = normal;
160    }
161
162    // Copy face mesh to normals mesh
163    _normals->faceNormals.resize(_faces.size());
164    for (fi = 0; fi < _faces.size(); fi++)
165        _normals->faceNormals[fi] = _faces[fi];
166
167    return true;
168}
169
170// Parse 'Mesh'
171void Mesh::parseMesh(std::istream& fin)
172{
173    char buf[256];
174    vector<string> token;
175
176    unsigned int nVertices = 0, nFaces = 0;
177
178    //cerr << "*** Mesh\n";
179    while (fin.getline(buf, sizeof(buf))) {
180
181        // Tokenize
182        token.clear();
183        tokenize(buf, token);
184        if (token.size() == 0)
185            continue;
186
187        //cerr << "*** Mesh token=" << token[0] << endl;
188        if (strrchr(buf, '}') != 0) {
189            break;
190        }
191        else if (strrchr(buf, '{') != 0) {
192            if (token[0] == "MeshMaterialList")
193                parseMeshMaterialList(fin);
194            else if (token[0] == "MeshNormals")
195                parseMeshNormals(fin);
196            else if (token[0] == "MeshTextureCoords")
197                readMeshTexCoords(fin);
198            else {
199                //cerr << "!!! Mesh: Begin section " << token[0] << endl;
200                _obj->parseSection(fin);
201            }
202        }
203        else if (nVertices == 0) {
204            // Vertices
205            nVertices = atoi(token[0].c_str());
206            readVector(fin, _vertices, nVertices);
207
208            if (nVertices != _vertices.size())
209            {
210                OSG_WARN << "DirectX loader: Error reading vertices; " << _vertices.size() << " instead of " << nVertices << endl;
211            }
212        }
213        else if (nFaces == 0) {
214            // Faces
215            nFaces = atoi(token[0].c_str());
216            readMeshFace(fin, _faces, nFaces);
217
218            if (nFaces != _faces.size())
219            {
220                OSG_WARN << "DirectX loader: Error reading mesh; " << _faces.size() << " instead of " << nFaces << endl;
221            }
222        }
223        else
224            OSG_INFO << "!!! " << buf << endl;
225    }
226}
227
228// Parse 'MeshMaterialList'
229void Mesh::parseMeshMaterialList(std::istream& fin)
230{
231    char buf[256];
232    vector<string> token;
233
234    unsigned int nMaterials = 0, nFaceIndices = 0;
235
236    //cerr << "*** MeshMaterialList\n";
237    while (fin.getline(buf, sizeof(buf))) {
238
239        // Tokenize
240        token.clear();
241        tokenize(buf, token);
242        if (token.size() == 0)
243            continue;
244
245        // check for "{ <material name> }" for a
246        // material which was declared globally
247        string materialName = token[0];
248        // could be given as "{ someName }" which more than 1 tokens
249        if (materialName == "{" && token.size()>1)
250        {
251            materialName = token[1];
252        }
253        // or could be given as "{someName}" which would be in token[0]
254        else if (materialName.size() > 2 && materialName[0] == '{' && materialName[materialName.size()-1] == '}')
255        {
256            // remove curly brackets
257            materialName = materialName.substr(1, materialName.size()-2);
258        }
259        Material * material = _obj->findMaterial(materialName);
260
261        if (material)
262        {
263            _materialList->material.push_back(*material);
264            continue;
265        }
266
267        if (strrchr(buf, '}') != 0)
268            break;
269        else if (strrchr(buf, '{') != 0) {
270            if (token[0] == "Material") {
271                Material mm;
272                parseMaterial(fin, mm);
273                _materialList->material.push_back(mm);
274                //cerr << "num mat=" << _materialList->material.size() << endl;
275            }
276            else {
277                //cerr << "!!! MeshMaterialList: Begin section " << token[0] << endl;
278                _obj->parseSection(fin);
279            }
280        }
281        else if (nMaterials == 0) {
282            // Create MeshMaterialList
283            if (!_materialList)
284                _materialList = new MeshMaterialList;
285
286            // Materials
287            nMaterials = atoi(token[0].c_str());
288            //cerr << "expecting num Materials=" << nMaterials << endl;
289        }
290        else if (nFaceIndices == 0) {
291            // Face indices
292            nFaceIndices = atoi(token[0].c_str());
293            readIndexList(fin, _materialList->faceIndices, nFaceIndices);
294
295            if (nFaceIndices != _materialList->faceIndices.size())
296            {
297                OSG_WARN << "DirectX loader: Error reading face indices; " << nFaceIndices << " instead of " << _materialList->faceIndices.size() << endl;
298            }
299        }
300    }
301
302    if (nMaterials != _materialList->material.size())
303    {
304        OSG_WARN << "DirectX loader: Error reading material list; " << nMaterials << " instead of " << _materialList->material.size() << endl;
305    }
306}
307
308// Parse 'MeshNormals'
309void Mesh::parseMeshNormals(std::istream& fin)
310{
311    char buf[256];
312    vector<string> token;
313
314    unsigned int nNormals = 0, nFaceNormals = 0;
315
316    //cerr << "*** MeshNormals\n";
317    while (fin.getline(buf, sizeof(buf))) {
318
319        // Tokenize
320        token.clear();
321        tokenize(buf, token);
322        if (token.size() == 0)
323            continue;
324
325        if (strrchr(buf, '}') != 0)
326            break;
327        else if (nNormals == 0) {
328            // Create MeshNormals
329            if (!_normals)
330                _normals = new MeshNormals;
331
332            // Normals
333            nNormals = atoi(token[0].c_str());
334            readVector(fin, _normals->normals, nNormals);
335
336            if (nNormals != _normals->normals.size())
337            {
338                OSG_WARN << "DirectX loader: Error reading normals; " << nNormals << " instead of " << _normals->normals.size() << endl;
339            }
340
341#define NORMALIZE_NORMALS
342#ifdef NORMALIZE_NORMALS
343            for (unsigned int i = 0; i < _normals->normals.size(); i++)
344                _normals->normals[i].normalize();
345#endif
346        }
347        else if (nFaceNormals == 0) {
348            // Face normals
349            nFaceNormals = atoi(token[0].c_str());
350            readMeshFace(fin, _normals->faceNormals, nFaceNormals);
351
352            if (nFaceNormals != _normals->faceNormals.size())
353            {
354                OSG_WARN << "DirectX loader: Error reading face normals; " << nFaceNormals << " instead of " << _normals->faceNormals.size() << endl;
355            }
356        }
357    }
358}
359
360// Read 'MeshTextureCoords'
361void Mesh::readMeshTexCoords(std::istream& fin)
362{
363    char buf[256];
364    vector<string> token;
365
366    unsigned int nTextureCoords = 0;
367
368    //cerr << "*** MeshTextureCoords\n";
369    while (fin.getline(buf, sizeof(buf))) {
370
371        // Tokenize
372        token.clear();
373        tokenize(buf, token);
374        if (token.size() == 0)
375            continue;
376
377        if (strrchr(buf, '}') != 0)
378            break;
379
380        // Create MeshTextureCoords
381        if (!_textureCoords)
382            _textureCoords = new MeshTextureCoords;
383
384        // Texture coords
385        nTextureCoords = atoi(token[0].c_str());
386        readCoords2d(fin, *_textureCoords, nTextureCoords);
387
388        if (nTextureCoords != _textureCoords->size())
389        {
390            OSG_INFO << "DirectX loader: Error reading texcoords; " << _textureCoords->size() << " instead of " << nTextureCoords << endl;
391            delete _textureCoords;
392            _textureCoords = 0;
393        }
394    }
395}
Note: See TracBrowser for help on using the browser.