source: GTP/trunk/App/Demos/Illum/pathmap/TriangleMesh.cpp @ 2498

Revision 2498, 15.0 KB checked in by szirmay, 18 years ago (diff)
Line 
1#include "dxstdafx.h"
2#include "trianglemesh.h"
3#include "Radion.hpp"
4
5TriangleMesh::TriangleMesh(Material* material, unsigned short* indexBuffer, unsigned int nFaces,
6                                                   FlexVertexArray& vertexBuffer, unsigned int nVertices)
7{
8        this->material = material;
9        nMeshVertices = nVertices;
10        nMeshPatches = nFaces;
11
12        meshVertices = new Vector[nMeshVertices];
13        normals = new Vector[nMeshVertices];
14        texCoords = new Vector[nMeshVertices];
15        for(int u=0; u < nMeshVertices; u++)
16        {
17                meshVertices[u] = vertexBuffer[u].pos();
18                normals[u] = vertexBuffer[u].normal();
19                texCoords[u] = vertexBuffer[u].tex0();
20        }
21       
22        meshPatches = new Patch[nMeshPatches];
23
24        int pup = 0;
25        int p = 0;
26        for(p = 0; p < nMeshPatches; p++)
27        {
28                meshPatches[p].vertexIndices[0] = indexBuffer[pup++];
29                meshPatches[p].vertexIndices[1] = indexBuffer[pup++];
30                meshPatches[p].vertexIndices[2] = indexBuffer[pup++];
31        }
32        //calculate normals
33        for(p = 0; p < nMeshPatches; p++)
34        {
35                meshPatches[p].flatNormal = (
36                        meshVertices[meshPatches[p].vertexIndices[0]] -
37                        meshVertices[meshPatches[p].vertexIndices[1]]
38                        )
39                        &&
40                        (
41                        meshVertices[meshPatches[p].vertexIndices[0]] -
42                        meshVertices[meshPatches[p].vertexIndices[2]]
43                        );
44                meshPatches[p].flatNormal.normalize();
45                normals[meshPatches[p].vertexIndices[0]] += meshPatches[p].flatNormal;
46                normals[meshPatches[p].vertexIndices[1]] += meshPatches[p].flatNormal;
47                normals[meshPatches[p].vertexIndices[2]] += meshPatches[p].flatNormal;
48                meshPatches[p].hyperPlaneShiftOffset =
49                        meshVertices[meshPatches[p].vertexIndices[0]] *
50                                                meshPatches[p].flatNormal;
51
52                Vector A[3];
53                A[0] = meshVertices[meshPatches[p].vertexIndices[0]];
54                A[1] = meshVertices[meshPatches[p].vertexIndices[1]];
55                A[2] = meshVertices[meshPatches[p].vertexIndices[2]];
56                float           t4 = A[0][0]*A[1][1];
57                float       t6 = A[0][0]*A[1][2];
58                float       t8 = A[0][1]*A[1][0];
59                float       t10 = A[0][2]*A[1][0];
60                float       t12 = A[0][1]*A[2][0];
61                float       t14 = A[0][2]*A[2][0];
62                float       t17 = 1/(t4*A[2][2]-t6*A[2][1]-t8*A[2][2]+t10*A[2][1]+t12*A[1][2]-t14*A[1][1]);
63       
64//              if(_isnan (t17) )
65//          AfxMessageBox("mtx inversion gbz");
66
67                Vector* m = meshPatches[p].inverseVertexMatrix;
68               
69                m[0][0] = (A[1][1]*A[2][2]-A[1][2]*A[2][1])*t17;
70                m[1][0] = -(A[0][1]*A[2][2]-A[0][2]*A[2][1])*t17;
71                m[2][0] = -(-A[0][1]*A[1][2]+A[0][2]*A[1][1])*t17;
72                m[0][1] = -(A[1][0]*A[2][2]-A[1][2]*A[2][0])*t17;
73                m[1][1] = (A[0][0]*A[2][2]-t14)*t17;
74                m[2][1] = -(t6-t10)*t17;
75                m[0][2] = -(-A[1][0]*A[2][1]+A[1][1]*A[2][0])*t17;
76                m[1][2] = -(A[0][0]*A[2][1]-t12)*t17;
77                m[2][2] = (t4-t8)*t17;
78
79                meshPatches[p].bbox.minPoint = meshVertices[meshPatches[p].vertexIndices[0]];
80                meshPatches[p].bbox.minPoint <= meshVertices[meshPatches[p].vertexIndices[1]];
81                meshPatches[p].bbox.minPoint <= meshVertices[meshPatches[p].vertexIndices[2]];
82
83                meshPatches[p].bbox.maxPoint = meshVertices[meshPatches[p].vertexIndices[0]];
84                meshPatches[p].bbox.maxPoint >= meshVertices[meshPatches[p].vertexIndices[1]];
85                meshPatches[p].bbox.maxPoint >= meshVertices[meshPatches[p].vertexIndices[2]];
86        }
87        for(int n=0; n<nMeshVertices; n++)
88        {
89                normals[n].normalize();
90        }
91        Intersectable** objs = new Intersectable*[nMeshPatches];
92        for(int t=0; t<nMeshPatches; t++)
93                objs[t] = meshPatches + t;
94        meshTree = new KDTree(objs, nMeshPatches);
95        bbox = meshTree->getBoundingBox();
96        delete objs;
97
98        buildAreaTree();
99}
100
101TriangleMesh::TriangleMesh(std::istream& isc, Material** materialTable, int nMaterials)
102{
103        char keyword[100];
104        isc >> keyword; //material
105        isc >> keyword;
106        for(int i=0; i < nMaterials; i++)
107        {
108                material = materialTable[i];
109                if(strcmp(keyword, material->getName()) == 0) break;
110        }
111        isc >> keyword;
112        isc >> nMeshVertices;
113        meshVertices = new Vector[nMeshVertices];
114        normals = new Vector[nMeshVertices];
115        for(int v=0; v<nMeshVertices; v++)
116        {
117                float a, b, c;
118                isc >> a >> b >> c;
119//              meshVertices[v] = Vector(a + (0.1f * (float)rand() / RAND_MAX),
120//                      b + (0.1f * (float)rand() / RAND_MAX),
121//                      c + (0.1f * (float)rand() / RAND_MAX));
122                meshVertices[v] = Vector(a , b, c);
123                normals[v].clear();
124        }
125        bbox.minPoint = meshVertices[0];
126        bbox.maxPoint = meshVertices[0];
127        for(int w=1; w<nMeshVertices; w++)
128        {
129                bbox.minPoint <= meshVertices[w];
130                bbox.maxPoint >= meshVertices[w];
131        }
132        isc >> keyword;
133        isc >> nMeshPatches;
134        meshPatches = new Patch[nMeshPatches];
135        int p;
136        for(p = 0; p < nMeshPatches; p++)
137        {
138                signed int ai, bi, ci;
139                isc >> ai >> bi >> ci;
140//              if(di < 0)
141                {
142                        meshPatches[p].vertexIndices[0] = ai;
143                        meshPatches[p].vertexIndices[1] = bi;
144                        meshPatches[p].vertexIndices[2] = ci;
145                }
146/*              else    //quad, tessellate
147                {
148                        meshPatches[p].vertexIndices[0] = ai;
149                        meshPatches[p].vertexIndices[1] = bi;
150                        meshPatches[p].vertexIndices[2] = ci;
151                        p++;
152                        meshPatches[p].vertexIndices[0] = ai;
153                        meshPatches[p].vertexIndices[1] = ci;
154                        meshPatches[p].vertexIndices[2] = di;
155                        isc >> ai; //final -1
156                }*/
157        }
158        //calculate normals
159        for(p = 0; p < nMeshPatches; p++)
160        {
161                meshPatches[p].flatNormal = (
162                        meshVertices[meshPatches[p].vertexIndices[0]] -
163                        meshVertices[meshPatches[p].vertexIndices[1]]
164                        )
165                        &&
166                        (
167                        meshVertices[meshPatches[p].vertexIndices[0]] -
168                        meshVertices[meshPatches[p].vertexIndices[2]]
169                        );
170                meshPatches[p].flatNormal.normalize();
171                normals[meshPatches[p].vertexIndices[0]] += meshPatches[p].flatNormal;
172                normals[meshPatches[p].vertexIndices[1]] += meshPatches[p].flatNormal;
173                normals[meshPatches[p].vertexIndices[2]] += meshPatches[p].flatNormal;
174                meshPatches[p].hyperPlaneShiftOffset =
175                        meshVertices[meshPatches[p].vertexIndices[0]] *
176                                                meshPatches[p].flatNormal;
177
178                Vector A[3];
179                A[0] = meshVertices[meshPatches[p].vertexIndices[0]];
180                A[1] = meshVertices[meshPatches[p].vertexIndices[1]];
181                A[2] = meshVertices[meshPatches[p].vertexIndices[2]];
182                float           t4 = A[0][0]*A[1][1];
183                float       t6 = A[0][0]*A[1][2];
184                float       t8 = A[0][1]*A[1][0];
185                float       t10 = A[0][2]*A[1][0];
186                float       t12 = A[0][1]*A[2][0];
187                float       t14 = A[0][2]*A[2][0];
188                float       t17 = 1/(t4*A[2][2]-t6*A[2][1]-t8*A[2][2]+t10*A[2][1]+t12*A[1][2]-t14*A[1][1]);
189       
190//              if(_isnan (t17) )
191//          AfxMessageBox("mtx inversion gbz");
192
193                Vector* m = meshPatches[p].inverseVertexMatrix;
194               
195                m[0][0] = (A[1][1]*A[2][2]-A[1][2]*A[2][1])*t17;
196                m[1][0] = -(A[0][1]*A[2][2]-A[0][2]*A[2][1])*t17;
197                m[2][0] = -(-A[0][1]*A[1][2]+A[0][2]*A[1][1])*t17;
198                m[0][1] = -(A[1][0]*A[2][2]-A[1][2]*A[2][0])*t17;
199                m[1][1] = (A[0][0]*A[2][2]-t14)*t17;
200                m[2][1] = -(t6-t10)*t17;
201                m[0][2] = -(-A[1][0]*A[2][1]+A[1][1]*A[2][0])*t17;
202                m[1][2] = -(A[0][0]*A[2][1]-t12)*t17;
203                m[2][2] = (t4-t8)*t17;
204
205                meshPatches[p].bbox.minPoint = meshVertices[meshPatches[p].vertexIndices[0]];
206                meshPatches[p].bbox.minPoint <= meshVertices[meshPatches[p].vertexIndices[1]];
207                meshPatches[p].bbox.minPoint <= meshVertices[meshPatches[p].vertexIndices[2]];
208
209                meshPatches[p].bbox.maxPoint = meshVertices[meshPatches[p].vertexIndices[0]];
210                meshPatches[p].bbox.maxPoint >= meshVertices[meshPatches[p].vertexIndices[1]];
211                meshPatches[p].bbox.maxPoint >= meshVertices[meshPatches[p].vertexIndices[2]];
212        }
213        for(int n=0; n<nMeshVertices; n++)
214        {
215                normals[n].normalize();
216        }
217        Intersectable** objs = new Intersectable*[nMeshPatches];
218        for(int t=0; t<nMeshPatches; t++)
219                objs[t] = meshPatches + t;
220        meshTree = new KDTree(objs, nMeshPatches);
221        bbox = meshTree->getBoundingBox();
222        delete objs;
223}
224
225void TriangleMesh::getTransformedBoundingBox(const Transformation& tf, BoundingBox& bb)
226{
227        Vector tfdvec;
228        tf.transformPoint(meshVertices[0], tfdvec);
229        bb.minPoint = tfdvec;
230        bb.maxPoint = tfdvec;
231        for(int w=1; w<nMeshVertices; w++)
232        {
233                tf.transformPoint(meshVertices[w], tfdvec);
234                bb.minPoint <= tfdvec;
235                bb.maxPoint >= tfdvec;
236        }
237        bb.minPoint.x -= 0.01;
238        bb.minPoint.y -= 0.01;
239        bb.minPoint.z -= 0.01;
240        bb.maxPoint.x += 0.01;
241        bb.maxPoint.y += 0.01;
242        bb.maxPoint.z += 0.01;
243}
244
245bool TriangleMesh::Patch::intersectBackSide (const Ray& ray, float& depth, float rayMin, float rayMax)
246{
247        lastTestedRayId = ray.id;
248        lastTestedRayResult.isIntersect = false;
249
250        float cosa = flatNormal * ray.dir;
251        if (cosa < 0.00001f)    // front facing triangle
252                return false;
253
254        float originDistOnNormal = -(flatNormal * ray.origin);
255        depth = (hyperPlaneShiftOffset + originDistOnNormal) / cosa;
256        if (depth < 0.01f)
257                return false;
258
259        Vector hitPoint = ray.origin;
260        hitPoint.addScaled(depth, ray.dir);
261
262        float baryA = hitPoint * inverseVertexMatrix[0];
263        if(baryA < -0.0001f) return false;
264        float baryB = hitPoint * inverseVertexMatrix[1];
265        if(baryB < -0.0001f) return false;
266        float baryC = hitPoint * inverseVertexMatrix[2];
267        if(baryC < -0.0001f) return false;
268
269        if(ray.isShadowRay)
270        {
271                //faster way to tell
272                lastTestedRayResult.isIntersect = true;
273                lastTestedRayResult.depth               = depth;
274                return true;
275        }
276
277        lastTestedRayResult.normal.setScaled(baryA, meshNormals[vertexIndices[0]]);
278        lastTestedRayResult.normal.addScaled(baryB, meshNormals[vertexIndices[1]]);
279        lastTestedRayResult.normal.addScaled(baryC, meshNormals[vertexIndices[2]]);
280
281        lastTestedRayResult.texUV.setScaled(baryA, meshTexCoords[vertexIndices[0]]);
282        lastTestedRayResult.texUV.addScaled(baryB, meshTexCoords[vertexIndices[1]]);
283        lastTestedRayResult.texUV.addScaled(baryC, meshTexCoords[vertexIndices[2]]);
284
285        lastTestedRayResult.isIntersect = true;
286        lastTestedRayResult.depth               = depth;
287        lastTestedRayResult.point               = hitPoint;
288        lastTestedRayResult.object              = this;
289        return true;
290}
291
292bool TriangleMesh::Patch::intersect (const Ray& ray, float& depth, float rayMin, float rayMax)
293{
294        lastTestedRayId = ray.id;
295        lastTestedRayResult.isIntersect = false;
296
297        float cosa = flatNormal * ray.dir;
298        if (cosa > -0.00001f)   // back facing triangle
299                return false;
300
301        float originDistOnNormal = -(flatNormal * ray.origin);
302        depth = (hyperPlaneShiftOffset + originDistOnNormal) / cosa;
303        if (depth < 0.0f)
304                return false;
305
306        Vector hitPoint = ray.origin;
307        hitPoint.addScaled(depth, ray.dir);
308
309        float baryA = hitPoint * inverseVertexMatrix[0];
310        if(baryA < -0.1f) return false;
311        float baryB = hitPoint * inverseVertexMatrix[1];
312        if(baryB <  -0.1f) return false;
313        float baryC = hitPoint * inverseVertexMatrix[2];
314        if(baryC <  -0.1f) return false;
315
316        if(ray.isShadowRay)
317        {
318                //faster way to tell
319                lastTestedRayResult.isIntersect = true;
320                lastTestedRayResult.depth               = depth;
321                return true;
322        }
323
324        lastTestedRayResult.normal.setScaled(baryA, meshNormals[vertexIndices[0]]);
325        lastTestedRayResult.normal.addScaled(baryB, meshNormals[vertexIndices[1]]);
326        lastTestedRayResult.normal.addScaled(baryC, meshNormals[vertexIndices[2]]);
327//      lastTestedRayResult.normal = flatNormal;
328
329        lastTestedRayResult.texUV.setScaled(baryA, meshTexCoords[vertexIndices[0]]);
330        lastTestedRayResult.texUV.addScaled(baryB, meshTexCoords[vertexIndices[1]]);
331        lastTestedRayResult.texUV.addScaled(baryC, meshTexCoords[vertexIndices[2]]);
332
333        lastTestedRayResult.isIntersect = true;
334        lastTestedRayResult.depth               = depth;
335        lastTestedRayResult.point               = hitPoint;
336        return true;
337}
338
339void TriangleMesh::Patch::sampleSurface(Radion& radion)
340{
341        Vector u = meshVertices[vertexIndices[1]] - meshVertices[vertexIndices[0]];
342        Vector v = meshVertices[vertexIndices[2]] - meshVertices[vertexIndices[0]];
343        double r1 = (double)rand() / RAND_MAX;
344        double r2 = (double)rand() / RAND_MAX;
345        if(r1 + r2 > 1.0)
346        {
347                r1 = 1.0 - r1;
348                r2 = 1.0 - r2;
349        }
350        radion.position = meshVertices[vertexIndices[0]] + u * r1 + v * r2;
351        float baryA = (r1 + r2) * 0.5f;
352        float baryB = (1.0f - r1) * 0.5f;
353        float baryC = (1.0f - r2) * 0.5f;
354
355        radion.normal.setScaled(baryA, meshNormals[vertexIndices[0]]);
356        radion.normal.addScaled(baryB, meshNormals[vertexIndices[1]]);
357        radion.normal.addScaled(baryC, meshNormals[vertexIndices[2]]);
358
359        radion.radiance.setScaled(baryA, meshTexCoords[vertexIndices[0]]);
360        radion.radiance.addScaled(baryB, meshTexCoords[vertexIndices[1]]);
361        radion.radiance.addScaled(baryC, meshTexCoords[vertexIndices[2]]);
362
363        if(radion.radiance.norm2() < 0.00001)
364                bool mijafa = true;
365
366//      radion.radiance.z = getSurfaceArea();
367}
368
369Vector* TriangleMesh::Patch::meshVertices = 0x0;
370Vector* TriangleMesh::Patch::meshNormals = 0x0;
371Vector* TriangleMesh::Patch::meshTexCoords = 0x0;
372
373bool TriangleMesh::intersect (const Ray& ray, float& depth, float rayMin, float rayMax)
374{
375        lastTestedRayId = ray.id;
376        lastTestedRayResult.isIntersect = false;
377        Patch::meshNormals = normals;
378        Patch::meshTexCoords = texCoords;
379        HitRec hitRec;
380        meshTree->traverse(ray, hitRec, rayMin, rayMax);
381        lastTestedRayResult = hitRec;
382        lastTestedRayResult.material = this->material;
383        depth = lastTestedRayResult.depth;
384        lastTestedRayResult.object = this;
385        return lastTestedRayResult.isIntersect;
386}
387
388bool TriangleMesh::intersectBackSide (const Ray& ray, float& depth, float rayMin, float rayMax)
389{
390        lastTestedRayId = ray.id;
391        lastTestedRayResult.isIntersect = false;
392        Patch::meshNormals = normals;
393        HitRec hitRec;
394        meshTree->traverseBackSide(ray, hitRec, rayMin, rayMax);
395//      meshTree->forbidden = hitRec.object;
396        lastTestedRayResult = hitRec;
397        lastTestedRayResult.material = this->material;
398        depth = lastTestedRayResult.depth;
399        lastTestedRayResult.object = this;
400        return lastTestedRayResult.isIntersect;
401}
402
403TriangleMesh::~TriangleMesh(void)
404{
405        delete [] areaTree;
406        delete meshTree;
407        delete meshVertices;
408        delete [] meshPatches;
409        delete normals;
410        delete texCoords;
411}
412
413
414double TriangleMesh::getPatchArea(unsigned int index)
415{
416        if(index >= nMeshPatches)
417                return 0;
418        Vector a = meshVertices[meshPatches[index].vertexIndices[1]] -
419                        meshVertices[meshPatches[index].vertexIndices[0]];
420        Vector b = meshVertices[meshPatches[index].vertexIndices[2]] -
421                        meshVertices[meshPatches[index].vertexIndices[0]];
422        return (a && b).norm();
423}
424
425double TriangleMesh::buildAreaTree(unsigned int u)
426{
427        if(u >= nAreaTreeNodes)
428        {
429                u -= nAreaTreeNodes;
430                return getPatchArea(u);
431        }
432        areaTree[u] = buildAreaTree(u * 2 + 1) + buildAreaTree(u * 2 + 2);
433        return areaTree[u];
434}
435
436void TriangleMesh::buildAreaTree()
437{
438        nAreaTreeNodes = 1;
439        while(nAreaTreeNodes < nMeshPatches  )
440                nAreaTreeNodes <<= 1;
441        nAreaTreeNodes--;
442        areaTree = new double[nAreaTreeNodes];
443        surfaceArea = buildAreaTree(0);
444}
445
446void TriangleMesh::sampleSurface(unsigned int u, double rnd, Radion& radion)
447{
448        if(u >= nAreaTreeNodes)
449        {
450                u -= nAreaTreeNodes;
451                if(u >= nMeshPatches)
452                        u = 0;
453                meshPatches[u].sampleSurface(radion);
454                return;
455        }
456        float leftweight = 0.0f;
457        if(u * 2 + 1 >= nAreaTreeNodes)
458                leftweight = getPatchArea(u * 2 + 1 - nAreaTreeNodes);
459        else
460                leftweight = areaTree[u * 2 + 1];
461        if(rnd <= leftweight)
462                sampleSurface(u * 2 + 1, rnd, radion);
463        else
464                sampleSurface(u * 2 + 2, rnd - leftweight, radion);
465}
466
467void TriangleMesh::sampleSurface(Radion& radion)
468{
469        Patch::meshVertices = meshVertices;
470        Patch::meshNormals = normals;
471        Patch::meshTexCoords = texCoords;
472        double rnd = surfaceArea * (double)rand() / RAND_MAX;
473        sampleSurface(0, rnd, radion);
474        radion.radiance.z = surfaceArea;
475}
476
477float TriangleMesh::getSurfaceArea()
478{
479        return surfaceArea;
480}
Note: See TracBrowser for help on using the repository browser.