absence_thelab

view src/3deng/3dgeom.cpp @ 0:1cffe3409164

initial commit
author John Tsiombikas <nuclear@member.fsf.org>
date Thu, 23 Oct 2014 01:46:07 +0300
parents
children
line source
1 #include <cassert>
2 #include "3dgeom.h"
3 #include "3dengine.h"
5 using std::vector;
7 TexCoord::TexCoord(float u, float v) {
8 this->u = u;
9 this->v = v;
10 }
12 // Vertex class implementation
14 Vertex::Vertex() {
15 color = 0x00ffffff;
16 memset(tex, 0, 4*sizeof(TexCoord));
17 }
19 Vertex::Vertex(const Vector3 &position, float tu, float tv, dword color) {
20 pos = position;
21 tex[0].u = tex[1].u = tex[2].u = tex[3].u = tu;
22 tex[0].v = tex[1].v = tex[2].v = tex[3].v = tv;
23 this->color = color;
24 }
26 void Vertex::CalculateNormal(const Vertex *vbuffer, const Triangle *triangles, long trinum) {
28 // find the position of the curent vertex in the vertex buffer
29 dword index = (dword)(this - vbuffer);
31 normal = Vector3(0, 0, 0);
32 const Triangle *tri = triangles;
33 for(int i=0; i<trinum; i++, tri++) {
34 if(tri->vertices[0] == index || tri->vertices[1] == index || tri->vertices[2] == index) {
35 normal += tri->normal;
36 }
37 }
39 normal.Normalize();
40 }
42 /////////// Edge class implementation ///////////
44 Edge::Edge() {
45 vertices[0] = vertices[1] = adjfaces[0] = adjfaces[1] = 0;
46 }
48 Edge::Edge(Index v1, Index v2, Index af1, Index af2) {
49 vertices[0] = v1;
50 vertices[1] = v2;
51 adjfaces[0] = af1;
52 adjfaces[1] = af2;
53 }
55 /////////// Triangle class implementation /////////////
56 Triangle::Triangle(Index v1, Index v2, Index v3) {
57 vertices[0] = v1;
58 vertices[1] = v2;
59 vertices[2] = v3;
60 }
62 void Triangle::CalculateNormal(Vertex *vbuffer, bool normalize) {
63 Vector3 v1 = vbuffer[vertices[1]].pos - vbuffer[vertices[0]].pos;
64 Vector3 v2 = vbuffer[vertices[2]].pos - vbuffer[vertices[0]].pos;
65 normal = v1.CrossProduct(v2);
66 if(normalize) normal.Normalize();
67 }
70 /////////////// Triangular Mesh implementation /////////////
72 TriMesh::TriMesh(byte LODLevels, GraphicsContext *gc) {
73 memset(this, 0, sizeof(TriMesh));
74 this->gc = gc;
75 Levels = LODLevels;
77 varray = new Vertex*[Levels];
78 memset(varray, 0, Levels * sizeof(Vertex*));
80 triarray = new Triangle*[Levels];
81 memset(triarray, 0, Levels * sizeof(Triangle*));
83 vbuffer = new VertexBuffer*[Levels];
84 memset(vbuffer, 0, Levels * sizeof(VertexBuffer*));
86 ibuffer = new IndexBuffer*[Levels];
87 memset(ibuffer, 0, Levels * sizeof(IndexBuffer*));
89 AdjTriangles = new std::vector<dword>*[Levels];
90 memset(AdjTriangles, 0, Levels * sizeof(std::vector<dword>*));
92 VertexCount = new dword[Levels];
93 TriCount = new dword[Levels];
95 BuffersValid = new bool[Levels];
96 memset(BuffersValid, 0, Levels * sizeof(bool));
98 AdjValid = new bool[Levels];
99 memset(AdjValid, 0, Levels * sizeof(bool));
100 }
102 TriMesh::TriMesh(const TriMesh &mesh) {
104 memcpy(this, &mesh, sizeof(TriMesh));
106 BuffersValid = new bool[Levels];
107 memset(BuffersValid, 0, Levels * sizeof(bool));
109 varray = new Vertex*[Levels];
110 triarray = new Triangle*[Levels];
111 vbuffer = new VertexBuffer*[Levels];
112 ibuffer = new IndexBuffer*[Levels];
114 VertexCount = new dword[Levels];
115 TriCount = new dword[Levels];
117 for(int i=0; i<Levels; i++) {
119 VertexCount[i] = mesh.VertexCount[i];
120 TriCount[i] = mesh.TriCount[i];
122 varray[i] = new Vertex[VertexCount[i]];
123 triarray[i] = new Triangle[TriCount[i]];
125 memcpy(varray[i], mesh.varray[i], VertexCount[i] * sizeof(Vertex));
126 memcpy(triarray[i], mesh.triarray[i], TriCount[i] * sizeof(Triangle));
128 vbuffer[i] = 0;
129 ibuffer[i] = 0;
131 UpdateSystemBuffers(i);
132 }
133 }
135 TriMesh::~TriMesh() {
136 if(varray) {
137 for(int i=0; i<Levels; i++) {
138 delete [] varray[i];
139 }
140 delete [] varray;
141 }
143 if(triarray) {
144 for(int i=0; i<Levels; i++) {
145 delete [] triarray[i];
146 }
147 delete triarray;
148 }
150 if(vbuffer) {
151 for(int i=0; i<Levels; i++) {
152 if(vbuffer[i]) vbuffer[i]->Release();
153 }
154 }
155 if(ibuffer) {
156 for(int i=0; i<Levels; i++) {
157 if(ibuffer[i]) ibuffer[i]->Release();
158 }
159 }
161 if(AdjTriangles) {
162 for(int i=0; i<Levels; i++) {
163 delete [] AdjTriangles[i];
164 }
165 delete AdjTriangles;
166 }
167 }
169 const TriMesh &TriMesh::operator =(const TriMesh &mesh) {
170 memcpy(this, &mesh, sizeof(TriMesh));
172 BuffersValid = new bool[Levels];
173 memset(BuffersValid, 0, Levels * sizeof(bool));
175 varray = new Vertex*[Levels];
176 triarray = new Triangle*[Levels];
177 vbuffer = new VertexBuffer*[Levels];
178 ibuffer = new IndexBuffer*[Levels];
180 VertexCount = new dword[Levels];
181 TriCount = new dword[Levels];
183 for(int i=0; i<Levels; i++) {
185 VertexCount[i] = mesh.VertexCount[i];
186 TriCount[i] = mesh.TriCount[i];
188 varray[i] = new Vertex[VertexCount[i]];
189 triarray[i] = new Triangle[TriCount[i]];
191 memcpy(varray[i], mesh.varray[i], VertexCount[i] * sizeof(Vertex));
192 memcpy(triarray[i], mesh.triarray[i], TriCount[i] * sizeof(Triangle));
194 vbuffer[i] = 0;
195 ibuffer[i] = 0;
197 UpdateSystemBuffers(i);
198 }
199 return mesh;
200 }
203 const Vertex *TriMesh::GetVertexArray(byte level) const {
204 if(level >= Levels) return 0;
205 return varray[level];
206 }
208 const Triangle *TriMesh::GetTriangleArray(byte level) const {
209 if(level >= Levels) return 0;
210 return triarray[level];
211 }
214 Vertex *TriMesh::GetModVertexArray() {
215 memset(BuffersValid, 0, Levels * sizeof(bool));
216 return varray[0];
217 }
219 Triangle *TriMesh::GetModTriangleArray() {
220 memset(BuffersValid, 0, Levels * sizeof(bool));
221 memset(AdjValid, 0, Levels * sizeof(bool));
222 return triarray[0];
223 }
225 const VertexBuffer *TriMesh::GetVertexBuffer(byte level) const {
226 if(level >= Levels) return 0;
228 if(!BuffersValid[level]) {
229 const_cast<TriMesh*>(this)->UpdateSystemBuffers(level);
230 }
231 return vbuffer[level];
232 }
234 const IndexBuffer *TriMesh::GetIndexBuffer(byte level) const {
235 if(level >= Levels) return 0;
237 if(!BuffersValid[level]) {
238 const_cast<TriMesh*>(this)->UpdateSystemBuffers(level);
239 }
241 return ibuffer[level];
242 }
245 dword TriMesh::GetVertexCount(byte level) const {
246 if(level >= Levels) return 0xdeadbeef;
247 return VertexCount[level];
248 }
250 dword TriMesh::GetTriangleCount(byte level) const {
251 if(level >= Levels) return 0xdeadbeef;
252 return TriCount[level];
253 }
255 byte TriMesh::GetLevelCount() const {
256 return Levels;
257 }
259 void TriMesh::SetGraphicsContext(GraphicsContext *gc) {
260 this->gc = gc;
261 memset(BuffersValid, 0, Levels * sizeof(bool)); // invalidate all system buffers in all levels
262 }
264 void TriMesh::SetData(const Vertex *vdata, const Triangle *tridata, dword vcount, dword tricount) {
266 memset(BuffersValid, 0, Levels * sizeof(bool));
267 memset(AdjValid, 0, Levels * sizeof(bool));
269 if(varray[0]) delete [] varray[0];
270 if(triarray[0]) delete [] triarray[0];
271 varray[0] = new Vertex[vcount];
272 triarray[0] = new Triangle[tricount];
274 if(vdata) memcpy(varray[0], vdata, vcount * sizeof(Vertex));
275 if(tridata) memcpy(triarray[0], tridata, tricount * sizeof(Triangle));
276 VertexCount[0] = vcount;
277 TriCount[0] = tricount;
279 UpdateLODChain();
280 }
282 bool TriMesh::UpdateSystemBuffers(byte level) {
284 if(!gc || level >= Levels) return false;
286 if(vbuffer[level]) {
287 D3DVERTEXBUFFER_DESC vbdesc;
288 vbuffer[level]->GetDesc(&vbdesc);
289 if(vbdesc.Size / sizeof(Vertex) != VertexCount[level]) {
290 vbuffer[level]->Release();
292 if(gc->D3DDevice->CreateVertexBuffer(VertexCount[level] * sizeof(Vertex), dynamic ? D3DUSAGE_DYNAMIC : 0, VertexFormat, D3DPOOL_DEFAULT, &vbuffer[level]) != D3D_OK) {
293 return false;
294 }
295 }
296 } else {
297 if(gc->D3DDevice->CreateVertexBuffer(VertexCount[level] * sizeof(Vertex), dynamic ? D3DUSAGE_DYNAMIC : 0, VertexFormat, D3DPOOL_DEFAULT, &vbuffer[level]) != D3D_OK) {
298 return false;
299 }
300 }
302 Vertex *vbdata;
303 Lock(vbuffer[level], &vbdata);
304 memcpy(vbdata, varray[level], VertexCount[level] * sizeof(Vertex));
305 Unlock(vbuffer[level]);
307 if(ibuffer[level]) {
308 D3DINDEXBUFFER_DESC ibdesc;
309 ibuffer[level]->GetDesc(&ibdesc);
310 if(ibdesc.Size / IndexSize != TriCount[level] * 3) {
311 ibuffer[level]->Release();
313 if(gc->D3DDevice->CreateIndexBuffer(TriCount[level] * 3 * IndexSize, dynamic ? D3DUSAGE_DYNAMIC : 0, IndexFormat, D3DPOOL_DEFAULT, &ibuffer[level]) != D3D_OK) {
314 return false;
315 }
316 }
317 } else {
318 if(gc->D3DDevice->CreateIndexBuffer(TriCount[level] * 3 * IndexSize, dynamic ? D3DUSAGE_DYNAMIC : 0, IndexFormat, D3DPOOL_DEFAULT, &ibuffer[level]) != D3D_OK) {
319 return false;
320 }
321 }
324 Index *ibdata;
325 Lock(ibuffer[level], &ibdata);
326 for(dword i=0; i<TriCount[level]; i++) {
327 *ibdata++ = triarray[level][i].vertices[0];
328 *ibdata++ = triarray[level][i].vertices[1];
329 *ibdata++ = triarray[level][i].vertices[2];
330 }
331 Unlock(ibuffer[level]);
333 BuffersValid[level] = true;
334 return true;
335 }
337 void TriMesh::UpdateLODChain() {
338 for(byte i=1; i<Levels; i++) {
339 // TODO: apply mesh optimization, for now, just copy as it is
340 VertexCount[i] = VertexCount[0];
341 TriCount[i] = TriCount[0];
343 if(!varray[i]) varray[i] = new Vertex[VertexCount[i]];
344 memcpy(varray[i], varray[0], VertexCount[i] * sizeof(Vertex));
346 if(!triarray[i]) triarray[i] = new Triangle[TriCount[i]];
347 memcpy(triarray[i], triarray[0], TriCount[i] * sizeof(Triangle));
349 UpdateSystemBuffers(i);
350 }
352 if(!BuffersValid[0]) UpdateSystemBuffers(0);
353 }
355 // TODO: this will brake currently with multiple LOD levels, revise LOD normal calculation
356 // and revise UpdateLODChain() too
357 void TriMesh::CalculateNormals() {
358 memset(BuffersValid, 0, Levels * sizeof(bool));
360 Triangle *tri = triarray[0];
361 Triangle *tend = tri + TriCount[0];
363 while(tri != tend) {
364 (*tri++).CalculateNormal(varray[0], false);
365 }
367 /*
368 Vertex *vert = varray[0];
369 Vertex *vend = vert + VertexCount[0];
371 while(vert != vend) {
372 (*vert++).CalculateNormal(varray[0], triarray[0], TriCount[0]);
373 }
374 */
376 if(!AdjValid[0]) {
377 if(AdjTriangles[0]) delete [] AdjTriangles[0];
378 AdjTriangles[0] = new std::vector<dword>[VertexCount[0]];
379 }
381 for(dword i=0; i<VertexCount[0]; i++) {
382 if(AdjValid[0]) {
383 assert(AdjTriangles[0]);
384 Vector3 normal(0.0f, 0.0f, 0.0f);
385 for(dword j=0; j<AdjTriangles[0][i].size(); j++) {
386 normal += triarray[0][AdjTriangles[0][i][j]].normal;
387 }
388 normal.Normalize();
389 varray[0][i].normal = normal;
390 } else {
392 AdjTriangles[0][i].erase(AdjTriangles[0][i].begin(), AdjTriangles[0][i].end());
393 Vector3 normal(0.0f, 0.0f, 0.0f);
394 for(dword j=0; j<TriCount[0]; j++) {
395 if(triarray[0][j].vertices[0] == i || triarray[0][j].vertices[1] == i || triarray[0][j].vertices[2] == i) {
396 AdjTriangles[0][i].push_back(j);
397 normal += triarray[0][j].normal;
398 }
399 }
400 normal.Normalize();
401 varray[0][i].normal = normal;
402 }
403 }
405 AdjValid[0] = true;
407 UpdateLODChain();
408 }
410 void TriMesh::CalculateNormalsFast() {
411 memset(BuffersValid, 0, Levels * sizeof(bool));
413 Triangle *tri = triarray[0];
414 Triangle *tend = tri + TriCount[0];
416 while(tri != tend) {
417 tri->CalculateNormal(varray[0], true);
418 varray[0][tri->vertices[0]].normal = tri->normal;
419 varray[0][tri->vertices[1]].normal = tri->normal;
420 varray[0][tri->vertices[2]].normal = tri->normal;
421 tri++;
422 }
424 UpdateLODChain();
425 }
427 void TriMesh::ChangeMode(TriMeshMode mode) {
428 dynamic = mode == TriMeshDynamic;
429 }
431 /*
433 void TriMesh::CalculateEdges() {
435 //build a list of triangles that share each vertex
436 std::list<Triangle*> *ShareTris = new std::list<Triangle*>[VertexCount[0]];
438 for(dword i=0; i<VertexCount[0]; i++) {
439 for(dword j=0; j<TriCount[0]; j++) {
440 Index VertexIndex = (Index)((Vertex*)&varray[0][i] - (Vertex*)&varray[0][0]);
441 if(triarray[0][j].vertices[0] == VertexIndex || triarray[0][j].vertices[1] == VertexIndex || triarray[0][j].vertices[2] == VertexIndex) {
442 ShareTris[i].push_back(&triarray[0][j]); // if it references this vertex add it
443 }
444 }
445 }
447 // find the adjacent triangles of each edge
448 for(dword i=0; i<TriCount[0]; i++) {
449 Triangle *tri = &triarray[0][i];
451 for(int j=0; j<3; j++) {
452 tri->edges[j].vertices[0] = tri->vertices[j];
453 tri->edges[j].vertices[1] = tri->vertices[(j+1) % 3];
454 tri->edges[j].adjfaces[0] = (Index)i;
455 }
457 for(int j=0; j<3; j++) {
458 Index v0 = (Index)((Vertex*)&varray[0][tri->edges[j].vertices[0]] - (Vertex*)&varray[0][0]);
459 Index v1 = (Index)((Vertex*)&varray[0][tri->edges[j].vertices[1]] - (Vertex*)&varray[0][0]);
461 std::list<Triangle*>::iterator iter = ShareTris[v0].begin();
462 while(iter != ShareTris[v0].end()) {
463 Index TriIndex = (Index)(*iter - &triarray[0][0]);
465 if((TriIndex != i) && ((*iter)->vertices[0] == v1 || (*iter)->vertices[1] == v1 || (*iter)->vertices[2] == v1)) {
466 tri->edges[j].adjfaces[1] = TriIndex;
467 break;
468 }
469 iter++;
470 }
471 if(iter == ShareTris[v0].end()) tri->edges[j].adjfaces[1] = (Index)0xffffffff;
472 }
473 }
475 // TODO: wield duplicate edges
476 }
478 */