Merge lp:~glmark2-dev/glmark2/obj-update into lp:glmark2/2011.11

Proposed by Jesse Barker
Status: Merged
Merged at revision: 260
Proposed branch: lp:~glmark2-dev/glmark2/obj-update
Merge into: lp:glmark2/2011.11
Diff against target: 730 lines (+296/-180)
8 files modified
src/model.cpp (+262/-168)
src/model.h (+17/-4)
src/scene-build.cpp (+2/-1)
src/scene-bump.cpp (+6/-3)
src/scene-refract.cpp (+2/-1)
src/scene-shading.cpp (+2/-1)
src/scene-shadow.cpp (+2/-1)
src/scene-texture.cpp (+3/-1)
To merge this branch: bzr merge lp:~glmark2-dev/glmark2/obj-update
Reviewer Review Type Date Requested Status
Alexandros Frantzis Approve
Review via email: mp+145746@code.launchpad.net

Description of the change

Model: This adds "more complete" handling of the .obj file format for models. In particular, these changes add better support for arbitrary whitespace between attribute elements, and add support for vertex normals and texcoords. These additional attributes also have potentially unique indices in the face descriptions, so the definition of a Face within the Model object needed to change (which caused some changes in the conversion of a model to a mesh). There are many other features of this file format that could be added, but it would be best to visit those upon encountering a compelling enough model.

To post a comment you must log in.
Revision history for this message
Alexandros Frantzis (afrantzis) wrote :

Looks good overall.

A nitpick (not worth blocking on, but nice to have fixed):

I am not sure we need Model::needNormals(), since calculate_normals() checks for that already. If we need to make it more explicit that calculate_normals() may or may not actually perform the calculation, it think it would be cleaner to rename it to calculate_normals_if_needed().

review: Approve
Revision history for this message
Jesse Barker (jesse-barker) wrote :

