changed copyright years in source files
[fegdk.git] / core / code / video / f_model.cpp
blob25f9d389f4939db5f3dee0cdb2ad75a1f769ea38
1 /*
2 fegdk: FE Game Development Kit
3 Copyright (C) 2001-2008 Alexey "waker" Yakovenko
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the Free
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 Alexey Yakovenko
20 waker@users.sourceforge.net
23 #include "pch.h"
24 #include "f_model.h"
25 #include "f_engine.h"
26 #include "f_error.h"
27 #include "f_resourcemgr.h"
28 #include "f_basetexture.h"
29 #include "f_material.h"
30 #include "f_modeldata.h"
31 #include "f_lightsource.h"
33 namespace fe
36 class mtlBlock : public baseObject
38 protected:
39 std::vector <materialPtr> mMtlList;
41 public:
42 void add (const materialPtr &mtl) { mMtlList.push_back (mtl); }
43 int numMtls (void) const { return (int)mMtlList.size (); }
44 materialPtr getMtl (int i) { return mMtlList[i]; }
45 void load( file *f )
47 uint32 sp;
48 f->readUINT32 (&sp, 1);
49 if (!sp)
50 return;
51 mMtlList.resize (sp);
52 for (uint32 i = 0; i < sp; i++)
54 uchar ln;
55 f->read (&ln, 1);
56 char *str = new char[ln+1];
57 f->read (str, ln);
58 str[ln]=0;
59 materialPtr m = g_engine->getResourceMgr ()->createMaterial (str);
60 mMtlList[i] = m;
61 delete[] str;
67 model::model (void)
69 /* mbLightmaps = 0;
70 mbTangents = 0;
71 mbColors = 0;
73 memset (&mTris, 0, sizeof (mTris));*/
76 sceneObject* model::load (const char *fname)
78 mbValid = true;
79 if (!fname)
81 mbValid = false;
82 return NULL;
85 mName = fname;
87 #if 0
88 bool noscript = false;
89 // check if we got bmdl
90 if (strstr (fname, ".bmdl"))
92 // yes, just load it
93 noscript = true;
95 else
97 // no, try loading script
98 try {
99 charParser p(g_engine->getFileSystem (), fname);
100 // file must contain only model def, and nothing more (no name, nothing)
101 return load (p);
103 catch (parserException e)
105 if (e == parserException::FILE_NOT_FOUND)
106 noscript = true;
107 else if (e != parserException::END_OF_FILE)
109 fprintf (stderr, "ERROR: failed to load script for model %s,\nerrors: %s", fname, cStr (e).c_str ());
110 mbValid = false;
111 return NULL;
115 if (noscript)
116 #endif
118 file *f = g_engine->getFileSystem ()->openFile (fname, FS_MODE_READ);
119 return load (f);
123 #if 0
124 model::model (charParser &parser, const char *fname, model *parent)
126 mbLightmaps = 0;
127 mbTangents = 0;
128 mbColors = 0;
129 memset (&mTris, 0, sizeof (mTris));
130 try {
131 charParser p(g_engine->getFileSystem (), fname);
132 // file must contain only model def, and nothing more (no name, nothing)
133 load (p);
135 catch (parserException e)
137 if (e != parserException::END_OF_FILE)
138 throw genericError ("failed to load script for model %s,\nerrors: %s",
139 fname, cStr (e).c_str ());
143 model::model (const char *name, model *parent, const matrix4 &mtx, const std::vector <drawVertex_t> &verts, std::vector <ushort> &inds, const std::vector <modelSubset_t> &subs, const std::vector <materialPtr> &mtls)
145 mName = name;
146 mbLightmaps = 0;
147 mbTangents = 0;
148 mbColors = 0;
149 memset (&mTris, 0, sizeof (mTris));
150 mRelativeMatrix = mtx;
151 mWorldMatrix = mpParentObject ? mRelativeMatrix * mpParentObject->getWorldMatrix() : mRelativeMatrix;
153 // init surfaces
154 mSurfaces = subs;
155 size_t nsubs = subs.size ();
156 for (size_t s = 0; s < nsubs; s++)
158 mSurfaces[s].tris = &mTris;
161 // init tris
162 mTris.numVerts = verts.size ();
163 mTris.verts = new drawVertex_t[verts.size ()];
164 memcpy (mTris.verts, &verts.front (), verts.size () * sizeof (drawVertex_t));
165 mTris.numIndexes = inds.size ();
166 mTris.indexes = new ushort[inds.size ()];
167 memcpy (mTris.indexes, &inds.front (), inds.size () * sizeof (ushort));
169 init ();
171 #endif
174 void model::init (void)
176 #if 0 // FIXME: all this should be in mesh data!!
177 // build faceplanes
178 mTris.facePlanes = new plane[mTris.numIndexes/3];
179 for (int i = 0; i < mTris.numIndexes/3; i++)
181 mTris.facePlanes[i].fromPoints (
182 mTris.verts[mTris.indexes[i*3+0]].pos,
183 mTris.verts[mTris.indexes[i*3+1]].pos,
184 mTris.verts[mTris.indexes[i*3+2]].pos);
187 // build silIndexes
188 // FIXME: move to fgp
189 mTris.silIndexes = new ushort[mTris.numIndexes];
190 for (int i = 0; i < mTris.numIndexes; i++)
192 vector3 *v = &mTris.verts[mTris.indexes[i]].pos;
193 size_t j;
194 for (j = 0; j < mTris.numVerts; j++)
196 if (*v == mTris.verts[j].pos)
198 mTris.silIndexes[i] = j;
199 break;
202 assert (j != mTris.numVerts);
205 // silEdges
206 // vertex indexes are from silIndexes
207 // TODO: move to fgp
208 mTris.numSilEdges = 0;
209 mTris.silEdges = new silEdge_t[mTris.numIndexes/3 * 2];
210 for (int i = 0; i < mTris.numIndexes/3; i++)
212 for (int k = 0; k < 3; k++)
214 int v1 = mTris.silIndexes[i * 3 + k];
215 int v2 = mTris.silIndexes[i * 3 + ((k+1)%3)];
217 for (int j = 0; j < mTris.numIndexes/3; j++)
219 if (i == j)
220 continue;
221 for (int n = 0; n < 3; n++)
223 int vv1 = mTris.silIndexes[j * 3 + n];
224 int vv2 = mTris.silIndexes[j * 3 + ((n+1)%3)];
225 if (v1 == vv2 && v2 == vv1)
227 // check for dupe
228 int m;
229 for (m = 0; m < mTris.numSilEdges; m++)
231 if ((mTris.silEdges[m].v1 == v1 && mTris.silEdges[m].v2 == v2)
232 || (mTris.silEdges[m].v1 == v2 && mTris.silEdges[m].v2 == v1))
234 break;
237 if (m == mTris.numSilEdges)
239 // add edge
240 mTris.silEdges[mTris.numSilEdges].f1 = i;
241 mTris.silEdges[mTris.numSilEdges].f2 = j;
242 mTris.silEdges[mTris.numSilEdges].v1 = v1;
243 mTris.silEdges[mTris.numSilEdges].v2 = v2;
244 mTris.numSilEdges++;
253 // each edge forms a quad, which is 2 triangles, which is 6 indexes
254 // in case we're using vertexshader - we will index normal vertex array, and pass
255 // extrusion as one of vertex attributes
256 // in case we're not using vertex shader - we'll make dynamic vertex array,
257 // which will contain entire (extruded) shadow volume
258 mTris.shadowVolumeIndexes = new ushort[mTris.numIndexes/3 * 2 * 6 + mTris.numIndexes];
259 mTris.shadowVerts = new shadowVertex_t[mTris.numVerts * 2];
261 // verts are going in interleaved order, i.e. v0: normal, v1: extruded (to minimize cache misses)
262 for (int i = 0; i < mTris.numVerts; i++)
264 mTris.shadowVerts[i].xyzw = vector4 (mTris.verts[i].pos.x, mTris.verts[i].pos.y, mTris.verts[i].pos.z, 1);
267 mbTangents = true;
269 calcOBB (false);
271 // mpData = new modelData (this);
273 // fill meshData from model
274 #endif
277 model::~model (void)
279 #if 0
280 if (mTris.verts)
281 delete[] mTris.verts;
282 if (mTris.indexes)
283 delete[] mTris.indexes;
284 if (mTris.silIndexes)
285 delete[] mTris.silIndexes;
286 if (mTris.facePlanes)
287 delete[] mTris.facePlanes;
288 if (mTris.silEdges)
289 delete[] mTris.silEdges;
290 // if (mTris.mtlIndexes)
291 // delete[] mTris.mtlIndexes;
292 if (mTris.dupVerts)
293 delete[] mTris.dupVerts;
294 if (mTris.shadowVolumeIndexes)
295 delete[] mTris.shadowVolumeIndexes;
296 if (mTris.shadowVerts)
297 delete[] mTris.shadowVerts;
298 #endif
299 if (mpMeshData)
301 if (mpMeshData->vbo)
303 glDeleteBuffersARB (1, &mpMeshData->vbo);
304 mpMeshData->vbo = 0;
306 if (mpMeshData->ibo)
308 glDeleteBuffersARB (1, &mpMeshData->ibo);
309 mpMeshData->ibo = 0;
311 if (mpMeshData->verts)
313 delete[] mpMeshData->verts;
314 mpMeshData->verts = NULL;
316 if (mpMeshData->inds)
318 delete[] mpMeshData->inds;
319 mpMeshData->inds = NULL;
324 void model::loadMesh (file *f, int majorver, int minorver, std::vector <materialPtr> &mtls, int numSubsets, renderable *rend)
326 drawSurf_t *ds = NULL;
327 if (numSubsets)
329 mMeshDataCount = numSubsets;
330 mpMeshData = new meshData_t[mMeshDataCount];
331 ds = new drawSurf_t[mMeshDataCount];
332 memset (mpMeshData, 0, sizeof (meshData_t) * mMeshDataCount);
333 memset (ds, 0, sizeof (drawSurf_t) * mMeshDataCount);
334 rend->setDrawSurfs (ds, mMeshDataCount);
335 for (int i = 0; i < mMeshDataCount; i++)
337 // meshData/geomSource stuff (shared)
338 f->readUINT32 (&mpMeshData[i].firstVertex, 1);
339 f->readUINT32 (&mpMeshData[i].firstIndex, 1);
340 mpMeshData[i].firstIndex *= 3;
341 f->readUINT32 (&mpMeshData[i].numVerts, 1);
342 f->readUINT32 (&mpMeshData[i].numInds, 1);
343 mpMeshData[i].numInds *= 3;
344 // material is going to drawSurf (not shared)
345 uint32 mtl;
346 f->readUINT32 (&mtl, 1);
347 ds[i].mtl = mtls[mtl];
348 // ds[i].obj = node; // no need to set this at load time! it will be set during getNewInstance
349 ds[i].mesh = &mpMeshData[i];
350 // mSurfaces[i].tris = &mTris;
353 uint32 sp;
355 // hastangents
356 uchar tangents;
357 f->read (&tangents, sizeof (uchar));
358 //fprintf (stderr, "tangents: %s\n", tangents ? "yes" : "no");
360 uchar lightmaps = 0;
361 if (minorver >= 1)
363 f->read (&lightmaps, sizeof (uchar));
365 //fprintf (stderr, "lightmaps: %s\n", lightmaps ? "yes" : "no");
366 if (lightmaps)
368 uchar sz;
369 f->read (&sz, sizeof (uchar));
370 if (sz)
372 cStr s;
373 s.resize (sz);
374 f->read ((char *)&s[0], sz);
375 // read lightmap texture
376 baseTexturePtr t = g_engine->getResourceMgr ()->createTexture ("lightmaps/" + s);
377 for (size_t i = 0; i < mMeshDataCount; i++)
378 ds[i].lightmap = t;
382 uchar colors = 0;
384 // vertex buffer (meshData stuff)
385 // it is shared for entire model (all subsets) so don't delete VBO for each subset please!
387 f->readUINT32 (&sp, 1);
388 //fprintf (stderr, "%d verts\n", sp);
389 if (sp)
391 int numVerts = sp;
392 int vertSize;
393 vertSize = sizeof (vector3) * 2 + sizeof (vector2); // pos + norm + uv
394 if (colors)
395 vertSize += 4;
396 if (lightmaps)
397 vertSize += sizeof (vector2);
398 if (tangents)
399 vertSize += sizeof (vector3) * 2;
400 int size = (int)(vertSize * numVerts);
401 // init vertex/index buffers
402 uchar* vb;
403 GLuint vbo;
404 vb = NULL;
405 vbo = 0;
407 uchar *ptr;
408 vb = new uchar[size];
409 ptr = vb;
411 // mTris.verts = new drawVertex_t[mTris.numVerts];
412 for (int i = 0; i < numVerts; i++)
414 f->readFloat ((float*)ptr, 3);
415 ptr += sizeof (vector3);
416 f->readFloat ((float*)ptr, 3);
417 ptr += sizeof (vector3);
418 f->readFloat ((float*)ptr, 2);
419 ptr += sizeof (vector2);
420 if (colors) // FIXME: bmdl never contain colors now
422 f->read (ptr, 4);
423 ptr += 4;
425 if (!lightmaps)
427 vector2 lm;
428 f->readFloat ((float*)&lm, 2);
430 else
432 f->readFloat ((float*)ptr, 2);
433 ptr += sizeof (vector2);
435 if (!tangents)
437 vector3 tn[2];
438 f->readFloat ((float*)&tn, 6);
440 else
442 f->readFloat ((float*)ptr, 6);
443 ptr += sizeof (vector3) * 2;
445 if (minorver >= 2)
447 uint32 clr;
448 f->read (&clr, sizeof (clr)); // color?
451 if (GLEW_ARB_vertex_buffer_object)
453 glGenBuffersARB (1, &vbo);
454 glBindBufferARB (GL_ARRAY_BUFFER_ARB, vbo);
455 glBufferDataARB (GL_ARRAY_BUFFER_ARB, size, NULL, GL_STATIC_DRAW_ARB);
456 uchar *p = (uchar*)glMapBufferARB (GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
457 memcpy (p, vb, size);
458 glUnmapBufferARB (GL_ARRAY_BUFFER_ARB);
461 // set vb to meshdata
462 for (int j = 0; j < mMeshDataCount; j++)
464 mpMeshData[j].verts = vb;
465 mpMeshData[j].vbo = vbo;
466 mpMeshData[j].primType = GL_TRIANGLES;
467 mpMeshData[j].vertexSize = vertSize;
468 mpMeshData[j].have_colors = colors ? 1 : 0;
469 mpMeshData[j].have_lightmaps = lightmaps ? 1 : 0;
470 mpMeshData[j].have_tangents = tangents ? 1 : 0;
474 // faces
475 f->readUINT32 (&sp, 1);
476 if (sp)
478 // copy faces
479 int numIndexes = sp * 3;
480 uchar* ib;
481 GLuint ibo;
482 ib = NULL;
483 ibo = 0;
485 ib = new uchar[sizeof (ushort) * numIndexes];
486 f->readUINT16 ((uint16*)ib, numIndexes);
488 if (GLEW_ARB_vertex_buffer_object)
490 glGenBuffersARB (1, &ibo);
491 glBindBufferARB (GL_ELEMENT_ARRAY_BUFFER_ARB, ibo);
492 glBufferDataARB (GL_ELEMENT_ARRAY_BUFFER_ARB, numIndexes * sizeof (ushort), ib, GL_STATIC_DRAW_ARB);
494 // set ib to meshdata
495 for (int j = 0; j < mMeshDataCount; j++)
497 mpMeshData[j].inds = ib;
498 mpMeshData[j].ibo = ibo;
502 if (minorver < 2)
504 // skip old version animation flag
505 uchar b;
506 f->read (&b, sizeof (b));
510 sceneObject* model::load (file *f, mtlBlock *mtls, sceneObject *parent)
512 // FIXME: pass as formal parameter?
513 static int minorver = 0;
514 static int majorver = 1;
515 sceneObject *node = new sceneObject (parent);
516 renderable *rend = new renderable (this);
517 node->attachRenderable (rend);
518 if (!parent)
520 // read magic
521 char mgc[10];
522 f->read( mgc, 9 );
523 mgc[9] = 0;
524 if (!strcmp (mgc, "FEMDL0101"))
526 majorver = 1;
527 minorver = 1;
529 else if (!strcmp (mgc, "FEMDL0102"))
531 majorver = 1;
532 minorver = 2;
534 else
535 sys_error ( "Invalid model file signature (%s).\n", f->name());
537 // load materials
538 mtls = new mtlBlock ();
539 mtls->load( f );
542 if (minorver >= 2)
544 char nsz;
545 f->read (&nsz, sizeof (char));
546 if (nsz)
548 char nm[100];
549 f->read (nm, nsz);
550 nm[nsz] = 0;
551 setName (nm);
552 node->setName (nm);
554 //fprintf (stderr, "got object %s\n", name ());
557 uint32 sp;
559 // matrix
560 matrix4 mtx;
561 f->readMatrix4 (&mtx, 1);
562 matrix4 worldMtx = parent ? mtx * parent->getWorldMatrix() : mtx;
563 node->setRelativeMatrix (mtx);
564 node->setWorldMatrix (worldMtx);
566 // subsets
567 f->readUINT32 (&sp, 1);
568 //fprintf (stderr, "got %d subsets\n", sp);
569 drawSurf_t *ds = NULL;
570 if (sp)
572 // mSurfaces.resize( sp );
573 mMeshDataCount = sp;
574 mpMeshData = new meshData_t[sp];
575 ds = new drawSurf_t[sp];
576 memset (mpMeshData, 0, sizeof (meshData_t) * sp);
577 memset (ds, 0, sizeof (drawSurf_t) * sp);
578 rend->setDrawSurfs (ds, sp);
579 for (size_t i = 0; i < sp; i++)
581 // meshData/geomSource stuff (shared)
582 f->readUINT32 (&mpMeshData[i].firstVertex, 1);
583 f->readUINT32 (&mpMeshData[i].firstIndex, 1);
584 mpMeshData[i].firstIndex *= 3;
585 f->readUINT32 (&mpMeshData[i].numVerts, 1);
586 f->readUINT32 (&mpMeshData[i].numInds, 1);
587 mpMeshData[i].numInds *= 3;
588 // material is going to drawSurf (not shared)
589 uint32 mtl;
590 f->readUINT32 (&mtl, 1);
591 ds[i].mtl = mtls->getMtl (mtl);
592 ds[i].obj = node;
593 ds[i].mesh = &mpMeshData[i];
594 // mSurfaces[i].tris = &mTris;
598 // hastangents
599 uchar tangents;
600 f->read(&tangents, sizeof(uchar));
601 //fprintf (stderr, "tangents: %s\n", tangents ? "yes" : "no");
603 uchar lightmaps = 0;
604 if (minorver >= 1)
606 f->read (&lightmaps, sizeof (uchar));
608 //fprintf (stderr, "lightmaps: %s\n", lightmaps ? "yes" : "no");
609 if (lightmaps)
611 uchar sz;
612 f->read (&sz, sizeof (uchar));
613 if (sz)
615 char nm[200] = "lightmaps/";
616 int l = strlen (nm);
617 f->read (nm + l, sz);
618 nm[l+sz] = 0;
619 // read lightmap texture
620 baseTexturePtr t = g_engine->getResourceMgr ()->createTexture (nm);
621 for (size_t i = 0; i < mMeshDataCount; i++)
622 ds[i].lightmap = t;
626 uchar colors = 0;
628 // vertex buffer (meshData stuff)
629 // it is shared for entire model (all subsets) so don't delete VBO for each subset please!
631 f->readUINT32 (&sp, 1);
632 //fprintf (stderr, "%d verts\n", sp);
633 if (sp)
635 int numVerts = sp;
636 int vertSize;
637 vertSize = sizeof (vector3) * 2 + sizeof (vector2); // pos + norm + uv
638 if (colors)
639 vertSize += 4;
640 if (lightmaps)
641 vertSize += sizeof (vector2);
642 if (tangents)
643 vertSize += sizeof (vector3) * 2;
644 int size = (int)(vertSize * numVerts);
645 // init vertex/index buffers
646 uchar* vb;
647 GLuint vbo;
648 vb = NULL;
649 vbo = 0;
651 uchar *ptr;
652 vb = new uchar[size];
653 ptr = vb;
655 // mTris.verts = new drawVertex_t[mTris.numVerts];
656 for (int i = 0; i < numVerts; i++)
658 f->readFloat ((float*)ptr, 3);
659 ptr += sizeof (vector3);
660 f->readFloat ((float*)ptr, 3);
661 ptr += sizeof (vector3);
662 f->readFloat ((float*)ptr, 2);
663 ptr += sizeof (vector2);
664 if (colors) // FIXME: bmdl never contain colors now
666 f->read (ptr, 4);
667 ptr += 4;
669 if (!lightmaps)
671 // skipt lightmap stub
672 // FIXME: do not include this when not needed
673 vector2 lm;
674 f->readFloat ((float*)&lm, 2);
676 else
678 f->readFloat ((float*)ptr, 2);
679 ptr += sizeof (vector2);
681 if (!tangents)
683 vector3 tn[2];
684 f->readFloat ((float*)&tn, 3);
686 else
688 f->readFloat ((float*)ptr, 6);
689 ptr += sizeof (vector3) * 2;
691 if (minorver >= 2)
693 // stub-skip colors (where is this came from?)
694 uint32 clr;
695 f->read (&clr, sizeof (clr)); // color?
698 if (GLEW_ARB_vertex_buffer_object)
700 glGenBuffersARB (1, &vbo);
701 glBindBufferARB (GL_ARRAY_BUFFER_ARB, vbo);
702 glBufferDataARB (GL_ARRAY_BUFFER_ARB, size, NULL, GL_STATIC_DRAW_ARB);
703 uchar *p = (uchar*)glMapBufferARB (GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
704 memcpy (p, vb, size);
705 glUnmapBufferARB (GL_ARRAY_BUFFER_ARB);
708 // set vb to meshdata
709 for (int j = 0; j < mMeshDataCount; j++)
711 mpMeshData[j].verts = vb;
712 mpMeshData[j].vbo = vbo;
713 mpMeshData[j].primType = GL_TRIANGLES;
714 mpMeshData[j].vertexSize = vertSize;
715 mpMeshData[j].have_colors = colors ? 1 : 0;
716 mpMeshData[j].have_lightmaps = lightmaps ? 1 : 0;
717 mpMeshData[j].have_tangents = tangents ? 1 : 0;
721 // faces
722 f->readUINT32 (&sp, 1);
723 if (sp)
725 // copy faces
726 int numIndexes = sp * 3;
727 uchar* ib;
728 GLuint ibo;
729 ib = NULL;
730 ibo = 0;
732 ib = new uchar[sizeof (ushort) * numIndexes];
733 f->readUINT16 ((uint16*)ib, numIndexes);
735 if (GLEW_ARB_vertex_buffer_object)
737 glGenBuffersARB (1, &ibo);
738 glBindBufferARB (GL_ELEMENT_ARRAY_BUFFER_ARB, ibo);
739 glBufferDataARB (GL_ELEMENT_ARRAY_BUFFER_ARB, numIndexes * sizeof (ushort), ib, GL_STATIC_DRAW_ARB);
741 // set ib to meshdata
742 for (int j = 0; j < mMeshDataCount; j++)
744 mpMeshData[j].inds = ib;
745 mpMeshData[j].ibo = ibo;
749 if (minorver < 2)
751 // skip old version animation flag
752 uchar b;
753 f->read (&b, sizeof (b));
756 // children
757 f->readUINT32 (&sp, 1);
758 int nChildren = sp;
759 // mChildren.resize( sp );
760 for (uint32 i = 0; i < nChildren; i++)
762 model* m = new model;
763 sceneObject *c = m->load (f, mtls, node);
764 node->addChild (c);
767 init ();
769 if (!parent)
770 delete mtls;
771 return node;
774 /* typedef smartPtr <mtlBlock> mtlBlockPtr;
776 mtlBlockPtr mpMtlBlock;*/
778 /* // renderable implementation
779 int model::numSubsets (void) const
781 return (int)mSurfaces.size ();
784 materialPtr model::getMtl (int subset) const
786 return mpMtlBlock ? mSurfaces[subset].mtl : NULL;
788 #if 0
789 void model::prepare (int subset) const
792 g_engine->getEffectParms()->setMatrix( effectParm_WorldMatrix, mWorldMatrix );
793 if (mSurfaces[subset].lightmap)
794 g_engine->getEffectParms ()->setTexture (effectParm_LightmapTexture, mSurfaces[subset].lightmap);*/
797 void model::render (int subset, int pass) const
799 if (mpData)
800 mpData->drawSubset (subset, pass);
802 #endif
803 /* void model::renderShadowVolume (bool withChildren) const
805 if (mpData) // FIXME: model can contain NULL mpData, but this is the case for dummy object, which can be handled in more efficient way
806 mpData->renderShadowVolume ();
807 sceneObject::renderShadowVolume (withChildren);
810 #if 0
811 void model::buildShadowVolume (const lightSource &src)
813 #if 1
814 lightSource::type t = src.getType ();
816 // lightpos is transformed just like everything other, but we want it in model space
817 matrix4 light2model = src.getWorldMatrix () * getWorldMatrix ().inverse ();
818 vector3 pos = src.getPosition () * light2model;
819 vector3 dir;
820 vector3 L = src.getPosition () * light2model;
821 if (src.getType () == lightSource::direct)
823 vector3 dir = light2model.transform (src.getDirection ());
824 dir.normalize ();
827 // extrude verts
828 for (int i = 0; i < mTris.numVerts; i++)
830 if (src.getType () != lightSource::direct)
832 dir = (vector3 &)mTris.shadowVerts[i] - src.getPosition ();
833 dir.normalize ();
836 // V.w*L + float4 (V.xyz - L.xyz, 0)
837 mTris.shadowVerts[i + mTris.numVerts].xyzw.x = mTris.shadowVerts[i].xyzw.x - L.x;
838 mTris.shadowVerts[i + mTris.numVerts].xyzw.y = mTris.shadowVerts[i].xyzw.y - L.y;
839 mTris.shadowVerts[i + mTris.numVerts].xyzw.z = mTris.shadowVerts[i].xyzw.z - L.z;
840 mTris.shadowVerts[i + mTris.numVerts].xyzw.w = 0;
843 // write indexes, build shadow volume
844 mTris.numShadowVolumeIndexes = 0;
845 for (int i = 0; i < mTris.numSilEdges; i++)
847 // check if only one of two faces forming the edge is visible from light
848 const vector3 &n1 = mTris.facePlanes[mTris.silEdges[i].f1].normal ();
849 const vector3 &n2 = mTris.facePlanes[mTris.silEdges[i].f2].normal ();
850 float d1 = n1.dot (dir);
851 float d2 = n2.dot (dir);
852 #define s_idx (mTris.shadowVolumeIndexes)
853 #define n_idx (mTris.numShadowVolumeIndexes)
854 // add edge verts to list of shadow volume indexes, forming a quad
855 if (d1 < 0 && d2 > 0) // f1 is visible, v2-v1 form CCW order
857 s_idx[n_idx++] = mTris.silEdges[i].v2;
858 s_idx[n_idx++] = mTris.silEdges[i].v1;
859 s_idx[n_idx++] = mTris.silEdges[i].v1 + mTris.numVerts;
860 s_idx[n_idx++] = mTris.silEdges[i].v2;
861 s_idx[n_idx++] = mTris.silEdges[i].v1 + mTris.numVerts;
862 s_idx[n_idx++] = mTris.silEdges[i].v2 + mTris.numVerts;
864 else if (d2 < 0 && d1 > 0) // f2 is visible, v1-v2 form CCW order
866 s_idx[n_idx++] = mTris.silEdges[i].v1;
867 s_idx[n_idx++] = mTris.silEdges[i].v2;
868 s_idx[n_idx++] = mTris.silEdges[i].v1 + mTris.numVerts;
869 s_idx[n_idx++] = mTris.silEdges[i].v2;
870 s_idx[n_idx++] = mTris.silEdges[i].v2 + mTris.numVerts;
871 s_idx[n_idx++] = mTris.silEdges[i].v1 + mTris.numVerts;
875 // front/back caps are not added to shadow vertex list, because they are taken from normal vertex array
876 // but we write caps indexes
877 #if 0
878 for (int i = 0; i < mTris.numIndexes/3; i++)
880 float d = mTris.facePlanes[i].normal ().dot (dir);
881 if (d < 0) // visible
883 // front cap
884 s_idx[n_idx++] = mTris.silIndexes[i*3+0];
885 s_idx[n_idx++] = mTris.silIndexes[i*3+2];
886 s_idx[n_idx++] = mTris.silIndexes[i*3+1];
888 else
890 // back cap (from extruded list)
891 s_idx[n_idx++] = mTris.silIndexes[i*3+0] + mTris.numVerts;
892 s_idx[n_idx++] = mTris.silIndexes[i*3+2] + mTris.numVerts;
893 s_idx[n_idx++] = mTris.silIndexes[i*3+1] + mTris.numVerts;
896 #endif
897 #undef s_idx
898 for (size_t i = 0; i < mChildren.size (); i++)
900 if (mChildren[i]->isTypeOf (TypeId))
902 mChildren[i].dynamicCast<model>()->buildShadowVolume (src);
906 #endif
908 #endif
910 #if 0
911 const modelTriangles_t& model::getTriangles (void) const
913 return mTris;
915 #endif