int testhit_trianglevoxel(int triid, int vx, int vy, int vz) { float boxcenter[3]; float boxhalfsize[3]; float triverts[3][3]; boxcenter[0] = vx + (float)VOXELSIZEX/2; boxcenter[1] = vy + (float)VOXELSIZEY/2; boxcenter[2] = vz + (float)VOXELSIZEZ/2; boxhalfsize[0] = (float)VOXELSIZEX/2; boxhalfsize[1] = (float)VOXELSIZEY/2; boxhalfsize[2] = (float)VOXELSIZEZ/2; triverts[0][0] = scene_triinfos[triid].v0.x; triverts[0][1] = scene_triinfos[triid].v0.y; triverts[0][2] = scene_triinfos[triid].v0.z; triverts[1][0] = scene_triinfos[triid].v1.x; triverts[1][1] = scene_triinfos[triid].v1.y; triverts[1][2] = scene_triinfos[triid].v1.z; triverts[2][0] = scene_triinfos[triid].v2.x; triverts[2][1] = scene_triinfos[triid].v2.y; triverts[2][2] = scene_triinfos[triid].v2.z; return triBoxOverlap(boxcenter, boxhalfsize, triverts); }
bool CharacterController::colliding(Vector3 center, Vector3 half, Vector3 a, Vector3 b, Vector3 c) { float tri[3][3]; tri[0][0] = a.x; tri[0][1] = a.y; tri[0][2] = a.z; tri[1][0] = b.x; tri[1][1] = b.y; tri[1][2] = b.z; tri[2][0] = c.x; tri[2][1] = c.y; tri[2][2] = c.z; float halfsize[3]; halfsize[0] = half.x; halfsize[1] = half.y; halfsize[2] = half.z; float _center[3]; _center[0] = center.x; _center[1] = center.y; _center[2] = center.z; if(triBoxOverlap(_center, halfsize, tri) != 0) { return true; } return false; }
bool Triangle::intersectsBox(AABB box) const { Vector3d bcenter = (box.minCorner + box.maxCorner) / 2.0; float boxcenter[3]; boxcenter[0] = bcenter[0]; boxcenter[1] = bcenter[1]; boxcenter[2] = bcenter[2]; Vector3d bhalfsize = (box.maxCorner - box.minCorner) / 2.0; bhalfsize += Vector3d::Constant(EPSILON * 1000); float boxhalfsize[3]; boxhalfsize[0] = bhalfsize[0]; boxhalfsize[1] = bhalfsize[1]; boxhalfsize[2] = bhalfsize[2]; float triverts[3][3]; triverts[0][0] = p1[0]; triverts[0][1] = p1[1]; triverts[0][2] = p1[2]; triverts[1][0] = p2[0]; triverts[1][1] = p2[1]; triverts[1][2] = p2[2]; triverts[2][0] = p3[0]; triverts[2][1] = p3[1]; triverts[2][2] = p3[2]; return triBoxOverlap(boxcenter, boxhalfsize, triverts); }
bool containsTriangle(const float *p1,const float *p2,const float *p3) const { float boxCenter[3]; float boxHalfSize[3]; float triVerts[3][3]; boxCenter[0] = (mMin[0]+mMax[0])*0.5f; boxCenter[1] = (mMin[1]+mMax[1])*0.5f; boxCenter[2] = (mMin[2]+mMax[2])*0.5f; boxHalfSize[0] = (mMax[0]-mMin[0])*0.5f; boxHalfSize[1] = (mMax[1]-mMin[1])*0.5f; boxHalfSize[2] = (mMax[2]-mMin[2])*0.5f; triVerts[0][0] = p1[0]; triVerts[0][1] = p1[1]; triVerts[0][2] = p1[2]; triVerts[1][0] = p2[0]; triVerts[1][1] = p2[1]; triVerts[1][2] = p2[2]; triVerts[2][0] = p3[0]; triVerts[2][1] = p3[1]; triVerts[2][2] = p3[2]; int ret = triBoxOverlap(boxCenter,boxHalfSize,triVerts); return ret == 1 ? true : false; }
bool testIntersectionTriBox(const Vec3f *_pts, const Box &_box) { //float pt[3][3]; /* pt[0][0] = _pts[0].x; pt[0][1] = _pts[0].y; pt[0][2] = _pts[0].z; pt[1][0] = _pts[1].x; pt[1][1] = _pts[1].y; pt[1][2] = _pts[1].z; pt[2][0] = _pts[2].x; pt[2][1] = _pts[2].y; pt[2][2] = _pts[2].z; */ int res = triBoxOverlap(&_box.center.x, &_box.extent.x, _pts); if (res == 1) return true; return false; }
bool AxisAlignedBox3::CollisionTriangle(sglTriangle * triangle) { mmVector3 center = Center(); mmVector3 diagonal = Diagonal(); //const float eps = 1.00f; float boxcenter[3] = {center.x, center.y, center.z}; float boxhalfsize[3] = {diagonal.x / 2.0f, diagonal.y / 2.0f, diagonal.z / 2.0f}; float triverts[3][3] = { {triangle->point1.x, triangle->point1.y, triangle->point1.z}, {triangle->point2.x, triangle->point2.y, triangle->point2.z}, {triangle->point3.x, triangle->point3.y, triangle->point3.z}}; return triBoxOverlap(boxcenter, boxhalfsize, triverts); }
bool trigCubeIntersect(int tidx, const Mesh & m , GridIdx & cube, real_t * mn, real_t side_len) { float boxcenter[3]={mn[0]+(0.5+cube[0])*side_len, mn[1]+(0.5+cube[1])*side_len, mn[2]+(0.5+cube[2])*side_len}; float boxhalfsize[3]={side_len/2,side_len/2,side_len/2}; float triverts[3][3]; for(int ii=0;ii<3;ii++){ for(int jj=0;jj<3;jj++){ triverts[ii][jj]=m.v[m.t[tidx][ii]][jj]; } } return triBoxOverlap(boxcenter,boxhalfsize, triverts); }
EXPORT(sqInt) primitiveTriBoxIntersects(void) { float* maxCorner; float* v0; float* v2; float* v1; float* minCorner; sqInt result; if (!((interpreterProxy->methodArgumentCount()) == 5)) { return interpreterProxy->primitiveFail(); } v2 = stackVector3(0); v1 = stackVector3(1); v0 = stackVector3(2); maxCorner = stackVector3(3); minCorner = stackVector3(4); result = triBoxOverlap(minCorner, maxCorner, v0, v1, v2); if (result < 0) { return interpreterProxy->primitiveFail(); } interpreterProxy->pop(6); interpreterProxy->pushBool(result); }
/** * gts_bbox_overlaps_segment: * @bb: a #GtsBBox. * @s: a #GtsSegment. * * This functions uses gts_bbox_overlaps_triangle() with a degenerate * triangle. * * Returns: %TRUE if @bb overlaps with @s, %FALSE otherwise. */ gboolean gts_bbox_overlaps_segment (GtsBBox * bb, GtsSegment * s) { double bc[3], bh[3], tv[3][3]; GtsPoint * p1, * p2, * p3; g_return_val_if_fail (bb != NULL, FALSE); g_return_val_if_fail (s != NULL, FALSE); bc[0] = (bb->x2 + bb->x1)/2.; bh[0] = (bb->x2 - bb->x1)/2.; bc[1] = (bb->y2 + bb->y1)/2.; bh[1] = (bb->y2 - bb->y1)/2.; bc[2] = (bb->z2 + bb->z1)/2.; bh[2] = (bb->z2 - bb->z1)/2.; p1 = GTS_POINT (s->v1); p2 = GTS_POINT (s->v2); p3 = p1; tv[0][0] = p1->x; tv[0][1] = p1->y; tv[0][2] = p1->z; tv[1][0] = p2->x; tv[1][1] = p2->y; tv[1][2] = p2->z; tv[2][0] = p3->x; tv[2][1] = p3->y; tv[2][2] = p3->z; return triBoxOverlap (bc, bh, tv); }
/** * gts_bbox_overlaps_triangle: * @bb: a #GtsBBox. * @t: a #GtsTriangle. * * This is a wrapper around the fast overlap test of Tomas * Akenine-Moller (http://www.cs.lth.se/home/Tomas_Akenine_Moller/). * * Returns: %TRUE if @bb overlaps with @t, %FALSE otherwise. */ gboolean gts_bbox_overlaps_triangle (GtsBBox * bb, GtsTriangle * t) { double bc[3], bh[3], tv[3][3]; GtsPoint * p1, * p2, * p3; g_return_val_if_fail (bb != NULL, FALSE); g_return_val_if_fail (t != NULL, FALSE); bc[0] = (bb->x2 + bb->x1)/2.; bh[0] = (bb->x2 - bb->x1)/2.; bc[1] = (bb->y2 + bb->y1)/2.; bh[1] = (bb->y2 - bb->y1)/2.; bc[2] = (bb->z2 + bb->z1)/2.; bh[2] = (bb->z2 - bb->z1)/2.; p1 = GTS_POINT (GTS_SEGMENT (t->e1)->v1); p2 = GTS_POINT (GTS_SEGMENT (t->e1)->v2); p3 = GTS_POINT (gts_triangle_vertex (t)); tv[0][0] = p1->x; tv[0][1] = p1->y; tv[0][2] = p1->z; tv[1][0] = p2->x; tv[1][1] = p2->y; tv[1][2] = p2->z; tv[2][0] = p3->x; tv[2][1] = p3->y; tv[2][2] = p3->z; return triBoxOverlap (bc, bh, tv); }
void AtlasOldMesher::writeCollision(Stream *s) { // First, do the binning. This is a bit gross but, hey, what can you do... const U32 gridSize = BIT(gAtlasColTreeDepth-1); const U32 gridCount = gridSize * gridSize; Vector<U16> bins[gridCount]; // Track the min/max for the bins. S16 binsMax[gridCount]; S16 binsMin[gridCount]; // Clear bins. for(S32 i=0; i<gridCount; i++) { binsMax[i] = S16_MIN; binsMin[i] = S16_MAX; } // Get the size of bins (we step in x/y, not in Z). Point3F binSize( mBounds.len_x() / F32(gridSize), mBounds.len_y() / F32(gridSize), mBounds.len_z()); for(S32 i=0; i<gridSize; i++) { for(S32 j=0; j<gridSize; j++) { // Figure the bounds for this bin... Box3F binBox; binBox.minExtents.x = binSize.x * i; binBox.minExtents.y = binSize.y * j; binBox.minExtents.z = mBounds.minExtents.z - 1.f; binBox.maxExtents.x = binSize.x * (i+1); binBox.maxExtents.y = binSize.y * (j+1); binBox.maxExtents.z = mBounds.maxExtents.z + 1.f; Vector<U16> &binList = bins[i * gridSize + j]; S16 &binMin = binsMin[i * gridSize + j]; S16 &binMax = binsMax[i * gridSize + j]; // Now, consider all the triangles in the mesh. Note: we assume a trilist. for(S32 v=0; v<mIndices.size(); v+=3) { // Get the verts. const Vert &a = mVerts[mIndices[v+0]]; const Vert &b = mVerts[mIndices[v+1]]; const Vert &c = mVerts[mIndices[v+2]]; // If it's a special, skip it, we don't want to collide with skirts. if(a.special || b.special || c.special) continue; // I can't stand skirts! // Reject anything degenerate... if(mIndices[v+0] == mIndices[v+1]) continue; if(mIndices[v+1] == mIndices[v+2]) continue; if(mIndices[v+2] == mIndices[v+0]) continue; // Otherwise, we're good, so consider it for the current bin. const Point3F aPos = getVertPos(a); const Point3F bPos = getVertPos(b); const Point3F cPos = getVertPos(c); if(triBoxOverlap(binBox, aPos, bPos, cPos)) { // Got a hit, add it to the list! binList.push_back(v); // Update the min/max info. This will be TOO BIG if we have a // very large triangle! An optimal implementation will do a clip, // then update the bin. This is probably ok for the moment. S16 hA = mHeight->sample(a.pos); S16 hB = mHeight->sample(b.pos); S16 hC = mHeight->sample(c.pos); if(hA > binMax) binMax = hA; if(hB > binMax) binMax = hB; if(hC > binMax) binMax = hC; if(hA < binMin) binMin = hA; if(hB < binMin) binMin = hB; if(hC < binMin) binMin = hC; } } // Limit the triangle count to 16bits. While primary meshes support more // than that, collision meshes don't. If we don't catch that here, we'll // see raycasting issues later in Atlas. AssertISV( binList.size() <= 65536, "AtlasOldMesher::writeCollision - too many triangles! (>65536) Try again with a deeper tree" ); // Ok, we're all set for this bin... AssertFatal(binMin <= binMax, "AtlasOldMesher::writeCollision - empty bin, crap!"); } } // Next, generate the quadtree. FrameAllocatorMarker qtPool; const U32 nodeCount = QuadTreeTracer::getNodeCount(gAtlasColTreeDepth); S16 *qtMin = (S16*)qtPool.alloc(sizeof(S16) * nodeCount); S16 *qtMax = (S16*)qtPool.alloc(sizeof(S16) * nodeCount); // We have to recursively generate this from the bins on up. First we copy // the bins from earlier, then we do our recursomatic thingummy. (It's // actually not recursive.) for(S32 i=0; i<gridSize; i++) { for(S32 j=0; j<gridSize; j++) { const U32 qtIdx = QuadTreeTracer::getNodeIndex(gAtlasColTreeDepth-1, Point2I(i,j)); qtMin[qtIdx] = binsMin[i * gridSize + j]; qtMax[qtIdx] = binsMax[i * gridSize + j]; AssertFatal(qtMin[qtIdx] <= qtMax[qtIdx], "AtlasOldMesher::writeCollision - bad child quadtree node min/max! (negative a)"); } } // Alright, now we go up the bins, generating from the four children of each, // till we hit the root. // For each empty level from bottom to top... for(S32 depth = gAtlasColTreeDepth - 2; depth >= 0; depth--) { // For each square... for(S32 i=0; i<BIT(depth); i++) for(S32 j=0; j<BIT(depth); j++) { const U32 curIdx = QuadTreeTracer::getNodeIndex(depth, Point2I(i,j)); // For each of this square's 4 children... for(S32 subI=0; subI<2; subI++) for(S32 subJ=0; subJ<2; subJ++) { const U32 subIdx = QuadTreeTracer::getNodeIndex(depth+1, Point2I(i*2+subI,j*2+subJ)); // As is the child. AssertFatal(qtMin[subIdx] <= qtMax[subIdx], "AtlasOldMesher::writeCollision - bad child quadtree node min/max! (a)"); // Update the min and max of the parent. if(qtMin[subIdx] < qtMin[curIdx]) qtMin[curIdx] = qtMin[subIdx]; if(qtMax[subIdx] > qtMax[curIdx]) qtMax[curIdx] = qtMax[subIdx]; // Make sure we actually contain the child. AssertFatal(qtMin[subIdx] >= qtMin[curIdx], "AtlasOldMesher::writeCollision - bad quadtree child min during coltree generation!"); AssertFatal(qtMax[subIdx] <= qtMax[curIdx], "AtlasOldMesher::writeCollision - bad quadtree child max during coltree generation!"); // And that the parent is still valid. AssertFatal(qtMin[curIdx] <= qtMax[curIdx], "AtlasOldMesher::writeCollision - bad parent quadtree node min/max!"); // As is the child. AssertFatal(qtMin[subIdx] <= qtMax[subIdx], "AtlasOldMesher::writeCollision - bad child quadtree node min/max! (b)"); } } } // Wasn't that fun? Now we have a ready-to-go quadtree. // Now write the quadtree, in proper order for(S32 i=0; i<nodeCount; i++) { AssertFatal(qtMin[i] <= qtMax[i], "AtlasOldMesher::writeCollision - invalid quadtree min/max."); s->write(qtMin[i]); s->write(qtMax[i]); } s->write(U32(0xb33fd34d)); // We have to generate... // ... the list of triangle offsets for each bin. (Done above!) // ... the triangle buffer which stores the offsets for each bin. ChunkTriangleBufferGenerator ctbg(gridSize); for(S32 i=0; i<gridSize; i++) for(S32 j=0; j<gridSize; j++) ctbg.insertBinList(Point2I(i,j), bins[i * gridSize + j]); // Finally, write the data out. ctbg.write(s); }
void UniformGrid::calculateGrid(unsigned int p_numTriangles, std::vector<RTMesh>* p_mesh, std::vector<RTMaterial>* p_material, std::vector<RTLight>* p_light, Vector3 p_numVoxels) { std::vector<RTTriangle*>* aux_grid = new std::vector<RTTriangle*>[(int)(p_numVoxels.x * p_numVoxels.y * p_numVoxels.z)]; unsigned int size = 0; for(unsigned int i=0; i<p_mesh->size(); i++){ std::vector<RTTriangle>* trianglesArray = p_mesh->at(i).getTriangles(); for(unsigned int j=0; j<trianglesArray->size(); j++){ RTTriangle* currentTriangle = &(trianglesArray->at(j)); Vector3 voxelIndex_vertex1 = getVertexGridIndex(currentTriangle->v1); Vector3 voxelIndex_vertex2 = getVertexGridIndex(currentTriangle->v2); Vector3 voxelIndex_vertex3 = getVertexGridIndex(currentTriangle->v3); aux_grid[getVoxelAt(voxelIndex_vertex1)].push_back(currentTriangle); size++; if((voxelIndex_vertex2 == voxelIndex_vertex1) == false){ aux_grid[getVoxelAt(voxelIndex_vertex2)].push_back(currentTriangle); size++; } if((voxelIndex_vertex3 == voxelIndex_vertex2) == false && (voxelIndex_vertex3 == voxelIndex_vertex1) == false){ aux_grid[getVoxelAt(voxelIndex_vertex3)].push_back(currentTriangle); size++; } //Test triangle / box intersections for(float x=0; x<m_numVoxels.x; x++){ for(float y=0; y<m_numVoxels.y; y++){ for(float z=0; z<m_numVoxels.z; z++){ Vector3 bbMin = m_min + Vector3(x * m_voxelSize.x, y * m_voxelSize.y, z * m_voxelSize.z); Vector3 bbMax = bbMin + m_voxelSize; float bbCenter [] = {bbMin.x + ((bbMax.x - bbMin.x) / 2.0f), (bbMin.y + (bbMax.y - bbMin.y) / 2.0f), (bbMin.z + (bbMax.z - bbMin.z) / 2.0f)}; float bbHalfSize [] = {((m_voxelSize).x / 2.0f), ((m_voxelSize).y / 2.0f), ((m_voxelSize).z / 2.0f)}; float triangle [][3] = {{currentTriangle->v1.x, currentTriangle->v1.y, currentTriangle->v1.z}, {currentTriangle->v2.x, currentTriangle->v2.y, currentTriangle->v2.z}, {currentTriangle->v3.x, currentTriangle->v3.y, currentTriangle->v3.z}}; bool hit = triBoxOverlap(bbCenter, bbHalfSize, triangle); //std::cout << triBoxOverlap(bbCenter, bbHalfSize, triangle) << "\n"; Vector3 voxel = Vector3(x,y,z); if(hit == true && (voxel == voxelIndex_vertex1) == false && (voxel == voxelIndex_vertex2) == false && (voxel == voxelIndex_vertex3) == false){ aux_grid[getVoxelAt(voxel)].push_back(currentTriangle); size++; } } } } } } // GLint max_tex_size = 0; glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_tex_size); int texture2DnumLines; m_gridArraySize = (int)(p_numVoxels.x * p_numVoxels.y * p_numVoxels.z) * 4; texture2DnumLines = (int)((m_gridArraySize/4)/max_tex_size) + (int)(m_gridArraySize%max_tex_size != 0); m_gridArray = new GLfloat[texture2DnumLines*max_tex_size*4]; for(int i = 0; i < texture2DnumLines*max_tex_size*4; ++i) m_gridArray[i] = -1.0f; //memset(m_gridArray, -1.0f, sizeof(GLfloat) * m_gridArraySize);//Do not work for floats different then 0 size += p_numVoxels.x * p_numVoxels.y * p_numVoxels.z; m_triangleListArraySize = size; texture2DnumLines = (int)((m_triangleListArraySize)/max_tex_size) + (int)(m_triangleListArraySize%max_tex_size != 0); m_triangleListArray = new GLfloat[texture2DnumLines*max_tex_size]; for(int i = 0; i < texture2DnumLines*max_tex_size; ++i) m_triangleListArray[i] = -1.0f; m_triangleVertexArraySize = p_numTriangles * 3 * 3; texture2DnumLines = (int)((m_triangleVertexArraySize/3)/max_tex_size) + (int)(m_triangleVertexArraySize%max_tex_size != 0); m_triangleVertexArray = new GLfloat[texture2DnumLines*max_tex_size*3]; for(int i = 0; i < texture2DnumLines*max_tex_size*3; ++i) m_triangleVertexArray[i] = 1.0f; m_triangleNormalsArraySize = p_numTriangles * 3 * 3; texture2DnumLines = (int)((m_triangleNormalsArraySize/3)/max_tex_size) + (int)(m_triangleNormalsArraySize%max_tex_size != 0); m_triangleNormalsArray = new GLfloat[texture2DnumLines*max_tex_size*3]; memset(m_triangleNormalsArray, 0, sizeof(GLfloat) * texture2DnumLines*max_tex_size*3); m_triangleMaterialArraySize = p_numTriangles * 3 * 4; texture2DnumLines = (int)((m_triangleMaterialArraySize/4)/max_tex_size) + (int)(m_triangleMaterialArraySize%max_tex_size != 0); m_triangleMaterialArray = new GLfloat[texture2DnumLines*max_tex_size*4]; memset(m_triangleMaterialArray, 0, sizeof(GLfloat) * texture2DnumLines*max_tex_size*4); m_lightsArraySize = p_light->size()*sizeof(struct lightStruct)/(sizeof(GLfloat)); m_lightsArray = new GLfloat[m_lightsArraySize]; for( unsigned int i = 0; i < p_light->size(); ++i) memcpy(&m_lightsArray[i*sizeof(struct lightStruct)/sizeof(GLfloat)], p_light->at(i).getLightStruct(), sizeof(struct lightStruct)); unsigned int gridCount = 0; unsigned int gridCountPlusOne = 0; int cont = 0; int gridIndexCont = 0; for(int x=0; x<p_numVoxels.x; x++){ for(int y=0; y<p_numVoxels.y; y++){ for(int z=0; z<p_numVoxels.z; z++){ unsigned int prevGridCountPlusOne = gridCountPlusOne; for(int j=0; j<aux_grid[cont].size(); j++){ unsigned int triangleIndex = aux_grid[cont].at(j)->getGlobalIndex(); m_triangleListArray[gridCountPlusOne+j] = triangleIndex; m_triangleVertexArray[triangleIndex*3*3] = aux_grid[cont].at(j)->v1.x; m_triangleVertexArray[triangleIndex*3*3+1] = aux_grid[cont].at(j)->v1.y; m_triangleVertexArray[triangleIndex*3*3+2] = aux_grid[cont].at(j)->v1.z; m_triangleVertexArray[triangleIndex*3*3+3] = aux_grid[cont].at(j)->v2.x; m_triangleVertexArray[triangleIndex*3*3+3+1] = aux_grid[cont].at(j)->v2.y; m_triangleVertexArray[triangleIndex*3*3+3+2] = aux_grid[cont].at(j)->v2.z; m_triangleVertexArray[triangleIndex*3*3+3+3] = aux_grid[cont].at(j)->v3.x; m_triangleVertexArray[triangleIndex*3*3+3+3+1] = aux_grid[cont].at(j)->v3.y; m_triangleVertexArray[triangleIndex*3*3+3+3+2] = aux_grid[cont].at(j)->v3.z; m_triangleNormalsArray[triangleIndex*3*3] = aux_grid[cont].at(j)->n1.x; m_triangleNormalsArray[triangleIndex*3*3+1] = aux_grid[cont].at(j)->n1.y; m_triangleNormalsArray[triangleIndex*3*3+2] = aux_grid[cont].at(j)->n1.z; m_triangleNormalsArray[triangleIndex*3*3+3] = aux_grid[cont].at(j)->n2.x; m_triangleNormalsArray[triangleIndex*3*3+3+1] = aux_grid[cont].at(j)->n2.y; m_triangleNormalsArray[triangleIndex*3*3+3+2] = aux_grid[cont].at(j)->n2.z; m_triangleNormalsArray[triangleIndex*3*3+3+3] = aux_grid[cont].at(j)->n3.x; m_triangleNormalsArray[triangleIndex*3*3+3+3+1] = aux_grid[cont].at(j)->n3.y; m_triangleNormalsArray[triangleIndex*3*3+3+3+2] = aux_grid[cont].at(j)->n3.z; m_triangleMaterialArray[triangleIndex*3*4] = p_material->at(aux_grid[cont].at(j)->getMaterialIndex()).opacity; m_triangleMaterialArray[triangleIndex*3*4+1] = p_material->at(aux_grid[cont].at(j)->getMaterialIndex()).reflective; m_triangleMaterialArray[triangleIndex*3*4+2] = p_material->at(aux_grid[cont].at(j)->getMaterialIndex()).refractive; m_triangleMaterialArray[triangleIndex*3*4+3] = 1.0; m_triangleMaterialArray[triangleIndex*3*4+4] = p_material->at(aux_grid[cont].at(j)->getMaterialIndex()).diffuse.r; m_triangleMaterialArray[triangleIndex*3*4+4+1] = p_material->at(aux_grid[cont].at(j)->getMaterialIndex()).diffuse.g; m_triangleMaterialArray[triangleIndex*3*4+4+2] = p_material->at(aux_grid[cont].at(j)->getMaterialIndex()).diffuse.b; m_triangleMaterialArray[triangleIndex*3*4+4+3] = 1.0; m_triangleMaterialArray[triangleIndex*3*4+4+4] = p_material->at(aux_grid[cont].at(j)->getMaterialIndex()).specular.r; m_triangleMaterialArray[triangleIndex*3*4+4+4+1] = p_material->at(aux_grid[cont].at(j)->getMaterialIndex()).specular.g; m_triangleMaterialArray[triangleIndex*3*4+4+4+2] = p_material->at(aux_grid[cont].at(j)->getMaterialIndex()).specular.b; m_triangleMaterialArray[triangleIndex*3*4+4+4+3] = p_material->at(aux_grid[cont].at(j)->getMaterialIndex()).specularExp; } m_gridArray[gridIndexCont++] = x; m_gridArray[gridIndexCont++] = y; m_gridArray[gridIndexCont++] = z; m_gridArray[gridIndexCont++] = aux_grid[cont].size() != 0 ? (float)prevGridCountPlusOne : -1.0; gridCountPlusOne += aux_grid[cont].size()+1; gridCount += aux_grid[cont].size(); cont++; } } } delete [] aux_grid; }
void Resizer::computeFacePassthroughingCell(int _faceIndex,float _tempVertex[3][3],int _indexMin[3],int _indexMax[3],float _cellHalfLength[3]) { int num = 0; //记录该face穿过的cell的个数 float cellCenter[3]; //记录当前cell的中心点 //仔细考虑八种情况 if(_indexMax[0] == _indexMin[0]) { if(_indexMax[1] == _indexMin[1]) { if(_indexMax[2] == _indexMin[2]) //如果X,Y,Z方向都相同(肯定是相交的) { facePassthroughCell[_faceIndex][num] = computeCellIndex(_indexMin[0],_indexMin[1],_indexMin[2]); // printf("X,Y,Z方向都相同:%d--%d\n",num,computeCellIndex(_indexMin[0],_indexMin[1],_indexMin[2])); num++; facePassthroughCellNum[_faceIndex] = num; // Sleep(500); } else //如果X,Y方向相同,Z方向不同(需要判断是否相交) { cellCenter[0] = minBoundingBox[0]+_indexMin[0]*edgeLength[0]+_cellHalfLength[0]; cellCenter[1] = minBoundingBox[1]+_indexMin[1]*edgeLength[1]+_cellHalfLength[1]; for(int j=_indexMin[2];j<=_indexMax[2];j++) //Z轴 { cellCenter[2] = minBoundingBox[2]+j*edgeLength[2]+_cellHalfLength[2]; if(triBoxOverlap(cellCenter,_cellHalfLength,_tempVertex) == 1) //如果face和cell相交 { facePassthroughCell[_faceIndex][num] = computeCellIndex(_indexMin[0],_indexMin[1],j); // printf("X,Y方向相同,Z方向不同:%d--%d\n",num,computeCellIndex(_indexMin[0],_indexMin[1],j)); num++; // Sleep(500); } /*else { printf("X,Y方向相同,Z方向不同:face和cell不相交.\n"); Sleep(500); }*/ } facePassthroughCellNum[_faceIndex] = num; } } else //Y方向不相同 { if(_indexMin[2] == _indexMax[2]) //X,Z方向相同,Y方向不同 { cellCenter[0] = minBoundingBox[0]+_indexMin[0]*edgeLength[0]+_cellHalfLength[0]; cellCenter[2] = minBoundingBox[2]+_indexMin[2]*edgeLength[2]+_cellHalfLength[2]; for(int j=_indexMin[1];j<=_indexMax[1];j++) //Y轴 { cellCenter[1] = minBoundingBox[1]+j*edgeLength[1]+_cellHalfLength[1]; if(triBoxOverlap(cellCenter,_cellHalfLength,_tempVertex) == 1) //如果face和cell相交 { facePassthroughCell[_faceIndex][num] = computeCellIndex(_indexMin[0],j,_indexMin[2]); // printf("X,Z方向相同,Y方向不同:%d--%d\n",num,computeCellIndex(_indexMin[0],j,_indexMin[2])); num++; // Sleep(500); } /*else { printf("X,Z方向相同,Y方向不同:face和cell不相交.\n"); Sleep(500); }*/ facePassthroughCellNum[_faceIndex] = num; } } else //X方向相同,Y,Z方向不同 { cellCenter[0] = minBoundingBox[0]+_indexMin[0]*edgeLength[0]+_cellHalfLength[0]; for(int j=_indexMin[1];j<=_indexMax[1];j++) //Y方向 { for(int k=_indexMin[2];k<=_indexMax[2];k++) //Z方向 { cellCenter[1] = minBoundingBox[1]+j*edgeLength[1]+_cellHalfLength[1]; cellCenter[2] = minBoundingBox[2]+k*edgeLength[2]+_cellHalfLength[2]; if(triBoxOverlap(cellCenter,_cellHalfLength,_tempVertex) == 1) //如果face和cell相交 { facePassthroughCell[_faceIndex][num] = computeCellIndex(_indexMin[0],j,k); // printf("X方向相同,Y,Z方向不同:%d--%d\n",num,computeCellIndex(_indexMin[0],j,k)); num++; // Sleep(500); } /*else { printf("X方向相同,Y,Z方向不同:face和cell不相交.\n"); Sleep(500); }*/ facePassthroughCellNum[_faceIndex] = num; } } } } } else //X方向不同 { if(_indexMin[1] == _indexMax[1]) //Y方向相同 { if(_indexMin[2] == _indexMax[2]) //Y,Z方向相同,X方向不同 { cellCenter[1] = minBoundingBox[1]+_indexMin[1]*edgeLength[1]+_cellHalfLength[1]; cellCenter[2] = minBoundingBox[2]+_indexMin[2]*edgeLength[2]+_cellHalfLength[2]; for(int j=_indexMin[0];j<=_indexMax[0];j++) //X方向 { cellCenter[0] = minBoundingBox[0]+j*edgeLength[0]+_cellHalfLength[0]; if(triBoxOverlap(cellCenter,_cellHalfLength,_tempVertex) == 1) //如果face和cell相交 { facePassthroughCell[_faceIndex][num] = computeCellIndex(j,_indexMin[1],_indexMin[2]); // printf("Y,Z方向相同,X方向不同:%d--%d\n",num,computeCellIndex(j,_indexMin[1],_indexMin[2])); num++; // Sleep(500); } /*else { printf("Y,Z方向相同,X方向不同:face和cell不相交.\n"); Sleep(500); }*/ } facePassthroughCellNum[_faceIndex] = num; } else //Y方向相同,X,Z方向不同 { cellCenter[1] = minBoundingBox[1]+_indexMin[1]*edgeLength[1]+_cellHalfLength[1]; for(int j=_indexMin[0];j<=_indexMax[0];j++) //X方向 { for(int k=_indexMin[2];k<=_indexMax[2];k++) //Z方向 { cellCenter[0] = minBoundingBox[0]+j*edgeLength[0]+_cellHalfLength[0]; cellCenter[2] = minBoundingBox[2]+k*edgeLength[2]+_cellHalfLength[2]; if(triBoxOverlap(cellCenter,_cellHalfLength,_tempVertex) == 1) //如果face和cell相交 { facePassthroughCell[_faceIndex][num] = computeCellIndex(j,_indexMin[1],k); // printf("Y方向相同,X,Z方向不同:%d--%d\n",num,computeCellIndex(j,_indexMin[1],k)); num++; // Sleep(500); } /*else { printf("Y方向相同,X,Z方向不同:face和cell不相交.\n"); Sleep(500); }*/ facePassthroughCellNum[_faceIndex] = num; } } } } else //Y方向不同 { if(_indexMin[2] == _indexMax[2]) //Z方向相同,X,Y方向不同 { cellCenter[2] = minBoundingBox[2]+_indexMin[2]*edgeLength[2]+_cellHalfLength[2]; for(int j=_indexMin[0];j<=_indexMax[0];j++) //X方向 { for(int k=_indexMin[1];k<=_indexMax[1];k++) //Y方向 { cellCenter[0] = minBoundingBox[0]+j*edgeLength[0]+_cellHalfLength[0]; cellCenter[1] = minBoundingBox[1]+k*edgeLength[1]+_cellHalfLength[1]; if(triBoxOverlap(cellCenter,_cellHalfLength,_tempVertex) == 1) //如果face和cell相交 { facePassthroughCell[_faceIndex][num] = computeCellIndex(j,k,_indexMin[2]); // printf("Z方向相同,X,Y方向不同:%d--%d\n",num,computeCellIndex(j,k,_indexMin[2])); num++; // Sleep(500); } /*else { printf("Z方向相同,X,Y方向不同:face和cell不相交.\n"); Sleep(500); }*/ facePassthroughCellNum[_faceIndex] = num; } } } else //X,Y,Z方向都不同 { for(int j=_indexMin[0];j<=_indexMax[0];j++) //X轴 { for(int k=_indexMin[1];k<=_indexMax[1];k++) //Y轴 { for(int p=_indexMin[2];p<=_indexMax[2];p++) //Z轴 { cellCenter[0] = minBoundingBox[0]+j*edgeLength[0]+_cellHalfLength[0]; cellCenter[1] = minBoundingBox[1]+k*edgeLength[1]+_cellHalfLength[1]; cellCenter[2] = minBoundingBox[2]+p*edgeLength[2]+_cellHalfLength[2]; if(triBoxOverlap(cellCenter,_cellHalfLength,_tempVertex) == 1) //如果face和cell相交 { facePassthroughCell[_faceIndex][num] = computeCellIndex(j,k,p); /* printf("X,Y,Z方向不同:%d--%d\n",num,computeCellIndex(j,k,p)); printf("(%f,%f,%f),(%f,%f,%f),(%f,%f,%f)\n",_tempVertex[0][0],_tempVertex[0][1],_tempVertex[0][2], _tempVertex[1][0],_tempVertex[1][1],_tempVertex[1][2], _tempVertex[2][0],_tempVertex[2][1],_tempVertex[2][2]);*/ num++; // Sleep(1500); } /*else { printf("X,Y,Z方向不同:face和cell不相交.\n"); printf("(%f,%f,%f),(%f,%f,%f),(%f,%f,%f)\n",_tempVertex[0][0],_tempVertex[0][1],_tempVertex[0][2], _tempVertex[1][0],_tempVertex[1][1],_tempVertex[1][2], _tempVertex[2][0],_tempVertex[2][1],_tempVertex[2][2]); Sleep(1500); }*/ facePassthroughCellNum[_faceIndex] = num; } } } } } } }
/*! Builds the uniform grid for ray tracing acceleration */ void SLUniformGrid::build(SLVec3f minV, SLVec3f maxV) { _minV = minV; _maxV = maxV; deleteAll(); // Calculate uniform grid // Calc. voxel resolution, extent and allocate voxel array SLVec3f size = _maxV - _minV; // Woo's method SLfloat voxDensity = 20.0f; SLuint numT = _m->numI / 3; // NO. of triangles SLfloat nr = (SLfloat)pow(voxDensity*numT,1.0f/3.0f); SLfloat maxS = SL_max(size.x, size.y, size.z); _voxResX = max(1, (SLint)(nr*size.x/maxS)); _voxResY = max(1, (SLint)(nr*size.y/maxS)); _voxResZ = max(1, (SLint)(nr*size.z/maxS)); _voxResXY= _voxResX * _voxResY; _voxCnt = _voxResZ * _voxResXY; _voxExtX = size.x / _voxResX; _voxExtY = size.y / _voxResY; _voxExtZ = size.z / _voxResZ; // Allocate array of pointer to SLV32ushort _vox = new SLV32ushort*[_voxCnt]; for (SLuint i=0; i<_voxCnt; ++i) _vox[i] = 0; SLint x, y, z; SLuint i, curVoxel = 0; SLfloat boxHalfExt[3] = {_voxExtX*0.5f, _voxExtY*0.5f, _voxExtZ*0.5f}; SLfloat curVoxelCenter[3]; SLfloat vert[3][3]; SLuint voxCntNotEmpty = 0; // Loop through all triangles and assign them to the voxels for(SLuint t = 0; t < numT; ++t) { // Copy triangle vertices into SLfloat array[3][3] SLuint i = t * 3; if (_m->I16) { vert[0][0] = _m->finalP()[_m->I16[i ]].x; vert[0][1] = _m->finalP()[_m->I16[i ]].y; vert[0][2] = _m->finalP()[_m->I16[i ]].z; vert[1][0] = _m->finalP()[_m->I16[i+1]].x; vert[1][1] = _m->finalP()[_m->I16[i+1]].y; vert[1][2] = _m->finalP()[_m->I16[i+1]].z; vert[2][0] = _m->finalP()[_m->I16[i+2]].x; vert[2][1] = _m->finalP()[_m->I16[i+2]].y; vert[2][2] = _m->finalP()[_m->I16[i+2]].z; } else { vert[0][0] = _m->finalP()[_m->I32[i ]].x; vert[0][1] = _m->finalP()[_m->I32[i ]].y; vert[0][2] = _m->finalP()[_m->I32[i ]].z; vert[1][0] = _m->finalP()[_m->I32[i+1]].x; vert[1][1] = _m->finalP()[_m->I32[i+1]].y; vert[1][2] = _m->finalP()[_m->I32[i+1]].z; vert[2][0] = _m->finalP()[_m->I32[i+2]].x; vert[2][1] = _m->finalP()[_m->I32[i+2]].y; vert[2][2] = _m->finalP()[_m->I32[i+2]].z; } // Min. and max. point of triangle SLVec3f minT = SLVec3f(SL_min(vert[0][0], vert[1][0], vert[2][0]), SL_min(vert[0][1], vert[1][1], vert[2][1]), SL_min(vert[0][2], vert[1][2], vert[2][2])); SLVec3f maxT = SLVec3f(SL_max(vert[0][0], vert[1][0], vert[2][0]), SL_max(vert[0][1], vert[1][1], vert[2][1]), SL_max(vert[0][2], vert[1][2], vert[2][2])); // min voxel index of triangle SLint minx = (SLint)((minT.x-_minV.x) / _voxExtX); SLint miny = (SLint)((minT.y-_minV.y) / _voxExtY); SLint minz = (SLint)((minT.z-_minV.z) / _voxExtZ); // max voxel index of triangle SLint maxx = (SLint)((maxT.x-_minV.x) / _voxExtX); SLint maxy = (SLint)((maxT.y-_minV.y) / _voxExtY); SLint maxz = (SLint)((maxT.z-_minV.z) / _voxExtZ); if (maxx >= _voxResX) maxx=_voxResX-1; if (maxy >= _voxResY) maxy=_voxResY-1; if (maxz >= _voxResZ) maxz=_voxResZ-1; // Loop through voxels curVoxelCenter[2] = _minV.z + minz*_voxExtZ + boxHalfExt[2]; for (z=minz; z<=maxz; ++z, curVoxelCenter[2] += _voxExtZ) { curVoxelCenter[1] = _minV.y + miny*_voxExtY + boxHalfExt[1]; for (y=miny; y<=maxy; ++y, curVoxelCenter[1] += _voxExtY) { curVoxelCenter[0] = _minV.x + minx*_voxExtX + boxHalfExt[0]; for (x=minx; x<=maxx; ++x, curVoxelCenter[0] += _voxExtX) { curVoxel = x + y*_voxResX + z*_voxResXY; //triangle-AABB overlap test by Thomas Möller if (triBoxOverlap(curVoxelCenter, boxHalfExt, vert)) //trianlgesAABB-AABB overlap test is faster but not as precise //if (triBoxBoxOverlap(curVoxelCenter, boxHalfExt, vert)) { { if (_vox[curVoxel] == 0) { voxCntNotEmpty++; _vox[curVoxel] = new SLV32ushort; } _vox[curVoxel]->push_back(t); if (_vox[curVoxel]->size() > _voxMaxTria) _voxMaxTria = _vox[curVoxel]->size(); } } } } } } _voxCntEmpty = _voxCnt - voxCntNotEmpty; // Reduce dynamic arrays to real size for (i=0; i<_voxCnt; ++i) { if (_vox[i]) _vox[i]->reserve(_vox[i]->size()); } /* // dump for debugging SL_LOG("\nMesh name: %s\n", _m->name().c_str()); SL_LOG("Number of voxels: %d\n", _voxCnt); SL_LOG("Empty voxels: %4.0f%%\n", (SLfloat)(_voxCnt-voxCntNotEmpty)/(SLfloat)_voxCnt * 100.0f); SL_LOG("Avg. tria. per voxel: %4.1f\n", (SLfloat)_m->numF/(SLfloat)voxCntNotEmpty); // dump voxels curVoxel = 0; curVoxelCenter[2] = _minV.z + boxHalfExt[2]; for (z=0; z<_voxResZ; ++z, curVoxelCenter[2] += _voxExtZ) { curVoxelCenter[1] = _minV.y + boxHalfExt[1]; for (y=0; y<_voxResY; ++y, curVoxelCenter[1] += _voxExtY) { curVoxelCenter[0] = _minV.x + boxHalfExt[0]; for (x=0; x<_voxResX; ++x, curVoxelCenter[0] += _voxExtX) { SL_LOG("\t%0d(%3.1f,%3.1f,%3.1f):%0d " ,curVoxel, curVoxelCenter[0], curVoxelCenter[1], curVoxelCenter[2], _vox[curVoxel].size()); curVoxel++; } SL_LOG("\n"); } SL_LOG("\n"); } */ }
void Octree::Build(Face** tria, unsigned int length) { if(length == 0) return; // Front half Back half (viewed from front) // ----------------- ----------------- // | | | | | | // | 2 | 6 | | 3 | 7 | // | | | | | | // ----------------- ----------------- // | | | | | | // | 0 | 4 | | 1 | 5 | // | | | | | | // ----------------- ----------------- // x smeruje doprava, y smeruje hore, z ODOMNA!! - bacha opengl ma Z inak // tabulka offsetov float Table[8][3] = { {-1.0, -1.0, -1.0}, {-1.0, -1.0, +1.0}, {-1.0, +1.0, -1.0}, {-1.0, +1.0, +1.0}, {+1.0, -1.0, -1.0}, {+1.0, -1.0, +1.0}, {+1.0, +1.0, -1.0}, {+1.0, +1.0, +1.0} }; if((depth >= max_depth) || (length <= min_count)) { count = length; triangles = tria; isLeaf = true; } else { isLeaf = false; count = 0; int new_depth = depth + 1; float new_size = size / 2.0f; LinkedList<Face>** son_tria = new LinkedList<Face>* [8]; for(unsigned int i = 0; i < 8; i++) son_tria[i] = NULL; // preistotu // zisti kam patria trojuholniky for(unsigned int i = 0; i < length; i++) { byte code1 = GetCode(tria[i]->v[0]->P); byte code2 = GetCode(tria[i]->v[1]->P); byte code3 = GetCode(tria[i]->v[2]->P); byte code = FLAG8; if((code1 == code2) && (code1 == code3)) { code = code1; if(son_tria[code] == NULL) son_tria[code] = new LinkedList<Face>(tria[i]); else son_tria[code]->InsertToEnd(tria[i]); } else { // moc neurychli /*bool crosses [8] = {0,0,0,0,0,0,0,0}; bool crosses1 [8] = {0,0,0,0,0,0,0,0}; bool crosses2 [8] = {0,0,0,0,0,0,0,0}; bool crosses3 [8] = {0,0,0,0,0,0,0,0}; if(!(code1 & FLAG1) || !(code2 & FLAG1) || !(code3 & FLAG1)) { crosses1[0] = true; crosses1[2] = true; crosses1[4] = true; crosses1[6] = true; } if((code1 & FLAG1) || (code2 & FLAG1) || (code3 & FLAG1)) { crosses1[1] = true; crosses1[3] = true; crosses1[5] = true; crosses1[7] = true; } if(!(code1 & FLAG2) || !(code2 & FLAG2) || !(code3 & FLAG2)) { crosses2[0] = true; crosses2[4] = true; crosses2[1] = true; crosses2[5] = true; } if((code1 & FLAG2) || (code2 & FLAG2) || (code3 & FLAG2)) { crosses2[2] = true; crosses2[6] = true; crosses2[3] = true; crosses2[7] = true; } if(!(code1 & FLAG4) || !(code2 & FLAG4) || !(code3 & FLAG4)) { crosses3[0] = true; crosses3[1] = true; crosses3[2] = true; crosses3[3] = true; } if((code1 & FLAG4) || (code2 & FLAG4) || (code3 & FLAG4)) { crosses3[4] = true; crosses3[5] = true; crosses3[6] = true; crosses3[7] = true; } for(byte j = 0; j < 8; j++) { if((crosses1[j] == true) && (crosses2[j] == true) && (crosses3[j] == true) ) crosses[j] = true; }*/ for(byte j = 0; j < 8; j++) { /*if(crosses[j] == false) continue;*/ Vector4 tmpv = Vector4(origin.X + new_size*Table[j][0], origin.Y + new_size*Table[j][1], origin.Z + new_size*Table[j][2]); if(triBoxOverlap(tmpv, new_size, tria[i]->v[0]->P, tria[i]->v[1]->P, tria[i]->v[2]->P)) { code = j; if(son_tria[code] == NULL) son_tria[code] = new LinkedList<Face>(tria[i]); else son_tria[code]->InsertToEnd(tria[i]); } } } } /* // old tabulka offsetov float Table[8][3] = { {-1.0, -1.0, -1.0}, {+1.0, -1.0, -1.0}, {-1.0, +1.0, -1.0}, {+1.0, +1.0, -1.0}, {-1.0, -1.0, +1.0}, {+1.0, -1.0, +1.0}, {-1.0, +1.0, +1.0}, {+1.0, +1.0, +1.0} };*/ // vytvor octree a uloz ich tam for(int i = 0; i < 8; i++) { Vector4 tmpv = Vector4(origin.X + new_size*Table[i][0], origin.Y + new_size*Table[i][1], origin.Z + new_size*Table[i][2]); son[i] = new Octree(new_depth, new_size, tmpv, this); unsigned int velkost = (son_tria[i] == NULL ? 0 : son_tria[i]->GetSize()); Face** tmp_zoznam = NULL; if(velkost > 0) { tmp_zoznam = new Face* [velkost]; LinkedList<Face>::Cell<Face>* tmp = son_tria[i]->start; for(unsigned int j = 0; j < velkost; j++) { tmp_zoznam[j] = tmp->data; tmp = tmp->next; } } son[i]->Build(tmp_zoznam, velkost); } // zmazanie pola, kedze vytvaram vlastne delete [] tria; // zmazanie pomocnych poli kedze som urobil vlastne for(unsigned int i = 0; i < 8; i++) { delete son_tria[i]; son_tria[i] = NULL; // preistotu } delete [] son_tria; } }
void Octree_BuildRecursiveInternal( TOctreeNode * node, TTriangle * triangles, int triangleCount, int * indices, int indexCount, int maxTrianglesPerNode ) { if( indexCount < maxTrianglesPerNode ) { int sizeBytes = sizeof( int ) * indexCount; node->indexCount = indexCount; node->indices = Memory_AllocateClean( sizeBytes ); memcpy( node->indices, indices, sizeBytes ); return; } Octree_SplitNode( node ); for( int childNum = 0; childNum < 8; childNum++ ) { TOctreeNode * child = node->childs[childNum]; TVec3 middle = Vec3_Middle( child->min, child->max ); TVec3 halfSize = Vec3_Scale( Vec3_Sub( child->max, child->min ), 0.5f ); float center[3] = {middle.x, middle.y, middle.z}; float half[3] = {halfSize.x, halfSize.y, halfSize.z}; // count triangles in each leaf int leafTriangleCount = 0; for( int i = 0; i < triangleCount; i++ ) { TTriangle * triangle = triangles + i; float triverts[3][3] = { {triangle->a.x,triangle->a.y, triangle->a.z}, {triangle->b.x,triangle->b.y, triangle->b.z}, {triangle->c.x,triangle->c.y, triangle->c.z} }; if( triBoxOverlap( center, half, triverts ) || Octree_IsPointInsideNode( child, &triangle->a ) || Octree_IsPointInsideNode( child, &triangle->b ) || Octree_IsPointInsideNode( child, &triangle->c ) ) { leafTriangleCount++; } } // allocate memory for temporary leaf and fill it with data int * leafIndices = Memory_NewCount( leafTriangleCount, int ); int triangleNum = 0; for( int i = 0; i < triangleCount; i++ ) { TTriangle * triangle = triangles + i; float triverts[3][3] = { {triangle->a.x,triangle->a.y, triangle->a.z}, {triangle->b.x,triangle->b.y, triangle->b.z}, {triangle->c.x,triangle->c.y, triangle->c.z} }; if( triBoxOverlap( center, half, triverts )|| Octree_IsPointInsideNode( child, &triangle->a ) || Octree_IsPointInsideNode( child, &triangle->b ) || Octree_IsPointInsideNode( child, &triangle->c ) ) { *(leafIndices + triangleNum) = i; triangleNum++; } } // recursively process childs of this node Octree_BuildRecursiveInternal( child, triangles, triangleCount, leafIndices, triangleNum, maxTrianglesPerNode ); // leafFaces data already copied to another node, so we can free temporary array Memory_Free( leafIndices ); } }