I was conflicted about that, but wanted to be consistent with the texcoord attribute, and also wanted to leave the interface in place to allow for the future possibility of offering different methods of calculating both attributes if they weren't provided with the model (of course, that would require some additional internal changes, so perhaps it's not worth it after all). The interfaces allow the scene to decide which option to use, but I could still see taking it out and worrying about it later.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/model.cpp'
2--- src/model.cpp 2012-07-05 17:22:16 +0000
3+++ src/model.cpp 2013-01-30 23:17:24 +0000
4@@ -35,6 +35,7 @@
5
6 using std::string;
7 using std::vector;
8+using LibMatrix::vec2;
9 using LibMatrix::vec3;
10 using LibMatrix::uvec3;
11
12@@ -108,50 +109,65 @@
13 int p_pos, int n_pos, int t_pos,
14 int nt_pos, int nb_pos)
15 {
16- size_t face_count = object.faces.size();
17-
18- for(size_t i = 0; i < 3 * face_count; i += 3)
19+ for (vector<Face>::const_iterator faceIt = object.faces.begin();
20+ faceIt != object.faces.end();
21+ faceIt++)
22 {
23- const Face &face = object.faces[i / 3];
24- const Vertex &a = object.vertices[face.a];
25- const Vertex &b = object.vertices[face.b];
26- const Vertex &c = object.vertices[face.c];
27-
28- mesh.next_vertex();
29- if (p_pos >= 0)
30- mesh.set_attrib(p_pos, a.v);
31- if (n_pos >= 0)
32- mesh.set_attrib(n_pos, a.n);
33- if (t_pos >= 0)
34- mesh.set_attrib(t_pos, a.t);
35- if (nt_pos >= 0)
36- mesh.set_attrib(nt_pos, a.nt);
37- if (nb_pos >= 0)
38- mesh.set_attrib(nb_pos, a.nb);
39-
40- mesh.next_vertex();
41- if (p_pos >= 0)
42- mesh.set_attrib(p_pos, b.v);
43- if (n_pos >= 0)
44- mesh.set_attrib(n_pos, b.n);
45- if (t_pos >= 0)
46- mesh.set_attrib(t_pos, b.t);
47- if (nt_pos >= 0)
48- mesh.set_attrib(nt_pos, b.nt);
49- if (nb_pos >= 0)
50- mesh.set_attrib(nb_pos, b.nb);
51-
52- mesh.next_vertex();
53- if (p_pos >= 0)
54- mesh.set_attrib(p_pos, c.v);
55- if (n_pos >= 0)
56- mesh.set_attrib(n_pos, c.n);
57- if (t_pos >= 0)
58- mesh.set_attrib(t_pos, c.t);
59- if (nt_pos >= 0)
60- mesh.set_attrib(nt_pos, c.nt);
61- if (nb_pos >= 0)
62- mesh.set_attrib(nb_pos, c.nb);
63+ // In some model file formats (OBJ in particular), the face description
64+ // may contain separate indices per-attribute. So, we need to allow
65+ // for this when adding each vertex attribute to the mesh.
66+ const Face &face = *faceIt;
67+ const Vertex &v1 = object.vertices[face.v.x()];
68+ const Vertex &v2 = object.vertices[face.v.y()];
69+ const Vertex &v3 = object.vertices[face.v.z()];
70+
71+ bool separate_t(face.which & Face::OBJ_FACE_T);
72+
73+ const Vertex &t1 = object.vertices[separate_t ? face.t.x() : face.v.x()];
74+ const Vertex &t2 = object.vertices[separate_t ? face.t.y() : face.v.y()];
75+ const Vertex &t3 = object.vertices[separate_t ? face.t.z() : face.v.z()];
76+
77+ bool separate_n(face.which & Face::OBJ_FACE_N);
78+
79+ const Vertex &n1 = object.vertices[separate_n ? face.n.x() : face.v.x()];
80+ const Vertex &n2 = object.vertices[separate_n ? face.n.y() : face.v.y()];
81+ const Vertex &n3 = object.vertices[separate_n ? face.n.z() : face.v.z()];
82+
83+ mesh.next_vertex();
84+ if (p_pos >= 0)
85+ mesh.set_attrib(p_pos, v1.v);
86+ if (n_pos >= 0)
87+ mesh.set_attrib(n_pos, n1.n);
88+ if (t_pos >= 0)
89+ mesh.set_attrib(t_pos, t1.t);
90+ if (nt_pos >= 0)
91+ mesh.set_attrib(nt_pos, v1.nt);
92+ if (nb_pos >= 0)
93+ mesh.set_attrib(nb_pos, v1.nb);
94+
95+ mesh.next_vertex();
96+ if (p_pos >= 0)
97+ mesh.set_attrib(p_pos, v2.v);
98+ if (n_pos >= 0)
99+ mesh.set_attrib(n_pos, n2.n);
100+ if (t_pos >= 0)
101+ mesh.set_attrib(t_pos, t2.t);
102+ if (nt_pos >= 0)
103+ mesh.set_attrib(nt_pos, v2.nt);
104+ if (nb_pos >= 0)
105+ mesh.set_attrib(nb_pos, v2.nb);
106+
107+ mesh.next_vertex();
108+ if (p_pos >= 0)
109+ mesh.set_attrib(p_pos, v3.v);
110+ if (n_pos >= 0)
111+ mesh.set_attrib(n_pos, n3.n);
112+ if (t_pos >= 0)
113+ mesh.set_attrib(t_pos, t3.t);
114+ if (nt_pos >= 0)
115+ mesh.set_attrib(nt_pos, v3.nt);
116+ if (nb_pos >= 0)
117+ mesh.set_attrib(nb_pos, v3.nb);
118 }
119 }
120
121@@ -225,6 +241,9 @@
122 void
123 Model::calculate_texcoords()
124 {
125+ if (gotTexcoords_)
126+ return;
127+
128 // Since the model didn't come with texcoords, and we don't actually know
129 // if it came with normals, either, we'll use positional spherical mapping
130 // to generate texcoords for the model. See:
131@@ -248,6 +267,8 @@
132 curVertex.t.y(asinf(vnorm.y()) / M_PI + 0.5);
133 }
134 }
135+
136+ gotTexcoords_ = true;
137 }
138
139 /**
140@@ -256,6 +277,9 @@
141 void
142 Model::calculate_normals()
143 {
144+ if (gotNormals_)
145+ return;
146+
147 LibMatrix::vec3 n;
148
149 for (std::vector<Object>::iterator iter = objects_.begin();
150@@ -269,9 +293,9 @@
151 f_iter++)
152 {
153 const Face &face = *f_iter;
154- Vertex &a = object.vertices[face.a];
155- Vertex &b = object.vertices[face.b];
156- Vertex &c = object.vertices[face.c];
157+ Vertex &a = object.vertices[face.v.x()];
158+ Vertex &b = object.vertices[face.v.y()];
159+ Vertex &c = object.vertices[face.v.z()];
160
161 /* Calculate normal */
162 n = LibMatrix::vec3::cross(b.v - a.v, c.v - a.v);
163@@ -318,8 +342,9 @@
164 v.nt.normalize();
165 v.nb.normalize();
166 }
167-
168 }
169+
170+ gotNormals_ = true;
171 }
172
173 /**
174@@ -425,9 +450,10 @@
175 for (uint16_t i = 0; i < qty; i++) {
176 float f[3];
177 read_or_fail(input_file, f, sizeof(float) * 3);
178- object->vertices[i].v.x(f[0]);
179- object->vertices[i].v.y(f[1]);
180- object->vertices[i].v.z(f[2]);
181+ vec3& vertex = object->vertices[i].v;
182+ vertex.x(f[0]);
183+ vertex.y(f[1]);
184+ vertex.z(f[2]);
185 }
186 }
187 break;
188@@ -445,10 +471,12 @@
189 read_or_fail(input_file, &qty, sizeof(uint16_t));
190 object->faces.resize(qty);
191 for (uint16_t i = 0; i < qty; i++) {
192- read_or_fail(input_file, &object->faces[i].a, sizeof(uint16_t));
193- read_or_fail(input_file, &object->faces[i].b, sizeof(uint16_t));
194- read_or_fail(input_file, &object->faces[i].c, sizeof(uint16_t));
195- read_or_fail(input_file, &object->faces[i].face_flags, sizeof(uint16_t));
196+ uint16_t f[4];
197+ read_or_fail(input_file, f, sizeof(uint16_t) * 4);
198+ uvec3& face = object->faces[i].v;
199+ face.x(f[0]);
200+ face.y(f[1]);
201+ face.z(f[2]);
202 }
203 }
204 break;
205@@ -467,8 +495,9 @@
206 for (uint16_t i = 0; i < qty; i++) {
207 float f[2];
208 read_or_fail(input_file, f, sizeof(float) * 2);
209- object->vertices[i].t.x(f[0]);
210- object->vertices[i].t.y(f[1]);
211+ vec2& texcoord = object->vertices[i].t;
212+ texcoord.x(f[0]);
213+ texcoord.y(f[1]);
214 }
215 }
216 gotTexcoords_ = true;
217@@ -500,118 +529,144 @@
218 return true;
219 }
220
221-/**
222- * Parse vec3 values from an OBJ file.
223+
224+const unsigned int Model::Face::OBJ_FACE_V = 0x1;
225+const unsigned int Model::Face::OBJ_FACE_T = 0x2;
226+const unsigned int Model::Face::OBJ_FACE_N = 0x4;
227+
228+/**
229+ * Parse 2-element vertex attribute from an OBJ file.
230+ *
231+ * @param source the source line to parse
232+ * @param v the vec2 to populate
233+ */
234+void
235+Model::obj_get_attrib(const string& source, vec2& v)
236+{
237+ // Our attribs are whitespace separated, so use a fuzzy split.
238+ vector<string> elements;
239+ Util::split(source, ' ', elements, Util::SplitModeFuzzy);
240+
241+ // Find the first value...
242+ float x = Util::fromString<float>(elements[0]);
243+ // And the second value (there might be a third, but we don't care)...
244+ float y = Util::fromString<float>(elements[1]);
245+ v.x(x);
246+ v.y(y);
247+}
248+
249+/**
250+ * Parse 3-element vertex attribute from an OBJ file.
251 *
252 * @param source the source line to parse
253 * @param v the vec3 to populate
254 */
255-static void
256-obj_get_values(const string& source, vec3& v)
257+void
258+Model::obj_get_attrib(const string& source, vec3& v)
259 {
260- // Skip the definition type...
261- string::size_type endPos = source.find(" ");
262- string::size_type startPos(0);
263- if (endPos == string::npos)
264- {
265- Log::error("Bad element '%s'\n", source.c_str());
266- return;
267- }
268+ // Our attribs are whitespace separated, so use a fuzzy split.
269+ vector<string> elements;
270+ Util::split(source, ' ', elements, Util::SplitModeFuzzy);
271+
272 // Find the first value...
273- startPos = endPos + 1;
274- endPos = source.find(" ", startPos);
275- if (endPos == string::npos)
276- {
277- Log::error("Bad element '%s'\n", source.c_str());
278- return;
279- }
280- string::size_type numChars(endPos - startPos);
281- string xs(source, startPos, numChars);
282- float x = Util::fromString<float>(xs);
283+ float x = Util::fromString<float>(elements[0]);
284 // Then the second value...
285- startPos = endPos + 1;
286- endPos = source.find(" ", startPos);
287- if (endPos == string::npos)
288- {
289- Log::error("Bad element '%s'\n", source.c_str());
290- return;
291- }
292- numChars = endPos - startPos;
293- string ys(source, startPos, numChars);
294- float y = Util::fromString<float>(ys);
295+ float y = Util::fromString<float>(elements[1]);
296 // And the third value (there might be a fourth, but we don't care)...
297- startPos = endPos + 1;
298- endPos = source.find(" ", startPos);
299- if (endPos == string::npos)
300- {
301- numChars = endPos;
302- }
303- else
304- {
305- numChars = endPos - startPos;
306- }
307- string zs(source, startPos, endPos - startPos);
308- float z = Util::fromString<float>(zs);
309+ float z = Util::fromString<float>(elements[2]);
310 v.x(x);
311 v.y(y);
312 v.z(z);
313 }
314
315+
316+void
317+Model::obj_face_get_index(const string& tuple, unsigned int& which,
318+ unsigned int& v, unsigned int& t, unsigned int& n)
319+{
320+ // We can use a normal split here as syntax requires no spaces around
321+ // the '/' delimiter for a face description.
322+ vector<string> elements;
323+ Util::split(tuple, '/', elements, Util::SplitModeNormal);
324+
325+ if (elements.empty())
326+ {
327+ which = 0;
328+ return;
329+ }
330+
331+ which = Face::OBJ_FACE_V;
332+ v = Util::fromString<unsigned int>(elements[0]);
333+
334+ unsigned int num_elements = elements.size();
335+
336+ if (num_elements > 1 && !elements[1].empty())
337+ {
338+ which |= Face::OBJ_FACE_T;
339+ t = Util::fromString<unsigned int>(elements[1]);
340+ }
341+
342+ if (num_elements > 2 && !elements[2].empty())
343+ {
344+ which |= Face::OBJ_FACE_N;
345+ n = Util::fromString<unsigned int>(elements[2]);
346+ }
347+
348+ return;
349+}
350+
351 /**
352- * Parse uvec3 values from an OBJ file.
353+ * Parse a face description from an OBJ file.
354+ * Faces always specify position, but optionally can also contain separate
355+ * indices for texcoords and normals.
356 *
357 * @param source the source line to parse
358 * @param v the uvec3 to populate
359 */
360-static void
361-obj_get_values(const string& source, uvec3& v)
362+void
363+Model::obj_get_face(const string& source, Face& f)
364 {
365- // Skip the definition type...
366- string::size_type endPos = source.find(" ");
367- string::size_type startPos(0);
368- if (endPos == string::npos)
369- {
370- Log::error("Bad element '%s'\n", source.c_str());
371- return;
372- }
373+ // Our indices are whitespace separated, so use a fuzzy split.
374+ vector<string> elements;
375+ Util::split(source, ' ', elements, Util::SplitModeFuzzy);
376+
377 // Find the first value...
378- startPos = endPos + 1;
379- endPos = source.find(" ", startPos);
380- if (endPos == string::npos)
381- {
382- Log::error("Bad element '%s'\n", source.c_str());
383- return;
384- }
385- string::size_type numChars(endPos - startPos);
386- string xs(source, startPos, numChars);
387- unsigned int x = Util::fromString<unsigned int>(xs);
388+ unsigned int which(0);
389+ unsigned int vx(0);
390+ unsigned int tx(0);
391+ unsigned int nx(0);
392+ obj_face_get_index(elements[0], which, vx, tx, nx);
393+
394 // Then the second value...
395- startPos = endPos+1;
396- endPos = source.find(" ", startPos);
397- if (endPos == string::npos)
398- {
399- Log::error("Bad element '%s'\n", source.c_str());
400- return;
401- }
402- numChars = endPos - startPos;
403- string ys(source, startPos, numChars);
404- unsigned int y = Util::fromString<unsigned int>(ys);
405+ unsigned int vy(0);
406+ unsigned int ty(0);
407+ unsigned int ny(0);
408+ obj_face_get_index(elements[1], which, vy, ty, ny);
409+
410 // And the third value (there might be a fourth, but we don't care)...
411- startPos = endPos + 1;
412- endPos = source.find(" ", startPos);
413- if (endPos == string::npos)
414- {
415- numChars = endPos;
416- }
417- else
418- {
419- numChars = endPos - startPos;
420- }
421- string zs(source, startPos, numChars);
422- unsigned int z = Util::fromString<unsigned int>(zs);
423- v.x(x);
424- v.y(y);
425- v.z(z);
426+ unsigned int vz(0);
427+ unsigned int tz(0);
428+ unsigned int nz(0);
429+ obj_face_get_index(elements[2], which, vz, tz, nz);
430+
431+ // OBJ models start absoluted indices at '1', so subtract to re-base to
432+ // '0'. We do not handle relative indexing (negative indices).
433+ f.which = which;
434+ f.v.x(vx - 1);
435+ f.v.y(vy - 1);
436+ f.v.z(vz - 1);
437+ if (which & Face::OBJ_FACE_T)
438+ {
439+ f.t.x(tx - 1);
440+ f.t.y(ty - 1);
441+ f.t.z(tz - 1);
442+ }
443+ if (which & Face::OBJ_FACE_N)
444+ {
445+ f.n.x(nx - 1);
446+ f.n.y(ny - 1);
447+ f.n.z(nz - 1);
448+ }
449 }
450
451 /**
452@@ -642,59 +697,98 @@
453 }
454
455 // Give ourselves an object to populate.
456- objects_.push_back(Object(filename));
457+ objects_.push_back(Object(string()));
458 Object& object(objects_.back());
459
460+ static const string object_definition("o");
461 static const string vertex_definition("v");
462 static const string normal_definition("vn");
463 static const string texcoord_definition("vt");
464 static const string face_definition("f");
465+ vector<vec3> positions;
466+ vector<vec3> normals;
467+ vector<vec2> texcoords;
468 for (vector<string>::const_iterator lineIt = sourceVec.begin();
469 lineIt != sourceVec.end();
470 lineIt++)
471 {
472 const string& curSrc = *lineIt;
473 // Is it a vertex attribute, a face description, comment or other?
474- // We only care about the first two, we ignore comments, object names,
475- // group names, smoothing groups, etc.
476+ // We only care about the first two, we ignore comments, group names,
477+ // smoothing groups, etc.
478 string::size_type startPos(0);
479 string::size_type spacePos = curSrc.find(" ", startPos);
480- string definitionType(curSrc, startPos, spacePos - startPos);
481+ string::size_type num_chars(string::npos);
482+ string definition;
483+ if (spacePos != string::npos)
484+ {
485+ // Could be arbitrary whitespace between description type and
486+ // the data
487+ string::size_type defPos = curSrc.find_first_not_of(' ', spacePos);
488+ definition = string(curSrc, defPos);
489+ num_chars = spacePos - startPos;
490+ }
491+ string definitionType(curSrc, startPos, num_chars);
492+
493 if (definitionType == vertex_definition)
494 {
495- Vertex v;
496- obj_get_values(curSrc, v.v);
497- object.vertices.push_back(v);
498+ vec3 p;
499+ obj_get_attrib(definition, p);
500+ positions.push_back(p);
501 }
502 else if (definitionType == normal_definition)
503 {
504- // If we encounter an OBJ model with normals, we can update this
505- // to update object.vertices.n directly
506- Log::debug("We got a normal...\n");
507+ vec3 n;
508+ obj_get_attrib(definition, n);
509+ normals.push_back(n);
510 }
511 else if (definitionType == texcoord_definition)
512 {
513- // If we encounter an OBJ model with normals, we can update this
514- // to update object.vertices.t directly
515- Log::debug("We got a texcoord...\n");
516+ vec2 t;
517+ obj_get_attrib(definition, t);
518+ texcoords.push_back(t);
519 }
520 else if (definitionType == face_definition)
521 {
522- uvec3 v;
523- obj_get_values(curSrc, v);
524 Face f;
525- // OBJ models index from '1'.
526- f.a = v.x() - 1;
527- f.b = v.y() - 1;
528- f.c = v.z() - 1;
529+ obj_get_face(definition, f);
530 object.faces.push_back(f);
531 }
532- }
533+ else if (definitionType == object_definition)
534+ {
535+ object.name = definition;
536+ }
537+ }
538+
539+ if (!texcoords.empty())
540+ {
541+ gotTexcoords_ = true;
542+ }
543+ if (!normals.empty())
544+ {
545+ gotNormals_ = true;
546+ }
547+ unsigned int numVertices = positions.size();
548+ object.vertices.resize(numVertices);
549+ for (unsigned int i = 0; i < numVertices; i++)
550+ {
551+ Vertex& curVertex = object.vertices[i];
552+ curVertex.v = positions[i];
553+ if (gotTexcoords_)
554+ {
555+ curVertex.t = texcoords[i];
556+ }
557+ if (gotNormals_)
558+ {
559+ curVertex.n = normals[i];
560+ }
561+ }
562+
563 // Compute bounding box for perspective projection
564 compute_bounding_box(object);
565
566- Log::debug("Object populated with %u vertices and %u faces.\n",
567- object.vertices.size(), object.faces.size());
568+ Log::debug("Object name: %s Vertex count: %u Face count: %u\n",
569+ object.name.empty() ? "(none)" : object.name.c_str(), object.vertices.size(), object.faces.size());
570 return true;
571 }
572
573
574=== modified file 'src/model.h'
575--- src/model.h 2012-07-27 09:11:50 +0000
576+++ src/model.h 2013-01-30 23:17:24 +0000
577@@ -78,12 +78,13 @@
578 AttribTypeCustom
579 } AttribType;
580
581- Model() : gotTexcoords_(false) {}
582+ Model() : gotTexcoords_(false), gotNormals_(false) {}
583 ~Model() {}
584
585 bool load(const std::string& name);
586
587 bool needTexcoords() const { return !gotTexcoords_; }
588+ bool needNormals() const { return !gotNormals_; }
589 void calculate_texcoords();
590 void calculate_normals();
591 void convert_to_mesh(Mesh &mesh);
592@@ -93,11 +94,18 @@
593 const LibMatrix::vec3& maxVec() const { return maxVec_; }
594 static const ModelMap& find_models();
595 private:
596- // If the model we loaded contained texcoord data...
597+ // If the model we loaded contained texcoord or normal data...
598 bool gotTexcoords_;
599+ bool gotNormals_;
600+
601 struct Face {
602- uint32_t a, b, c;
603- uint16_t face_flags;
604+ LibMatrix::uvec3 v;
605+ LibMatrix::uvec3 n;
606+ LibMatrix::uvec3 t;
607+ unsigned int which; // mask of which values are relevant for this face.
608+ static const unsigned int OBJ_FACE_V;
609+ static const unsigned int OBJ_FACE_T;
610+ static const unsigned int OBJ_FACE_N;
611 };
612
613 struct Vertex {
614@@ -120,6 +128,11 @@
615 int nt_pos, int nb_pos);
616 bool load_3ds(const std::string &filename);
617 bool load_obj(const std::string &filename);
618+ void obj_get_attrib(const std::string& description, LibMatrix::vec2& v);
619+ void obj_get_attrib(const std::string& description, LibMatrix::vec3& v);
620+ void obj_face_get_index(const std::string& tuple, unsigned int& which,
621+ unsigned int& v, unsigned int& t, unsigned int& n);
622+ void obj_get_face(const std::string& description, Face& face);
623
624 // For vertices of the bounding box for this model.
625 void compute_bounding_box(const Object& object);
626
627=== modified file 'src/scene-build.cpp'
628--- src/scene-build.cpp 2012-08-15 09:45:06 +0000
629+++ src/scene-build.cpp 2013-01-30 23:17:24 +0000
630@@ -141,7 +141,8 @@
631 orientationVec_ = vec3(0.0, 1.0, 0.0);
632 }
633
634- model.calculate_normals();
635+ if (model.needNormals())
636+ model.calculate_normals();
637
638 /* Tell the converter that we only care about position and normal attributes */
639 std::vector<std::pair<Model::AttribType, int> > attribs;
640
641=== modified file 'src/scene-bump.cpp'
642--- src/scene-bump.cpp 2012-08-15 09:45:06 +0000
643+++ src/scene-bump.cpp 2013-01-30 23:17:24 +0000
644@@ -80,7 +80,8 @@
645 if(!model.load(poly_filename))
646 return false;
647
648- model.calculate_normals();
649+ if (model.needNormals())
650+ model.calculate_normals();
651
652 /* Tell the converter that we only care about position and normal attributes */
653 std::vector<std::pair<Model::AttribType, int> > attribs;
654@@ -177,7 +178,8 @@
655 if(!model.load("asteroid-low"))
656 return false;
657
658- model.calculate_normals();
659+ if (model.needNormals())
660+ model.calculate_normals();
661
662 /* Calculate the half vector */
663 LibMatrix::vec3 halfVector(lightPosition.x(), lightPosition.y(), lightPosition.z());
664@@ -234,7 +236,8 @@
665 if(!model.load("asteroid-low"))
666 return false;
667
668- model.calculate_normals();
669+ if (model.needNormals())
670+ model.calculate_normals();
671
672 /* Calculate the half vector */
673 LibMatrix::vec3 halfVector(lightPosition.x(), lightPosition.y(), lightPosition.z());
674
675=== modified file 'src/scene-refract.cpp'
676--- src/scene-refract.cpp 2012-12-15 09:46:12 +0000
677+++ src/scene-refract.cpp 2013-01-30 23:17:24 +0000
678@@ -322,7 +322,8 @@
679 orientationVec_ = vec3(0.0, 1.0, 0.0);
680 }
681
682- model.calculate_normals();
683+ if (model.needNormals())
684+ model.calculate_normals();
685
686 // Mesh setup
687 vector<std::pair<Model::AttribType, int> > attribs;
688
689=== modified file 'src/scene-shading.cpp'
690--- src/scene-shading.cpp 2012-08-15 09:45:06 +0000
691+++ src/scene-shading.cpp 2013-01-30 23:17:24 +0000
692@@ -220,7 +220,8 @@
693 orientationVec_ = vec3(0.0, 1.0, 0.0);
694 }
695
696- model.calculate_normals();
697+ if (model.needNormals())
698+ model.calculate_normals();
699
700 /* Tell the converter that we only care about position and normal attributes */
701 std::vector<std::pair<Model::AttribType, int> > attribs;
702
703=== modified file 'src/scene-shadow.cpp'
704--- src/scene-shadow.cpp 2012-12-17 16:08:05 +0000
705+++ src/scene-shadow.cpp 2013-01-30 23:17:24 +0000
706@@ -324,7 +324,8 @@
707 return false;
708 }
709
710- model.calculate_normals();
711+ if (model.needNormals())
712+ model.calculate_normals();
713
714 // Mesh setup
715 vector<std::pair<Model::AttribType, int> > attribs;
716
717=== modified file 'src/scene-texture.cpp'
718--- src/scene-texture.cpp 2012-08-15 09:45:06 +0000
719+++ src/scene-texture.cpp 2013-01-30 23:17:24 +0000
720@@ -208,7 +208,9 @@
721
722 if (model.needTexcoords())
723 model.calculate_texcoords();
724- model.calculate_normals();
725+ if (model.needNormals())
726+ model.calculate_normals();
727+
728 // Tell the converter which attributes we care about
729 std::vector<std::pair<Model::AttribType, int> > attribs;
730 attribs.push_back(std::pair<Model::AttribType, int>(Model::AttribTypePosition, 3));

Subscribers

People subscribed via source and target branches

to all changes: