]> git.lizzy.rs Git - irrlicht.git/blob - source/Irrlicht/CMeshManipulator.cpp
Revert "Fix: Listbox was sometimes sending EGET_LISTBOX_SELECTED_AGAIN instead of...
[irrlicht.git] / source / Irrlicht / CMeshManipulator.cpp
1 // Copyright (C) 2002-2012 Nikolaus Gebhardt\r
2 // This file is part of the "Irrlicht Engine".\r
3 // For conditions of distribution and use, see copyright notice in irrlicht.h\r
4 \r
5 #include "CMeshManipulator.h"\r
6 #include "ISkinnedMesh.h"\r
7 #include "SMesh.h"\r
8 #include "CMeshBuffer.h"\r
9 #include "SAnimatedMesh.h"\r
10 #include "os.h"\r
11 #include "triangle3d.h"\r
12 \r
13 namespace irr\r
14 {\r
15 namespace scene\r
16 {\r
17 \r
18 static inline core::vector3df getAngleWeight(const core::vector3df& v1,\r
19                 const core::vector3df& v2,\r
20                 const core::vector3df& v3)\r
21 {\r
22         // Calculate this triangle's weight for each of its three vertices\r
23         // start by calculating the lengths of its sides\r
24         const f32 a = v2.getDistanceFromSQ(v3);\r
25         const f32 asqrt = sqrtf(a);\r
26         const f32 b = v1.getDistanceFromSQ(v3);\r
27         const f32 bsqrt = sqrtf(b);\r
28         const f32 c = v1.getDistanceFromSQ(v2);\r
29         const f32 csqrt = sqrtf(c);\r
30 \r
31         // use them to find the angle at each vertex\r
32         return core::vector3df(\r
33                 acosf((b + c - a) / (2.f * bsqrt * csqrt)),\r
34                 acosf((-b + c + a) / (2.f * asqrt * csqrt)),\r
35                 acosf((b - c + a) / (2.f * bsqrt * asqrt)));\r
36 }\r
37 \r
38 \r
39 namespace\r
40 {\r
41 template <typename T>\r
42 void recalculateNormalsT(IMeshBuffer* buffer, bool smooth, bool angleWeighted)\r
43 {\r
44         const u32 vtxcnt = buffer->getVertexCount();\r
45         const u32 idxcnt = buffer->getIndexCount();\r
46         const T* idx = reinterpret_cast<T*>(buffer->getIndices());\r
47 \r
48         if (!smooth)\r
49         {\r
50                 for (u32 i=0; i<idxcnt; i+=3)\r
51                 {\r
52                         const core::vector3df& v1 = buffer->getPosition(idx[i+0]);\r
53                         const core::vector3df& v2 = buffer->getPosition(idx[i+1]);\r
54                         const core::vector3df& v3 = buffer->getPosition(idx[i+2]);\r
55                         const core::vector3df normal = core::plane3d<f32>(v1, v2, v3).Normal;\r
56                         buffer->getNormal(idx[i+0]) = normal;\r
57                         buffer->getNormal(idx[i+1]) = normal;\r
58                         buffer->getNormal(idx[i+2]) = normal;\r
59                 }\r
60         }\r
61         else\r
62         {\r
63                 u32 i;\r
64 \r
65                 for ( i = 0; i!= vtxcnt; ++i )\r
66                         buffer->getNormal(i).set(0.f, 0.f, 0.f);\r
67 \r
68                 for ( i=0; i<idxcnt; i+=3)\r
69                 {\r
70                         const core::vector3df& v1 = buffer->getPosition(idx[i+0]);\r
71                         const core::vector3df& v2 = buffer->getPosition(idx[i+1]);\r
72                         const core::vector3df& v3 = buffer->getPosition(idx[i+2]);\r
73                         const core::vector3df normal = core::plane3d<f32>(v1, v2, v3).Normal;\r
74 \r
75                         core::vector3df weight(1.f,1.f,1.f);\r
76                         if (angleWeighted)\r
77                                 weight = irr::scene::getAngleWeight(v1,v2,v3); // writing irr::scene:: necessary for borland\r
78 \r
79                         buffer->getNormal(idx[i+0]) += weight.X*normal;\r
80                         buffer->getNormal(idx[i+1]) += weight.Y*normal;\r
81                         buffer->getNormal(idx[i+2]) += weight.Z*normal;\r
82                 }\r
83 \r
84                 for ( i = 0; i!= vtxcnt; ++i )\r
85                         buffer->getNormal(i).normalize();\r
86         }\r
87 }\r
88 }\r
89 \r
90 \r
91 //! Recalculates all normals of the mesh buffer.\r
92 /** \param buffer: Mesh buffer on which the operation is performed. */\r
93 void CMeshManipulator::recalculateNormals(IMeshBuffer* buffer, bool smooth, bool angleWeighted) const\r
94 {\r
95         if (!buffer)\r
96                 return;\r
97 \r
98         if (buffer->getIndexType()==video::EIT_16BIT)\r
99                 recalculateNormalsT<u16>(buffer, smooth, angleWeighted);\r
100         else\r
101                 recalculateNormalsT<u32>(buffer, smooth, angleWeighted);\r
102 }\r
103 \r
104 \r
105 //! Recalculates all normals of the mesh.\r
106 //! \param mesh: Mesh on which the operation is performed.\r
107 void CMeshManipulator::recalculateNormals(scene::IMesh* mesh, bool smooth, bool angleWeighted) const\r
108 {\r
109         if (!mesh)\r
110                 return;\r
111 \r
112         if (mesh->getMeshType() == EAMT_SKINNED)\r
113         {\r
114                 ISkinnedMesh *smesh = (ISkinnedMesh *) mesh;\r
115                 smesh->resetAnimation();\r
116         }\r
117 \r
118         const u32 bcount = mesh->getMeshBufferCount();\r
119         for ( u32 b=0; b<bcount; ++b)\r
120                 recalculateNormals(mesh->getMeshBuffer(b), smooth, angleWeighted);\r
121 \r
122         if (mesh->getMeshType() == EAMT_SKINNED)\r
123         {\r
124                 ISkinnedMesh *smesh = (ISkinnedMesh *) mesh;\r
125                 smesh->refreshJointCache();\r
126         }\r
127 }\r
128 \r
129 \r
130 //! Clones a static IMesh into a modifyable SMesh.\r
131 // not yet 32bit\r
132 SMesh* CMeshManipulator::createMeshCopy(scene::IMesh* mesh) const\r
133 {\r
134         if (!mesh)\r
135                 return 0;\r
136 \r
137         SMesh* clone = new SMesh();\r
138 \r
139         const u32 meshBufferCount = mesh->getMeshBufferCount();\r
140 \r
141         for ( u32 b=0; b<meshBufferCount; ++b)\r
142         {\r
143                 const IMeshBuffer* const mb = mesh->getMeshBuffer(b);\r
144                 switch(mb->getVertexType())\r
145                 {\r
146                 case video::EVT_STANDARD:\r
147                         {\r
148                                 SMeshBuffer* buffer = new SMeshBuffer();\r
149                                 buffer->Material = mb->getMaterial();\r
150                                 const u32 vcount = mb->getVertexCount();\r
151                                 buffer->Vertices.reallocate(vcount);\r
152                                 video::S3DVertex* vertices = (video::S3DVertex*)mb->getVertices();\r
153                                 for (u32 i=0; i < vcount; ++i)\r
154                                         buffer->Vertices.push_back(vertices[i]);\r
155                                 const u32 icount = mb->getIndexCount();\r
156                                 buffer->Indices.reallocate(icount);\r
157                                 const u16* indices = mb->getIndices();\r
158                                 for (u32 i=0; i < icount; ++i)\r
159                                         buffer->Indices.push_back(indices[i]);\r
160                                 clone->addMeshBuffer(buffer);\r
161                                 buffer->drop();\r
162                         }\r
163                         break;\r
164                 case video::EVT_2TCOORDS:\r
165                         {\r
166                                 SMeshBufferLightMap* buffer = new SMeshBufferLightMap();\r
167                                 buffer->Material = mb->getMaterial();\r
168                                 const u32 vcount = mb->getVertexCount();\r
169                                 buffer->Vertices.reallocate(vcount);\r
170                                 video::S3DVertex2TCoords* vertices = (video::S3DVertex2TCoords*)mb->getVertices();\r
171                                 for (u32 i=0; i < vcount; ++i)\r
172                                         buffer->Vertices.push_back(vertices[i]);\r
173                                 const u32 icount = mb->getIndexCount();\r
174                                 buffer->Indices.reallocate(icount);\r
175                                 const u16* indices = mb->getIndices();\r
176                                 for (u32 i=0; i < icount; ++i)\r
177                                         buffer->Indices.push_back(indices[i]);\r
178                                 clone->addMeshBuffer(buffer);\r
179                                 buffer->drop();\r
180                         }\r
181                         break;\r
182                 case video::EVT_TANGENTS:\r
183                         {\r
184                                 SMeshBufferTangents* buffer = new SMeshBufferTangents();\r
185                                 buffer->Material = mb->getMaterial();\r
186                                 const u32 vcount = mb->getVertexCount();\r
187                                 buffer->Vertices.reallocate(vcount);\r
188                                 video::S3DVertexTangents* vertices = (video::S3DVertexTangents*)mb->getVertices();\r
189                                 for (u32 i=0; i < vcount; ++i)\r
190                                         buffer->Vertices.push_back(vertices[i]);\r
191                                 const u32 icount = mb->getIndexCount();\r
192                                 buffer->Indices.reallocate(icount);\r
193                                 const u16* indices = mb->getIndices();\r
194                                 for (u32 i=0; i < icount; ++i)\r
195                                         buffer->Indices.push_back(indices[i]);\r
196                                 clone->addMeshBuffer(buffer);\r
197                                 buffer->drop();\r
198                         }\r
199                         break;\r
200                 }// end switch\r
201 \r
202         }// end for all mesh buffers\r
203 \r
204         clone->BoundingBox = mesh->getBoundingBox();\r
205         return clone;\r
206 }\r
207 \r
208 \r
209 //! Returns amount of polygons in mesh.\r
210 s32 CMeshManipulator::getPolyCount(scene::IMesh* mesh) const\r
211 {\r
212         if (!mesh)\r
213                 return 0;\r
214 \r
215         s32 trianglecount = 0;\r
216 \r
217         for (u32 g=0; g<mesh->getMeshBufferCount(); ++g)\r
218                 trianglecount += mesh->getMeshBuffer(g)->getIndexCount() / 3;\r
219 \r
220         return trianglecount;\r
221 }\r
222 \r
223 \r
224 //! Returns amount of polygons in mesh.\r
225 s32 CMeshManipulator::getPolyCount(scene::IAnimatedMesh* mesh) const\r
226 {\r
227         if (mesh && mesh->getFrameCount() != 0)\r
228                 return getPolyCount(mesh->getMesh(0));\r
229 \r
230         return 0;\r
231 }\r
232 \r
233 \r
234 //! create a new AnimatedMesh and adds the mesh to it\r
235 IAnimatedMesh * CMeshManipulator::createAnimatedMesh(scene::IMesh* mesh, scene::E_ANIMATED_MESH_TYPE type) const\r
236 {\r
237         return new SAnimatedMesh(mesh, type);\r
238 }\r
239 \r
240 \r
241 } // end namespace scene\r
242 } // end namespace irr\r
243 \r