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 static void applyFacesShading(video::SColor& color, float factor)
38 color.setRed(core::clamp(core::round32(color.getRed()*factor), 0, 255));
39 color.setGreen(core::clamp(core::round32(color.getGreen()*factor), 0, 255));
40 color.setBlue(core::clamp(core::round32(color.getBlue()*factor), 0, 255));
43 scene::IAnimatedMesh* createCubeMesh(v3f scale)
45 video::SColor c(255,255,255,255);
46 video::S3DVertex vertices[24] =
49 video::S3DVertex(-0.5,+0.5,-0.5, 0,1,0, c, 0,1),
50 video::S3DVertex(-0.5,+0.5,+0.5, 0,1,0, c, 0,0),
51 video::S3DVertex(+0.5,+0.5,+0.5, 0,1,0, c, 1,0),
52 video::S3DVertex(+0.5,+0.5,-0.5, 0,1,0, c, 1,1),
54 video::S3DVertex(-0.5,-0.5,-0.5, 0,-1,0, c, 0,0),
55 video::S3DVertex(+0.5,-0.5,-0.5, 0,-1,0, c, 1,0),
56 video::S3DVertex(+0.5,-0.5,+0.5, 0,-1,0, c, 1,1),
57 video::S3DVertex(-0.5,-0.5,+0.5, 0,-1,0, c, 0,1),
59 video::S3DVertex(+0.5,-0.5,-0.5, 1,0,0, c, 0,1),
60 video::S3DVertex(+0.5,+0.5,-0.5, 1,0,0, c, 0,0),
61 video::S3DVertex(+0.5,+0.5,+0.5, 1,0,0, c, 1,0),
62 video::S3DVertex(+0.5,-0.5,+0.5, 1,0,0, c, 1,1),
64 video::S3DVertex(-0.5,-0.5,-0.5, -1,0,0, c, 1,1),
65 video::S3DVertex(-0.5,-0.5,+0.5, -1,0,0, c, 0,1),
66 video::S3DVertex(-0.5,+0.5,+0.5, -1,0,0, c, 0,0),
67 video::S3DVertex(-0.5,+0.5,-0.5, -1,0,0, c, 1,0),
69 video::S3DVertex(-0.5,-0.5,+0.5, 0,0,1, c, 1,1),
70 video::S3DVertex(+0.5,-0.5,+0.5, 0,0,1, c, 0,1),
71 video::S3DVertex(+0.5,+0.5,+0.5, 0,0,1, c, 0,0),
72 video::S3DVertex(-0.5,+0.5,+0.5, 0,0,1, c, 1,0),
74 video::S3DVertex(-0.5,-0.5,-0.5, 0,0,-1, c, 0,1),
75 video::S3DVertex(-0.5,+0.5,-0.5, 0,0,-1, c, 0,0),
76 video::S3DVertex(+0.5,+0.5,-0.5, 0,0,-1, c, 1,0),
77 video::S3DVertex(+0.5,-0.5,-0.5, 0,0,-1, c, 1,1),
80 u16 indices[6] = {0,1,2,2,3,0};
82 scene::SMesh *mesh = new scene::SMesh();
83 for (u32 i=0; i<6; ++i)
85 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
86 buf->append(vertices + 4 * i, 4, indices, 6);
87 // Set default material
88 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
89 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
90 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
91 // Add mesh buffer to mesh
92 mesh->addMeshBuffer(buf);
96 scene::SAnimatedMesh *anim_mesh = new scene::SAnimatedMesh(mesh);
98 scaleMesh(anim_mesh, scale); // also recalculates bounding box
102 void scaleMesh(scene::IMesh *mesh, v3f scale)
107 core::aabbox3d<f32> bbox;
110 u32 mc = mesh->getMeshBufferCount();
111 for (u32 j = 0; j < mc; j++) {
112 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
113 const u32 stride = getVertexPitchFromType(buf->getVertexType());
114 u32 vertex_count = buf->getVertexCount();
115 u8 *vertices = (u8 *)buf->getVertices();
116 for (u32 i = 0; i < vertex_count; i++)
117 ((video::S3DVertex *)(vertices + i * stride))->Pos *= scale;
119 buf->recalculateBoundingBox();
121 // calculate total bounding box
123 bbox = buf->getBoundingBox();
125 bbox.addInternalBox(buf->getBoundingBox());
127 mesh->setBoundingBox(bbox);
130 void translateMesh(scene::IMesh *mesh, v3f vec)
135 core::aabbox3d<f32> bbox;
138 u32 mc = mesh->getMeshBufferCount();
139 for (u32 j = 0; j < mc; j++) {
140 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
141 const u32 stride = getVertexPitchFromType(buf->getVertexType());
142 u32 vertex_count = buf->getVertexCount();
143 u8 *vertices = (u8 *)buf->getVertices();
144 for (u32 i = 0; i < vertex_count; i++)
145 ((video::S3DVertex *)(vertices + i * stride))->Pos += vec;
147 buf->recalculateBoundingBox();
149 // calculate total bounding box
151 bbox = buf->getBoundingBox();
153 bbox.addInternalBox(buf->getBoundingBox());
155 mesh->setBoundingBox(bbox);
159 void setMeshColor(scene::IMesh *mesh, const video::SColor &color)
164 u32 mc = mesh->getMeshBufferCount();
165 for (u32 j = 0; j < mc; j++) {
166 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
167 const u32 stride = getVertexPitchFromType(buf->getVertexType());
168 u32 vertex_count = buf->getVertexCount();
169 u8 *vertices = (u8 *)buf->getVertices();
170 for (u32 i = 0; i < vertex_count; i++)
171 ((video::S3DVertex *)(vertices + i * stride))->Color = color;
175 void shadeMeshFaces(scene::IMesh *mesh)
180 u32 mc = mesh->getMeshBufferCount();
181 for (u32 j = 0; j < mc; j++) {
182 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
183 const u32 stride = getVertexPitchFromType(buf->getVertexType());
184 u32 vertex_count = buf->getVertexCount();
185 u8 *vertices = (u8 *)buf->getVertices();
186 for (u32 i = 0; i < vertex_count; i++) {
187 video::S3DVertex *vertex = (video::S3DVertex *)(vertices + i * stride);
188 video::SColor &vc = vertex->Color;
189 if (vertex->Normal.Y < -0.5) {
190 applyFacesShading (vc, 0.447213);
191 } else if (vertex->Normal.Z > 0.5) {
192 applyFacesShading (vc, 0.670820);
193 } else if (vertex->Normal.Z < -0.5) {
194 applyFacesShading (vc, 0.670820);
195 } else if (vertex->Normal.X > 0.5) {
196 applyFacesShading (vc, 0.836660);
197 } else if (vertex->Normal.X < -0.5) {
198 applyFacesShading (vc, 0.836660);
204 void setMeshColorByNormalXYZ(scene::IMesh *mesh,
205 const video::SColor &colorX,
206 const video::SColor &colorY,
207 const video::SColor &colorZ)
212 u16 mc = mesh->getMeshBufferCount();
213 for(u16 j=0; j<mc; j++)
215 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
216 video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
217 u16 vc = buf->getVertexCount();
218 for(u16 i=0; i<vc; i++)
220 f32 x = fabs(vertices[i].Normal.X);
221 f32 y = fabs(vertices[i].Normal.Y);
222 f32 z = fabs(vertices[i].Normal.Z);
224 vertices[i].Color = colorX;
226 vertices[i].Color = colorY;
228 vertices[i].Color = colorZ;
234 void rotateMeshXYby (scene::IMesh *mesh, f64 degrees)
236 u16 mc = mesh->getMeshBufferCount();
237 for(u16 j = 0; j < mc; j++)
239 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
240 video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
241 u16 vc = buf->getVertexCount();
242 for(u16 i = 0; i < vc; i++)
244 vertices[i].Pos.rotateXYBy(degrees);
249 void rotateMeshXZby (scene::IMesh *mesh, f64 degrees)
251 u16 mc = mesh->getMeshBufferCount();
252 for(u16 j = 0; j < mc; j++)
254 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
255 video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
256 u16 vc = buf->getVertexCount();
257 for(u16 i = 0; i < vc; i++)
259 vertices[i].Pos.rotateXZBy(degrees);
264 void rotateMeshYZby (scene::IMesh *mesh, f64 degrees)
266 u16 mc = mesh->getMeshBufferCount();
267 for(u16 j = 0; j < mc; j++)
269 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
270 video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
271 u16 vc = buf->getVertexCount();
272 for(u16 i = 0; i < vc; i++)
274 vertices[i].Pos.rotateYZBy(degrees);
279 void rotateMeshBy6dFacedir(scene::IMesh *mesh, int facedir)
281 int axisdir = facedir>>2;
284 u16 mc = mesh->getMeshBufferCount();
285 for(u16 j = 0; j < mc; j++)
287 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
288 video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
289 u16 vc = buf->getVertexCount();
290 for(u16 i=0; i<vc; i++)
296 vertices[i].Pos.rotateXZBy(-90);
297 else if(facedir == 2)
298 vertices[i].Pos.rotateXZBy(180);
299 else if(facedir == 3)
300 vertices[i].Pos.rotateXZBy(90);
303 vertices[i].Pos.rotateYZBy(90);
305 vertices[i].Pos.rotateXYBy(90);
306 else if(facedir == 2)
307 vertices[i].Pos.rotateXYBy(180);
308 else if(facedir == 3)
309 vertices[i].Pos.rotateXYBy(-90);
312 vertices[i].Pos.rotateYZBy(-90);
314 vertices[i].Pos.rotateXYBy(-90);
315 else if(facedir == 2)
316 vertices[i].Pos.rotateXYBy(180);
317 else if(facedir == 3)
318 vertices[i].Pos.rotateXYBy(90);
321 vertices[i].Pos.rotateXYBy(-90);
323 vertices[i].Pos.rotateYZBy(90);
324 else if(facedir == 2)
325 vertices[i].Pos.rotateYZBy(180);
326 else if(facedir == 3)
327 vertices[i].Pos.rotateYZBy(-90);
330 vertices[i].Pos.rotateXYBy(90);
332 vertices[i].Pos.rotateYZBy(-90);
333 else if(facedir == 2)
334 vertices[i].Pos.rotateYZBy(180);
335 else if(facedir == 3)
336 vertices[i].Pos.rotateYZBy(90);
339 vertices[i].Pos.rotateXYBy(-180);
341 vertices[i].Pos.rotateXZBy(90);
342 else if(facedir == 2)
343 vertices[i].Pos.rotateXZBy(180);
344 else if(facedir == 3)
345 vertices[i].Pos.rotateXZBy(-90);
354 void recalculateBoundingBox(scene::IMesh *src_mesh)
356 core::aabbox3d<f32> bbox;
358 for(u16 j = 0; j < src_mesh->getMeshBufferCount(); j++)
360 scene::IMeshBuffer *buf = src_mesh->getMeshBuffer(j);
361 buf->recalculateBoundingBox();
363 bbox = buf->getBoundingBox();
365 bbox.addInternalBox(buf->getBoundingBox());
367 src_mesh->setBoundingBox(bbox);
370 scene::IMesh* cloneMesh(scene::IMesh *src_mesh)
372 scene::SMesh* dst_mesh = new scene::SMesh();
373 for(u16 j = 0; j < src_mesh->getMeshBufferCount(); j++)
375 scene::IMeshBuffer *buf = src_mesh->getMeshBuffer(j);
376 video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
377 u16 *indices = (u16*)buf->getIndices();
378 scene::SMeshBuffer *temp_buf = new scene::SMeshBuffer();
379 temp_buf->append(vertices, buf->getVertexCount(),
380 indices, buf->getIndexCount());
381 dst_mesh->addMeshBuffer(temp_buf);
387 scene::IMesh* convertNodeboxNodeToMesh(ContentFeatures *f)
389 scene::SMesh* dst_mesh = new scene::SMesh();
390 for (u16 j = 0; j < 6; j++)
392 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
393 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
394 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
395 dst_mesh->addMeshBuffer(buf);
399 video::SColor c(255,255,255,255);
401 std::vector<aabb3f> boxes = f->node_box.fixed;
403 for(std::vector<aabb3f>::iterator
405 i != boxes.end(); i++)
410 if (box.MinEdge.X > box.MaxEdge.X)
413 box.MinEdge.X=box.MaxEdge.X;
416 if (box.MinEdge.Y > box.MaxEdge.Y)
419 box.MinEdge.Y=box.MaxEdge.Y;
422 if (box.MinEdge.Z > box.MaxEdge.Z)
425 box.MinEdge.Z=box.MaxEdge.Z;
428 // Compute texture coords
429 f32 tx1 = (box.MinEdge.X/BS)+0.5;
430 f32 ty1 = (box.MinEdge.Y/BS)+0.5;
431 f32 tz1 = (box.MinEdge.Z/BS)+0.5;
432 f32 tx2 = (box.MaxEdge.X/BS)+0.5;
433 f32 ty2 = (box.MaxEdge.Y/BS)+0.5;
434 f32 tz2 = (box.MaxEdge.Z/BS)+0.5;
437 tx1, 1-tz2, tx2, 1-tz1,
441 tz1, 1-ty2, tz2, 1-ty1,
443 1-tz2, 1-ty2, 1-tz1, 1-ty1,
445 1-tx2, 1-ty2, 1-tx1, 1-ty1,
447 tx1, 1-ty2, tx2, 1-ty1,
449 v3f min = box.MinEdge;
450 v3f max = box.MaxEdge;
452 video::S3DVertex vertices[24] =
455 video::S3DVertex(min.X,max.Y,max.Z, 0,1,0, c, txc[0],txc[1]),
456 video::S3DVertex(max.X,max.Y,max.Z, 0,1,0, c, txc[2],txc[1]),
457 video::S3DVertex(max.X,max.Y,min.Z, 0,1,0, c, txc[2],txc[3]),
458 video::S3DVertex(min.X,max.Y,min.Z, 0,1,0, c, txc[0],txc[3]),
460 video::S3DVertex(min.X,min.Y,min.Z, 0,-1,0, c, txc[4],txc[5]),
461 video::S3DVertex(max.X,min.Y,min.Z, 0,-1,0, c, txc[6],txc[5]),
462 video::S3DVertex(max.X,min.Y,max.Z, 0,-1,0, c, txc[6],txc[7]),
463 video::S3DVertex(min.X,min.Y,max.Z, 0,-1,0, c, txc[4],txc[7]),
465 video::S3DVertex(max.X,max.Y,min.Z, 1,0,0, c, txc[ 8],txc[9]),
466 video::S3DVertex(max.X,max.Y,max.Z, 1,0,0, c, txc[10],txc[9]),
467 video::S3DVertex(max.X,min.Y,max.Z, 1,0,0, c, txc[10],txc[11]),
468 video::S3DVertex(max.X,min.Y,min.Z, 1,0,0, c, txc[ 8],txc[11]),
470 video::S3DVertex(min.X,max.Y,max.Z, -1,0,0, c, txc[12],txc[13]),
471 video::S3DVertex(min.X,max.Y,min.Z, -1,0,0, c, txc[14],txc[13]),
472 video::S3DVertex(min.X,min.Y,min.Z, -1,0,0, c, txc[14],txc[15]),
473 video::S3DVertex(min.X,min.Y,max.Z, -1,0,0, c, txc[12],txc[15]),
475 video::S3DVertex(max.X,max.Y,max.Z, 0,0,1, c, txc[16],txc[17]),
476 video::S3DVertex(min.X,max.Y,max.Z, 0,0,1, c, txc[18],txc[17]),
477 video::S3DVertex(min.X,min.Y,max.Z, 0,0,1, c, txc[18],txc[19]),
478 video::S3DVertex(max.X,min.Y,max.Z, 0,0,1, c, txc[16],txc[19]),
480 video::S3DVertex(min.X,max.Y,min.Z, 0,0,-1, c, txc[20],txc[21]),
481 video::S3DVertex(max.X,max.Y,min.Z, 0,0,-1, c, txc[22],txc[21]),
482 video::S3DVertex(max.X,min.Y,min.Z, 0,0,-1, c, txc[22],txc[23]),
483 video::S3DVertex(min.X,min.Y,min.Z, 0,0,-1, c, txc[20],txc[23]),
486 u16 indices[] = {0,1,2,2,3,0};
488 for(u16 j = 0; j < 24; j += 4)
490 scene::IMeshBuffer *buf = dst_mesh->getMeshBuffer(j / 4);
491 buf->append(vertices + j, 4, indices, 6);
499 core::array<u32> tris;
512 const u16 cachesize = 32;
514 float FindVertexScore(vcache *v)
516 const float CacheDecayPower = 1.5f;
517 const float LastTriScore = 0.75f;
518 const float ValenceBoostScale = 2.0f;
519 const float ValenceBoostPower = 0.5f;
520 const float MaxSizeVertexCache = 32.0f;
522 if (v->NumActiveTris == 0)
524 // No tri needs this vertex!
529 int CachePosition = v->cachepos;
530 if (CachePosition < 0)
532 // Vertex is not in FIFO cache - no score.
536 if (CachePosition < 3)
538 // This vertex was used in the last triangle,
539 // so it has a fixed score.
540 Score = LastTriScore;
544 // Points for being high in the cache.
545 const float Scaler = 1.0f / (MaxSizeVertexCache - 3);
546 Score = 1.0f - (CachePosition - 3) * Scaler;
547 Score = powf(Score, CacheDecayPower);
551 // Bonus points for having a low number of tris still to
552 // use the vert, so we get rid of lone verts quickly.
553 float ValenceBoost = powf(v->NumActiveTris,
555 Score += ValenceBoostScale * ValenceBoost;
561 A specialized LRU cache for the Forsyth algorithm.
568 f_lru(vcache *v, tcache *t): vc(v), tc(t)
570 for (u16 i = 0; i < cachesize; i++)
576 // Adds this vertex index and returns the highest-scoring triangle index
577 u32 add(u16 vert, bool updatetris = false)
581 // Mark existing pos as empty
582 for (u16 i = 0; i < cachesize; i++)
584 if (cache[i] == vert)
586 // Move everything down
587 for (u16 j = i; j; j--)
589 cache[j] = cache[j - 1];
599 if (cache[cachesize-1] != -1)
600 vc[cache[cachesize-1]].cachepos = -1;
602 // Move everything down
603 for (u16 i = cachesize - 1; i; i--)
605 cache[i] = cache[i - 1];
616 // Update cache positions
617 for (u16 i = 0; i < cachesize; i++)
622 vc[cache[i]].cachepos = i;
623 vc[cache[i]].score = FindVertexScore(&vc[cache[i]]);
626 // Update triangle scores
627 for (u16 i = 0; i < cachesize; i++)
632 const u16 trisize = vc[cache[i]].tris.size();
633 for (u16 t = 0; t < trisize; t++)
635 tcache *tri = &tc[vc[cache[i]].tris[t]];
638 vc[tri->ind[0]].score +
639 vc[tri->ind[1]].score +
640 vc[tri->ind[2]].score;
642 if (tri->score > hiscore)
644 hiscore = tri->score;
645 highest = vc[cache[i]].tris[t];
655 s32 cache[cachesize];
661 Vertex cache optimization according to the Forsyth paper:
662 http://home.comcast.net/~tom_forsyth/papers/fast_vert_cache_opt.html
664 The function is thread-safe (read: you can optimize several meshes in different threads)
666 \param mesh Source mesh for the operation. */
667 scene::IMesh* createForsythOptimizedMesh(const scene::IMesh *mesh)
672 scene::SMesh *newmesh = new scene::SMesh();
673 newmesh->BoundingBox = mesh->getBoundingBox();
675 const u32 mbcount = mesh->getMeshBufferCount();
677 for (u32 b = 0; b < mbcount; ++b)
679 const scene::IMeshBuffer *mb = mesh->getMeshBuffer(b);
681 if (mb->getIndexType() != video::EIT_16BIT)
683 //os::Printer::log("Cannot optimize a mesh with 32bit indices", ELL_ERROR);
688 const u32 icount = mb->getIndexCount();
689 const u32 tcount = icount / 3;
690 const u32 vcount = mb->getVertexCount();
691 const u16 *ind = mb->getIndices();
693 vcache *vc = new vcache[vcount];
694 tcache *tc = new tcache[tcount];
699 for (u16 i = 0; i < vcount; i++)
703 vc[i].NumActiveTris = 0;
706 // First pass: count how many times a vert is used
707 for (u32 i = 0; i < icount; i += 3)
709 vc[ind[i]].NumActiveTris++;
710 vc[ind[i + 1]].NumActiveTris++;
711 vc[ind[i + 2]].NumActiveTris++;
713 const u32 tri_ind = i/3;
714 tc[tri_ind].ind[0] = ind[i];
715 tc[tri_ind].ind[1] = ind[i + 1];
716 tc[tri_ind].ind[2] = ind[i + 2];
719 // Second pass: list of each triangle
720 for (u32 i = 0; i < tcount; i++)
722 vc[tc[i].ind[0]].tris.push_back(i);
723 vc[tc[i].ind[1]].tris.push_back(i);
724 vc[tc[i].ind[2]].tris.push_back(i);
729 // Give initial scores
730 for (u16 i = 0; i < vcount; i++)
732 vc[i].score = FindVertexScore(&vc[i]);
734 for (u32 i = 0; i < tcount; i++)
737 vc[tc[i].ind[0]].score +
738 vc[tc[i].ind[1]].score +
739 vc[tc[i].ind[2]].score;
742 switch(mb->getVertexType())
744 case video::EVT_STANDARD:
746 video::S3DVertex *v = (video::S3DVertex *) mb->getVertices();
748 scene::SMeshBuffer *buf = new scene::SMeshBuffer();
749 buf->Material = mb->getMaterial();
751 buf->Vertices.reallocate(vcount);
752 buf->Indices.reallocate(icount);
754 core::map<const video::S3DVertex, const u16> sind; // search index for fast operation
755 typedef core::map<const video::S3DVertex, const u16>::Node snode;
762 if (tc[highest].drawn)
766 for (u32 t = 0; t < tcount; t++)
770 if (tc[t].score > hiscore)
773 hiscore = tc[t].score;
782 // Output the best triangle
783 u16 newind = buf->Vertices.size();
785 snode *s = sind.find(v[tc[highest].ind[0]]);
789 buf->Vertices.push_back(v[tc[highest].ind[0]]);
790 buf->Indices.push_back(newind);
791 sind.insert(v[tc[highest].ind[0]], newind);
796 buf->Indices.push_back(s->getValue());
799 s = sind.find(v[tc[highest].ind[1]]);
803 buf->Vertices.push_back(v[tc[highest].ind[1]]);
804 buf->Indices.push_back(newind);
805 sind.insert(v[tc[highest].ind[1]], newind);
810 buf->Indices.push_back(s->getValue());
813 s = sind.find(v[tc[highest].ind[2]]);
817 buf->Vertices.push_back(v[tc[highest].ind[2]]);
818 buf->Indices.push_back(newind);
819 sind.insert(v[tc[highest].ind[2]], newind);
823 buf->Indices.push_back(s->getValue());
826 vc[tc[highest].ind[0]].NumActiveTris--;
827 vc[tc[highest].ind[1]].NumActiveTris--;
828 vc[tc[highest].ind[2]].NumActiveTris--;
830 tc[highest].drawn = true;
832 for (u16 j = 0; j < 3; j++)
834 vcache *vert = &vc[tc[highest].ind[j]];
835 for (u16 t = 0; t < vert->tris.size(); t++)
837 if (highest == vert->tris[t])
845 lru.add(tc[highest].ind[0]);
846 lru.add(tc[highest].ind[1]);
847 highest = lru.add(tc[highest].ind[2], true);
851 buf->setBoundingBox(mb->getBoundingBox());
852 newmesh->addMeshBuffer(buf);
856 case video::EVT_2TCOORDS:
858 video::S3DVertex2TCoords *v = (video::S3DVertex2TCoords *) mb->getVertices();
860 scene::SMeshBufferLightMap *buf = new scene::SMeshBufferLightMap();
861 buf->Material = mb->getMaterial();
863 buf->Vertices.reallocate(vcount);
864 buf->Indices.reallocate(icount);
866 core::map<const video::S3DVertex2TCoords, const u16> sind; // search index for fast operation
867 typedef core::map<const video::S3DVertex2TCoords, const u16>::Node snode;
874 if (tc[highest].drawn)
878 for (u32 t = 0; t < tcount; t++)
882 if (tc[t].score > hiscore)
885 hiscore = tc[t].score;
894 // Output the best triangle
895 u16 newind = buf->Vertices.size();
897 snode *s = sind.find(v[tc[highest].ind[0]]);
901 buf->Vertices.push_back(v[tc[highest].ind[0]]);
902 buf->Indices.push_back(newind);
903 sind.insert(v[tc[highest].ind[0]], newind);
908 buf->Indices.push_back(s->getValue());
911 s = sind.find(v[tc[highest].ind[1]]);
915 buf->Vertices.push_back(v[tc[highest].ind[1]]);
916 buf->Indices.push_back(newind);
917 sind.insert(v[tc[highest].ind[1]], newind);
922 buf->Indices.push_back(s->getValue());
925 s = sind.find(v[tc[highest].ind[2]]);
929 buf->Vertices.push_back(v[tc[highest].ind[2]]);
930 buf->Indices.push_back(newind);
931 sind.insert(v[tc[highest].ind[2]], newind);
935 buf->Indices.push_back(s->getValue());
938 vc[tc[highest].ind[0]].NumActiveTris--;
939 vc[tc[highest].ind[1]].NumActiveTris--;
940 vc[tc[highest].ind[2]].NumActiveTris--;
942 tc[highest].drawn = true;
944 for (u16 j = 0; j < 3; j++)
946 vcache *vert = &vc[tc[highest].ind[j]];
947 for (u16 t = 0; t < vert->tris.size(); t++)
949 if (highest == vert->tris[t])
957 lru.add(tc[highest].ind[0]);
958 lru.add(tc[highest].ind[1]);
959 highest = lru.add(tc[highest].ind[2]);
963 buf->setBoundingBox(mb->getBoundingBox());
964 newmesh->addMeshBuffer(buf);
969 case video::EVT_TANGENTS:
971 video::S3DVertexTangents *v = (video::S3DVertexTangents *) mb->getVertices();
973 scene::SMeshBufferTangents *buf = new scene::SMeshBufferTangents();
974 buf->Material = mb->getMaterial();
976 buf->Vertices.reallocate(vcount);
977 buf->Indices.reallocate(icount);
979 core::map<const video::S3DVertexTangents, const u16> sind; // search index for fast operation
980 typedef core::map<const video::S3DVertexTangents, const u16>::Node snode;
987 if (tc[highest].drawn)
991 for (u32 t = 0; t < tcount; t++)
995 if (tc[t].score > hiscore)
998 hiscore = tc[t].score;
1007 // Output the best triangle
1008 u16 newind = buf->Vertices.size();
1010 snode *s = sind.find(v[tc[highest].ind[0]]);
1014 buf->Vertices.push_back(v[tc[highest].ind[0]]);
1015 buf->Indices.push_back(newind);
1016 sind.insert(v[tc[highest].ind[0]], newind);
1021 buf->Indices.push_back(s->getValue());
1024 s = sind.find(v[tc[highest].ind[1]]);
1028 buf->Vertices.push_back(v[tc[highest].ind[1]]);
1029 buf->Indices.push_back(newind);
1030 sind.insert(v[tc[highest].ind[1]], newind);
1035 buf->Indices.push_back(s->getValue());
1038 s = sind.find(v[tc[highest].ind[2]]);
1042 buf->Vertices.push_back(v[tc[highest].ind[2]]);
1043 buf->Indices.push_back(newind);
1044 sind.insert(v[tc[highest].ind[2]], newind);
1048 buf->Indices.push_back(s->getValue());
1051 vc[tc[highest].ind[0]].NumActiveTris--;
1052 vc[tc[highest].ind[1]].NumActiveTris--;
1053 vc[tc[highest].ind[2]].NumActiveTris--;
1055 tc[highest].drawn = true;
1057 for (u16 j = 0; j < 3; j++)
1059 vcache *vert = &vc[tc[highest].ind[j]];
1060 for (u16 t = 0; t < vert->tris.size(); t++)
1062 if (highest == vert->tris[t])
1064 vert->tris.erase(t);
1070 lru.add(tc[highest].ind[0]);
1071 lru.add(tc[highest].ind[1]);
1072 highest = lru.add(tc[highest].ind[2]);
1076 buf->setBoundingBox(mb->getBoundingBox());
1077 newmesh->addMeshBuffer(buf);
1086 } // for each meshbuffer