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

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