3 Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
10 This program 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
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 #include <IAnimatedMesh.h>
26 #include <SAnimatedMesh.h>
28 // In Irrlicht 1.8 the signature of ITexture::lock was changed from
29 // (bool, u32) to (E_TEXTURE_LOCK_MODE, u32).
30 #if IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR <= 7
31 #define MY_ETLM_READ_ONLY true
33 #define MY_ETLM_READ_ONLY video::ETLM_READ_ONLY
36 scene::IAnimatedMesh* createCubeMesh(v3f scale)
38 video::SColor c(255,255,255,255);
39 video::S3DVertex vertices[24] =
42 video::S3DVertex(-0.5,+0.5,-0.5, 0,1,0, c, 0,1),
43 video::S3DVertex(-0.5,+0.5,+0.5, 0,1,0, c, 0,0),
44 video::S3DVertex(+0.5,+0.5,+0.5, 0,1,0, c, 1,0),
45 video::S3DVertex(+0.5,+0.5,-0.5, 0,1,0, c, 1,1),
47 video::S3DVertex(-0.5,-0.5,-0.5, 0,-1,0, c, 0,0),
48 video::S3DVertex(+0.5,-0.5,-0.5, 0,-1,0, c, 1,0),
49 video::S3DVertex(+0.5,-0.5,+0.5, 0,-1,0, c, 1,1),
50 video::S3DVertex(-0.5,-0.5,+0.5, 0,-1,0, c, 0,1),
52 video::S3DVertex(+0.5,-0.5,-0.5, 1,0,0, c, 0,1),
53 video::S3DVertex(+0.5,+0.5,-0.5, 1,0,0, c, 0,0),
54 video::S3DVertex(+0.5,+0.5,+0.5, 1,0,0, c, 1,0),
55 video::S3DVertex(+0.5,-0.5,+0.5, 1,0,0, c, 1,1),
57 video::S3DVertex(-0.5,-0.5,-0.5, -1,0,0, c, 1,1),
58 video::S3DVertex(-0.5,-0.5,+0.5, -1,0,0, c, 0,1),
59 video::S3DVertex(-0.5,+0.5,+0.5, -1,0,0, c, 0,0),
60 video::S3DVertex(-0.5,+0.5,-0.5, -1,0,0, c, 1,0),
62 video::S3DVertex(-0.5,-0.5,+0.5, 0,0,1, c, 1,1),
63 video::S3DVertex(+0.5,-0.5,+0.5, 0,0,1, c, 0,1),
64 video::S3DVertex(+0.5,+0.5,+0.5, 0,0,1, c, 0,0),
65 video::S3DVertex(-0.5,+0.5,+0.5, 0,0,1, c, 1,0),
67 video::S3DVertex(-0.5,-0.5,-0.5, 0,0,-1, c, 0,1),
68 video::S3DVertex(-0.5,+0.5,-0.5, 0,0,-1, c, 0,0),
69 video::S3DVertex(+0.5,+0.5,-0.5, 0,0,-1, c, 1,0),
70 video::S3DVertex(+0.5,-0.5,-0.5, 0,0,-1, c, 1,1),
73 u16 indices[6] = {0,1,2,2,3,0};
75 scene::SMesh *mesh = new scene::SMesh();
76 for (u32 i=0; i<6; ++i)
78 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
79 buf->append(vertices + 4 * i, 4, indices, 6);
80 // Set default material
81 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
82 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
83 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
84 // Add mesh buffer to mesh
85 mesh->addMeshBuffer(buf);
89 scene::SAnimatedMesh *anim_mesh = new scene::SAnimatedMesh(mesh);
91 scaleMesh(anim_mesh, scale); // also recalculates bounding box
95 void scaleMesh(scene::IMesh *mesh, v3f scale)
100 core::aabbox3d<f32> bbox;
103 u32 mc = mesh->getMeshBufferCount();
104 for (u32 j = 0; j < mc; j++) {
105 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
106 const u32 stride = getVertexPitchFromType(buf->getVertexType());
107 u32 vertex_count = buf->getVertexCount();
108 u8 *vertices = (u8 *)buf->getVertices();
109 for (u32 i = 0; i < vertex_count; i++)
110 ((video::S3DVertex *)(vertices + i * stride))->Pos *= scale;
112 buf->recalculateBoundingBox();
114 // calculate total bounding box
116 bbox = buf->getBoundingBox();
118 bbox.addInternalBox(buf->getBoundingBox());
120 mesh->setBoundingBox(bbox);
123 void translateMesh(scene::IMesh *mesh, v3f vec)
128 core::aabbox3d<f32> bbox;
131 u32 mc = mesh->getMeshBufferCount();
132 for (u32 j = 0; j < mc; j++) {
133 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
134 const u32 stride = getVertexPitchFromType(buf->getVertexType());
135 u32 vertex_count = buf->getVertexCount();
136 u8 *vertices = (u8 *)buf->getVertices();
137 for (u32 i = 0; i < vertex_count; i++)
138 ((video::S3DVertex *)(vertices + i * stride))->Pos += vec;
140 buf->recalculateBoundingBox();
142 // calculate total bounding box
144 bbox = buf->getBoundingBox();
146 bbox.addInternalBox(buf->getBoundingBox());
148 mesh->setBoundingBox(bbox);
152 void setMeshColor(scene::IMesh *mesh, const video::SColor &color)
157 u32 mc = mesh->getMeshBufferCount();
158 for (u32 j = 0; j < mc; j++) {
159 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
160 const u32 stride = getVertexPitchFromType(buf->getVertexType());
161 u32 vertex_count = buf->getVertexCount();
162 u8 *vertices = (u8 *)buf->getVertices();
163 for (u32 i = 0; i < vertex_count; i++)
164 ((video::S3DVertex *)(vertices + i * stride))->Color = color;
168 void setMeshColorByNormalXYZ(scene::IMesh *mesh,
169 const video::SColor &colorX,
170 const video::SColor &colorY,
171 const video::SColor &colorZ)
176 u16 mc = mesh->getMeshBufferCount();
177 for(u16 j=0; j<mc; j++)
179 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
180 video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
181 u16 vc = buf->getVertexCount();
182 for(u16 i=0; i<vc; i++)
184 f32 x = fabs(vertices[i].Normal.X);
185 f32 y = fabs(vertices[i].Normal.Y);
186 f32 z = fabs(vertices[i].Normal.Z);
188 vertices[i].Color = colorX;
190 vertices[i].Color = colorY;
192 vertices[i].Color = colorZ;
198 void rotateMeshXYby (scene::IMesh *mesh, f64 degrees)
200 u16 mc = mesh->getMeshBufferCount();
201 for(u16 j = 0; j < mc; j++)
203 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
204 video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
205 u16 vc = buf->getVertexCount();
206 for(u16 i = 0; i < vc; i++)
208 vertices[i].Pos.rotateXYBy(degrees);
213 void rotateMeshXZby (scene::IMesh *mesh, f64 degrees)
215 u16 mc = mesh->getMeshBufferCount();
216 for(u16 j = 0; j < mc; j++)
218 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
219 video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
220 u16 vc = buf->getVertexCount();
221 for(u16 i = 0; i < vc; i++)
223 vertices[i].Pos.rotateXZBy(degrees);
228 void rotateMeshYZby (scene::IMesh *mesh, f64 degrees)
230 u16 mc = mesh->getMeshBufferCount();
231 for(u16 j = 0; j < mc; j++)
233 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
234 video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
235 u16 vc = buf->getVertexCount();
236 for(u16 i = 0; i < vc; i++)
238 vertices[i].Pos.rotateYZBy(degrees);
243 void rotateMeshBy6dFacedir(scene::IMesh *mesh, int facedir)
245 int axisdir = facedir>>2;
248 u16 mc = mesh->getMeshBufferCount();
249 for(u16 j = 0; j < mc; j++)
251 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
252 video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
253 u16 vc = buf->getVertexCount();
254 for(u16 i=0; i<vc; i++)
260 vertices[i].Pos.rotateXZBy(-90);
261 else if(facedir == 2)
262 vertices[i].Pos.rotateXZBy(180);
263 else if(facedir == 3)
264 vertices[i].Pos.rotateXZBy(90);
267 vertices[i].Pos.rotateYZBy(90);
269 vertices[i].Pos.rotateXYBy(90);
270 else if(facedir == 2)
271 vertices[i].Pos.rotateXYBy(180);
272 else if(facedir == 3)
273 vertices[i].Pos.rotateXYBy(-90);
276 vertices[i].Pos.rotateYZBy(-90);
278 vertices[i].Pos.rotateXYBy(-90);
279 else if(facedir == 2)
280 vertices[i].Pos.rotateXYBy(180);
281 else if(facedir == 3)
282 vertices[i].Pos.rotateXYBy(90);
285 vertices[i].Pos.rotateXYBy(-90);
287 vertices[i].Pos.rotateYZBy(90);
288 else if(facedir == 2)
289 vertices[i].Pos.rotateYZBy(180);
290 else if(facedir == 3)
291 vertices[i].Pos.rotateYZBy(-90);
294 vertices[i].Pos.rotateXYBy(90);
296 vertices[i].Pos.rotateYZBy(-90);
297 else if(facedir == 2)
298 vertices[i].Pos.rotateYZBy(180);
299 else if(facedir == 3)
300 vertices[i].Pos.rotateYZBy(90);
303 vertices[i].Pos.rotateXYBy(-180);
305 vertices[i].Pos.rotateXZBy(90);
306 else if(facedir == 2)
307 vertices[i].Pos.rotateXZBy(180);
308 else if(facedir == 3)
309 vertices[i].Pos.rotateXZBy(-90);
318 void recalculateBoundingBox(scene::IMesh *src_mesh)
320 core::aabbox3d<f32> bbox;
322 for(u16 j = 0; j < src_mesh->getMeshBufferCount(); j++)
324 scene::IMeshBuffer *buf = src_mesh->getMeshBuffer(j);
325 buf->recalculateBoundingBox();
327 bbox = buf->getBoundingBox();
329 bbox.addInternalBox(buf->getBoundingBox());
331 src_mesh->setBoundingBox(bbox);
334 scene::IMesh* cloneMesh(scene::IMesh *src_mesh)
336 scene::SMesh* dst_mesh = new scene::SMesh();
337 for(u16 j = 0; j < src_mesh->getMeshBufferCount(); j++)
339 scene::IMeshBuffer *buf = src_mesh->getMeshBuffer(j);
340 video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
341 u16 *indices = (u16*)buf->getIndices();
342 scene::SMeshBuffer *temp_buf = new scene::SMeshBuffer();
343 temp_buf->append(vertices, buf->getVertexCount(),
344 indices, buf->getIndexCount());
345 dst_mesh->addMeshBuffer(temp_buf);
351 scene::IMesh* convertNodeboxNodeToMesh(ContentFeatures *f)
353 scene::SMesh* dst_mesh = new scene::SMesh();
354 for (u16 j = 0; j < 6; j++)
356 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
357 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
358 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
359 dst_mesh->addMeshBuffer(buf);
363 video::SColor c(255,255,255,255);
365 std::vector<aabb3f> boxes = f->node_box.fixed;
367 for(std::vector<aabb3f>::iterator
369 i != boxes.end(); i++)
374 if (box.MinEdge.X > box.MaxEdge.X)
377 box.MinEdge.X=box.MaxEdge.X;
380 if (box.MinEdge.Y > box.MaxEdge.Y)
383 box.MinEdge.Y=box.MaxEdge.Y;
386 if (box.MinEdge.Z > box.MaxEdge.Z)
389 box.MinEdge.Z=box.MaxEdge.Z;
392 // Compute texture coords
393 f32 tx1 = (box.MinEdge.X/BS)+0.5;
394 f32 ty1 = (box.MinEdge.Y/BS)+0.5;
395 f32 tz1 = (box.MinEdge.Z/BS)+0.5;
396 f32 tx2 = (box.MaxEdge.X/BS)+0.5;
397 f32 ty2 = (box.MaxEdge.Y/BS)+0.5;
398 f32 tz2 = (box.MaxEdge.Z/BS)+0.5;
401 tx1, 1-tz2, tx2, 1-tz1,
405 tz1, 1-ty2, tz2, 1-ty1,
407 1-tz2, 1-ty2, 1-tz1, 1-ty1,
409 1-tx2, 1-ty2, 1-tx1, 1-ty1,
411 tx1, 1-ty2, tx2, 1-ty1,
413 v3f min = box.MinEdge;
414 v3f max = box.MaxEdge;
416 video::S3DVertex vertices[24] =
419 video::S3DVertex(min.X,max.Y,max.Z, 0,1,0, c, txc[0],txc[1]),
420 video::S3DVertex(max.X,max.Y,max.Z, 0,1,0, c, txc[2],txc[1]),
421 video::S3DVertex(max.X,max.Y,min.Z, 0,1,0, c, txc[2],txc[3]),
422 video::S3DVertex(min.X,max.Y,min.Z, 0,1,0, c, txc[0],txc[3]),
424 video::S3DVertex(min.X,min.Y,min.Z, 0,-1,0, c, txc[4],txc[5]),
425 video::S3DVertex(max.X,min.Y,min.Z, 0,-1,0, c, txc[6],txc[5]),
426 video::S3DVertex(max.X,min.Y,max.Z, 0,-1,0, c, txc[6],txc[7]),
427 video::S3DVertex(min.X,min.Y,max.Z, 0,-1,0, c, txc[4],txc[7]),
429 video::S3DVertex(max.X,max.Y,min.Z, 1,0,0, c, txc[ 8],txc[9]),
430 video::S3DVertex(max.X,max.Y,max.Z, 1,0,0, c, txc[10],txc[9]),
431 video::S3DVertex(max.X,min.Y,max.Z, 1,0,0, c, txc[10],txc[11]),
432 video::S3DVertex(max.X,min.Y,min.Z, 1,0,0, c, txc[ 8],txc[11]),
434 video::S3DVertex(min.X,max.Y,max.Z, -1,0,0, c, txc[12],txc[13]),
435 video::S3DVertex(min.X,max.Y,min.Z, -1,0,0, c, txc[14],txc[13]),
436 video::S3DVertex(min.X,min.Y,min.Z, -1,0,0, c, txc[14],txc[15]),
437 video::S3DVertex(min.X,min.Y,max.Z, -1,0,0, c, txc[12],txc[15]),
439 video::S3DVertex(max.X,max.Y,max.Z, 0,0,1, c, txc[16],txc[17]),
440 video::S3DVertex(min.X,max.Y,max.Z, 0,0,1, c, txc[18],txc[17]),
441 video::S3DVertex(min.X,min.Y,max.Z, 0,0,1, c, txc[18],txc[19]),
442 video::S3DVertex(max.X,min.Y,max.Z, 0,0,1, c, txc[16],txc[19]),
444 video::S3DVertex(min.X,max.Y,min.Z, 0,0,-1, c, txc[20],txc[21]),
445 video::S3DVertex(max.X,max.Y,min.Z, 0,0,-1, c, txc[22],txc[21]),
446 video::S3DVertex(max.X,min.Y,min.Z, 0,0,-1, c, txc[22],txc[23]),
447 video::S3DVertex(min.X,min.Y,min.Z, 0,0,-1, c, txc[20],txc[23]),
450 u16 indices[] = {0,1,2,2,3,0};
452 for(u16 j = 0; j < 24; j += 4)
454 scene::IMeshBuffer *buf = dst_mesh->getMeshBuffer(j / 4);
455 buf->append(vertices + j, 4, indices, 6);
463 core::array<u32> tris;
476 const u16 cachesize = 32;
478 float FindVertexScore(vcache *v)
480 const float CacheDecayPower = 1.5f;
481 const float LastTriScore = 0.75f;
482 const float ValenceBoostScale = 2.0f;
483 const float ValenceBoostPower = 0.5f;
484 const float MaxSizeVertexCache = 32.0f;
486 if (v->NumActiveTris == 0)
488 // No tri needs this vertex!
493 int CachePosition = v->cachepos;
494 if (CachePosition < 0)
496 // Vertex is not in FIFO cache - no score.
500 if (CachePosition < 3)
502 // This vertex was used in the last triangle,
503 // so it has a fixed score.
504 Score = LastTriScore;
508 // Points for being high in the cache.
509 const float Scaler = 1.0f / (MaxSizeVertexCache - 3);
510 Score = 1.0f - (CachePosition - 3) * Scaler;
511 Score = powf(Score, CacheDecayPower);
515 // Bonus points for having a low number of tris still to
516 // use the vert, so we get rid of lone verts quickly.
517 float ValenceBoost = powf(v->NumActiveTris,
519 Score += ValenceBoostScale * ValenceBoost;
525 A specialized LRU cache for the Forsyth algorithm.
532 f_lru(vcache *v, tcache *t): vc(v), tc(t)
534 for (u16 i = 0; i < cachesize; i++)
540 // Adds this vertex index and returns the highest-scoring triangle index
541 u32 add(u16 vert, bool updatetris = false)
545 // Mark existing pos as empty
546 for (u16 i = 0; i < cachesize; i++)
548 if (cache[i] == vert)
550 // Move everything down
551 for (u16 j = i; j; j--)
553 cache[j] = cache[j - 1];
563 if (cache[cachesize-1] != -1)
564 vc[cache[cachesize-1]].cachepos = -1;
566 // Move everything down
567 for (u16 i = cachesize - 1; i; i--)
569 cache[i] = cache[i - 1];
580 // Update cache positions
581 for (u16 i = 0; i < cachesize; i++)
586 vc[cache[i]].cachepos = i;
587 vc[cache[i]].score = FindVertexScore(&vc[cache[i]]);
590 // Update triangle scores
591 for (u16 i = 0; i < cachesize; i++)
596 const u16 trisize = vc[cache[i]].tris.size();
597 for (u16 t = 0; t < trisize; t++)
599 tcache *tri = &tc[vc[cache[i]].tris[t]];
602 vc[tri->ind[0]].score +
603 vc[tri->ind[1]].score +
604 vc[tri->ind[2]].score;
606 if (tri->score > hiscore)
608 hiscore = tri->score;
609 highest = vc[cache[i]].tris[t];
619 s32 cache[cachesize];
625 Vertex cache optimization according to the Forsyth paper:
626 http://home.comcast.net/~tom_forsyth/papers/fast_vert_cache_opt.html
628 The function is thread-safe (read: you can optimize several meshes in different threads)
630 \param mesh Source mesh for the operation. */
631 scene::IMesh* createForsythOptimizedMesh(const scene::IMesh *mesh)
636 scene::SMesh *newmesh = new scene::SMesh();
637 newmesh->BoundingBox = mesh->getBoundingBox();
639 const u32 mbcount = mesh->getMeshBufferCount();
641 for (u32 b = 0; b < mbcount; ++b)
643 const scene::IMeshBuffer *mb = mesh->getMeshBuffer(b);
645 if (mb->getIndexType() != video::EIT_16BIT)
647 //os::Printer::log("Cannot optimize a mesh with 32bit indices", ELL_ERROR);
652 const u32 icount = mb->getIndexCount();
653 const u32 tcount = icount / 3;
654 const u32 vcount = mb->getVertexCount();
655 const u16 *ind = mb->getIndices();
657 vcache *vc = new vcache[vcount];
658 tcache *tc = new tcache[tcount];
663 for (u16 i = 0; i < vcount; i++)
667 vc[i].NumActiveTris = 0;
670 // First pass: count how many times a vert is used
671 for (u32 i = 0; i < icount; i += 3)
673 vc[ind[i]].NumActiveTris++;
674 vc[ind[i + 1]].NumActiveTris++;
675 vc[ind[i + 2]].NumActiveTris++;
677 const u32 tri_ind = i/3;
678 tc[tri_ind].ind[0] = ind[i];
679 tc[tri_ind].ind[1] = ind[i + 1];
680 tc[tri_ind].ind[2] = ind[i + 2];
683 // Second pass: list of each triangle
684 for (u32 i = 0; i < tcount; i++)
686 vc[tc[i].ind[0]].tris.push_back(i);
687 vc[tc[i].ind[1]].tris.push_back(i);
688 vc[tc[i].ind[2]].tris.push_back(i);
693 // Give initial scores
694 for (u16 i = 0; i < vcount; i++)
696 vc[i].score = FindVertexScore(&vc[i]);
698 for (u32 i = 0; i < tcount; i++)
701 vc[tc[i].ind[0]].score +
702 vc[tc[i].ind[1]].score +
703 vc[tc[i].ind[2]].score;
706 switch(mb->getVertexType())
708 case video::EVT_STANDARD:
710 video::S3DVertex *v = (video::S3DVertex *) mb->getVertices();
712 scene::SMeshBuffer *buf = new scene::SMeshBuffer();
713 buf->Material = mb->getMaterial();
715 buf->Vertices.reallocate(vcount);
716 buf->Indices.reallocate(icount);
718 core::map<const video::S3DVertex, const u16> sind; // search index for fast operation
719 typedef core::map<const video::S3DVertex, const u16>::Node snode;
726 if (tc[highest].drawn)
730 for (u32 t = 0; t < tcount; t++)
734 if (tc[t].score > hiscore)
737 hiscore = tc[t].score;
746 // Output the best triangle
747 u16 newind = buf->Vertices.size();
749 snode *s = sind.find(v[tc[highest].ind[0]]);
753 buf->Vertices.push_back(v[tc[highest].ind[0]]);
754 buf->Indices.push_back(newind);
755 sind.insert(v[tc[highest].ind[0]], newind);
760 buf->Indices.push_back(s->getValue());
763 s = sind.find(v[tc[highest].ind[1]]);
767 buf->Vertices.push_back(v[tc[highest].ind[1]]);
768 buf->Indices.push_back(newind);
769 sind.insert(v[tc[highest].ind[1]], newind);
774 buf->Indices.push_back(s->getValue());
777 s = sind.find(v[tc[highest].ind[2]]);
781 buf->Vertices.push_back(v[tc[highest].ind[2]]);
782 buf->Indices.push_back(newind);
783 sind.insert(v[tc[highest].ind[2]], newind);
787 buf->Indices.push_back(s->getValue());
790 vc[tc[highest].ind[0]].NumActiveTris--;
791 vc[tc[highest].ind[1]].NumActiveTris--;
792 vc[tc[highest].ind[2]].NumActiveTris--;
794 tc[highest].drawn = true;
796 for (u16 j = 0; j < 3; j++)
798 vcache *vert = &vc[tc[highest].ind[j]];
799 for (u16 t = 0; t < vert->tris.size(); t++)
801 if (highest == vert->tris[t])
809 lru.add(tc[highest].ind[0]);
810 lru.add(tc[highest].ind[1]);
811 highest = lru.add(tc[highest].ind[2], true);
815 buf->setBoundingBox(mb->getBoundingBox());
816 newmesh->addMeshBuffer(buf);
820 case video::EVT_2TCOORDS:
822 video::S3DVertex2TCoords *v = (video::S3DVertex2TCoords *) mb->getVertices();
824 scene::SMeshBufferLightMap *buf = new scene::SMeshBufferLightMap();
825 buf->Material = mb->getMaterial();
827 buf->Vertices.reallocate(vcount);
828 buf->Indices.reallocate(icount);
830 core::map<const video::S3DVertex2TCoords, const u16> sind; // search index for fast operation
831 typedef core::map<const video::S3DVertex2TCoords, const u16>::Node snode;
838 if (tc[highest].drawn)
842 for (u32 t = 0; t < tcount; t++)
846 if (tc[t].score > hiscore)
849 hiscore = tc[t].score;
858 // Output the best triangle
859 u16 newind = buf->Vertices.size();
861 snode *s = sind.find(v[tc[highest].ind[0]]);
865 buf->Vertices.push_back(v[tc[highest].ind[0]]);
866 buf->Indices.push_back(newind);
867 sind.insert(v[tc[highest].ind[0]], newind);
872 buf->Indices.push_back(s->getValue());
875 s = sind.find(v[tc[highest].ind[1]]);
879 buf->Vertices.push_back(v[tc[highest].ind[1]]);
880 buf->Indices.push_back(newind);
881 sind.insert(v[tc[highest].ind[1]], newind);
886 buf->Indices.push_back(s->getValue());
889 s = sind.find(v[tc[highest].ind[2]]);
893 buf->Vertices.push_back(v[tc[highest].ind[2]]);
894 buf->Indices.push_back(newind);
895 sind.insert(v[tc[highest].ind[2]], newind);
899 buf->Indices.push_back(s->getValue());
902 vc[tc[highest].ind[0]].NumActiveTris--;
903 vc[tc[highest].ind[1]].NumActiveTris--;
904 vc[tc[highest].ind[2]].NumActiveTris--;
906 tc[highest].drawn = true;
908 for (u16 j = 0; j < 3; j++)
910 vcache *vert = &vc[tc[highest].ind[j]];
911 for (u16 t = 0; t < vert->tris.size(); t++)
913 if (highest == vert->tris[t])
921 lru.add(tc[highest].ind[0]);
922 lru.add(tc[highest].ind[1]);
923 highest = lru.add(tc[highest].ind[2]);
927 buf->setBoundingBox(mb->getBoundingBox());
928 newmesh->addMeshBuffer(buf);
933 case video::EVT_TANGENTS:
935 video::S3DVertexTangents *v = (video::S3DVertexTangents *) mb->getVertices();
937 scene::SMeshBufferTangents *buf = new scene::SMeshBufferTangents();
938 buf->Material = mb->getMaterial();
940 buf->Vertices.reallocate(vcount);
941 buf->Indices.reallocate(icount);
943 core::map<const video::S3DVertexTangents, const u16> sind; // search index for fast operation
944 typedef core::map<const video::S3DVertexTangents, const u16>::Node snode;
951 if (tc[highest].drawn)
955 for (u32 t = 0; t < tcount; t++)
959 if (tc[t].score > hiscore)
962 hiscore = tc[t].score;
971 // Output the best triangle
972 u16 newind = buf->Vertices.size();
974 snode *s = sind.find(v[tc[highest].ind[0]]);
978 buf->Vertices.push_back(v[tc[highest].ind[0]]);
979 buf->Indices.push_back(newind);
980 sind.insert(v[tc[highest].ind[0]], newind);
985 buf->Indices.push_back(s->getValue());
988 s = sind.find(v[tc[highest].ind[1]]);
992 buf->Vertices.push_back(v[tc[highest].ind[1]]);
993 buf->Indices.push_back(newind);
994 sind.insert(v[tc[highest].ind[1]], newind);
999 buf->Indices.push_back(s->getValue());
1002 s = sind.find(v[tc[highest].ind[2]]);
1006 buf->Vertices.push_back(v[tc[highest].ind[2]]);
1007 buf->Indices.push_back(newind);
1008 sind.insert(v[tc[highest].ind[2]], newind);
1012 buf->Indices.push_back(s->getValue());
1015 vc[tc[highest].ind[0]].NumActiveTris--;
1016 vc[tc[highest].ind[1]].NumActiveTris--;
1017 vc[tc[highest].ind[2]].NumActiveTris--;
1019 tc[highest].drawn = true;
1021 for (u16 j = 0; j < 3; j++)
1023 vcache *vert = &vc[tc[highest].ind[j]];
1024 for (u16 t = 0; t < vert->tris.size(); t++)
1026 if (highest == vert->tris[t])
1028 vert->tris.erase(t);
1034 lru.add(tc[highest].ind[0]);
1035 lru.add(tc[highest].ind[1]);
1036 highest = lru.add(tc[highest].ind[2]);
1040 buf->setBoundingBox(mb->getBoundingBox());
1041 newmesh->addMeshBuffer(buf);
1050 } // for each meshbuffer