////////////////////////////////////////////////////////////////////////// // Given the position, normal, and set of rays compute the bent normal and // occlusion term. ////////////////////////////////////////////////////////////////////////// void ComputeOcclusion (NmRawPointD* newPos, NmRawPointD* newNorm, int numTris, NmRawTriangle* tri, AtiOctree* octree, int numRays, NmRawPointD* rays, double* rayWeights, NmRawPointD* bentNormal, double* occlusion, int& gMaxCells, AtiOctreeCell** &gCell) { #ifdef _DEBUG if ((newPos == NULL) || (newNorm == NULL) || (tri == NULL) || (octree == NULL) || (rays == NULL) || (rayWeights == NULL) || (bentNormal == NULL) || (occlusion == NULL)) { //NmPrint ("ERROR: Incorrect arguments passed!\n"); exit (-1); } #endif // Clear results. // Bent normal should at minimum be the regular normal (I think). bentNormal->x = newNorm->x; bentNormal->y = newNorm->y; bentNormal->z = newNorm->z; (*occlusion) = 0.0; double hit = 0.0f; double num = 0.0f; // Compute offset vertex NmRawPointD pos; pos.x = newPos->x + (newNorm->x * gDistanceOffset); pos.y = newPos->y + (newNorm->y * gDistanceOffset); pos.z = newPos->z + (newNorm->z * gDistanceOffset); // Compute rotation matrix to match hemisphere to normal double rotMat[16]; FromToRotation (rotMat, gZVec, newNorm->v); // Shoot the rays for (int r = 0; r < numRays; r++) { // First rotate the ray into position NmRawPointD oRay; oRay.x = rays[r].x*rotMat[0] + rays[r].y*rotMat[4] + rays[r].z*rotMat[8]; oRay.y = rays[r].x*rotMat[1] + rays[r].y*rotMat[5] + rays[r].z*rotMat[9]; oRay.z = rays[r].x*rotMat[2] + rays[r].y*rotMat[6] + rays[r].z*rotMat[10]; // Walk the Octree to find triangle intersections. bool intersect = false; int numCells = 0; int cellCount = 0; int triCount = 0; AddCell (octree->m_root, &numCells, gMaxCells, gCell); while ((numCells > 0) && !intersect) { // Take the cell from the list. cellCount++; numCells--; AtiOctreeCell* currCell = gCell[numCells]; // See if this is a leaf node bool leaf = true; for (int c = 0; c < 8; c++) { if (currCell->m_children[c] != NULL) { leaf = false; break; } } // If we are a leaf check the triangles if (leaf) { // Run through the triangles seeing if the ray intersects. for (int t = 0; t < currCell->m_numItems; t++) { // Save off current triangle. NmRawTriangle* currTri = &(tri[currCell->m_item[t]]); triCount++; // See if it intersects. double oT, oU, oV; if (IntersectTriangle (pos.v, oRay.v, currTri->vert[0].v, currTri->vert[1].v, currTri->vert[2].v, &oT, &oU, &oV)) { if (oT > 0.0f) { intersect = true; break; } } } // end for t (num triangles in this cell) } // end if leaf else { // Non-leaf, add the children to the list if their bounding // box intersects the ray. for (int c = 0; c < 8; c++) { if (currCell->m_children[c] != NULL) { // Save off current child. AtiOctreeCell* child = currCell->m_children[c]; // If the ray intersects the box if (RayIntersectsBox (&pos, &oRay, &child->m_boundingBox)) { AddCell (child, &numCells, gMaxCells, gCell); } // end if the ray intersects this bounding box. // else do nothing, we'll never intersect any triangles // for it's children. } // end if we have a cell } // end for c (8 children) } // end else non-leaf node. } // end while cells // Update our running results based on if we found and intersection. num += rayWeights[r]; if (!intersect) { bentNormal->x += (oRay.x * rayWeights[r]); bentNormal->y += (oRay.y * rayWeights[r]); bentNormal->z += (oRay.z * rayWeights[r]); } else { hit += rayWeights[r]; } /* // Save off some stats. if (triCount > gAOMaxTrisTested) { gAOMaxTrisTested = triCount; } if (cellCount > gAOMaxCellsTested) { gAOMaxCellsTested = cellCount; } */ } // end for r (number of rays) // Normalize result Normalize (bentNormal->v); (*occlusion) = (num - hit) / num; } // end of ComputeOcclusion
Matrix3 Matrix3::CreateRotation( const Vec3D& vFrom, const Vec3D& vTo ) { FLOAT mat[3][3]; FromToRotation( vFrom.ToPtr(), vTo.ToPtr(), mat ); return Matrix3( mat ); }