source: GTP/trunk/App/Demos/Illum/PathMap/TriangleMesh.cpp @ 896

Revision 896, 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                                                   D3DVERTEX* 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//      radion.radiance.z = getSurfaceArea();
363}
364
365Vector* TriangleMesh::Patch::meshVertices = 0x0;
366Vector* TriangleMesh::Patch::meshNormals = 0x0;
367Vector* TriangleMesh::Patch::meshTexCoords = 0x0;
368
369bool TriangleMesh::intersect (const Ray& ray, float& depth, float rayMin, float rayMax)
370{
371        lastTestedRayId = ray.id;
372        lastTestedRayResult.isIntersect = false;
373        Patch::meshNormals = normals;
374        Patch::meshTexCoords = texCoords;
375        HitRec hitRec;
376        meshTree->traverse(ray, hitRec, rayMin, rayMax);
377        lastTestedRayResult = hitRec;
378        lastTestedRayResult.material = this->material;
379        depth = lastTestedRayResult.depth;
380        lastTestedRayResult.object = this;
381        return lastTestedRayResult.isIntersect;
382}
383
384bool TriangleMesh::intersectBackSide (const Ray& ray, float& depth, float rayMin, float rayMax)
385{
386        lastTestedRayId = ray.id;
387        lastTestedRayResult.isIntersect = false;
388        Patch::meshNormals = normals;
389        HitRec hitRec;
390        meshTree->traverseBackSide(ray, hitRec, rayMin, rayMax);
391//      meshTree->forbidden = hitRec.object;
392        lastTestedRayResult = hitRec;
393        lastTestedRayResult.material = this->material;
394        depth = lastTestedRayResult.depth;
395        lastTestedRayResult.object = this;
396        return lastTestedRayResult.isIntersect;
397}
398
399TriangleMesh::~TriangleMesh(void)
400{
401        delete [] areaTree;
402        delete meshTree;
403        delete meshVertices;
404        delete [] meshPatches;
405        delete normals;
406        delete texCoords;
407}
408
409
410double TriangleMesh::getPatchArea(unsigned int index)
411{
412        if(index >= nMeshPatches)
413                return 0;
414        Vector a = meshVertices[meshPatches[index].vertexIndices[1]] -
415                        meshVertices[meshPatches[index].vertexIndices[0]];
416        Vector b = meshVertices[meshPatches[index].vertexIndices[2]] -
417                        meshVertices[meshPatches[index].vertexIndices[0]];
418        return (a && b).norm();
419}
420
421double TriangleMesh::buildAreaTree(unsigned int u)
422{
423        if(u >= nAreaTreeNodes)
424        {
425                u -= nAreaTreeNodes;
426                return getPatchArea(u);
427        }
428        areaTree[u] = buildAreaTree(u * 2 + 1) + buildAreaTree(u * 2 + 2);
429        return areaTree[u];
430}
431
432void TriangleMesh::buildAreaTree()
433{
434        nAreaTreeNodes = 1;
435        while(nAreaTreeNodes < nMeshPatches - 1)
436                nAreaTreeNodes <<= 1;
437        nAreaTreeNodes--;
438        areaTree = new double[nAreaTreeNodes];
439        surfaceArea = buildAreaTree(0);
440}
441
442void TriangleMesh::sampleSurface(unsigned int u, double rnd, Radion& radion)
443{
444        if(u >= nAreaTreeNodes)
445        {
446                u -= nAreaTreeNodes;
447                if(u >= nMeshPatches)
448                        u = 0;
449                meshPatches[u].sampleSurface(radion);
450                return;
451        }
452        float leftweight = 0.0f;
453        if(u * 2 + 1 >= nAreaTreeNodes)
454                leftweight = getPatchArea(u * 2 + 1 - nAreaTreeNodes);
455        else
456                leftweight = areaTree[u * 2 + 1];
457        if(rnd <= leftweight)
458                sampleSurface(u * 2 + 1, rnd, radion);
459        else
460                sampleSurface(u * 2 + 2, rnd - leftweight, radion);
461}
462
463void TriangleMesh::sampleSurface(Radion& radion)
464{
465        Patch::meshVertices = meshVertices;
466        Patch::meshNormals = normals;
467        Patch::meshTexCoords = texCoords;
468        double rnd = surfaceArea * (double)rand() / RAND_MAX;
469        sampleSurface(0, rnd, radion);
470        radion.radiance.z = surfaceArea;
471}
472
473float TriangleMesh::getSurfaceArea()
474{
475        return surfaceArea;
476}
Note: See TracBrowser for help on using the repository browser.