XMVECTOR MathHelper::RandHemisphereUnitVec3(XMVECTOR n) { XMVECTOR One = XMVectorSet(1.0f, 1.0f, 1.0f, 1.0f); XMVECTOR Zero = XMVectorZero(); // Keep trying until we get a point on/in the hemisphere. while(true) { // Generate random point in the cube [-1,1]^3. XMVECTOR v = XMVectorSet(MathHelper::RandF(-1.0f, 1.0f), MathHelper::RandF(-1.0f, 1.0f), MathHelper::RandF(-1.0f, 1.0f), 0.0f); // Ignore points outside the unit sphere in order to get an even distribution // over the unit sphere. Otherwise points will clump more on the sphere near // the corners of the cube. if( XMVector3Greater( XMVector3LengthSq(v), One) ) continue; // Ignore points in the bottom hemisphere. if( XMVector3Less( XMVector3Dot(n, v), Zero ) ) continue; return XMVector3Normalize(v); } }
XMVECTOR MathHelper::RandUnitVec3() { XMVECTOR One = XMVectorSet(1.0f, 1.0f, 1.0f, 1.0f); XMVECTOR Zero = XMVectorZero(); while (true) { // Generate random point in the cube [-1,1]^3. XMVECTOR v = XMVectorSet(MathHelper::RandF(-1.0f, 1.0f), MathHelper::RandF(-1.0f, 1.0f), MathHelper::RandF(-1.0f, 1.0f), 0.0f); // Ignore points outside the unit sphere in order to get an even distribution // over the unit sphere. Otherwise points will clump more on the sphere near // the corners of the cube. if (XMVector3Greater(XMVector3LengthSq(v), One))//知道代码意思,但是代码实际执行看不懂。知其然不知其所以然 continue; return XMVector3Normalize(v); } }
void rtBIHNode::buildSubNodes(rtNodeBuildDesc* pDesc, UINT* pCounter) { size_t dataSize = sizeof(rtBIHLeaf*) * pDesc->leavesCount; if (pDesc->leavesCount < 3) { m_pLeaves = (rtBIHLeaf**)pDesc->pLeavesMemPool->alloc(dataSize); memcpy_4(m_pLeaves, pDesc->pSrcLeaves, dataSize); m_Flags = BIH_LEAF | (pDesc->leavesCount << 2); return; } LARGE_INTEGER start, stop; // sort leaves for (UINT i = 0; i<3; i++) { if (i != pDesc->sortedBy) { memcpy_4(pDesc->pSortedLeaves[i], pDesc->pSrcLeaves, dataSize); if (pDesc->leavesCount > INSERT_SORT_TRESHOLD+1) quickSortObjectsByAxis(pDesc->pSortedLeaves[i], 0, pDesc->leavesCount-1, i); else insertSortObjectsByAxis(pDesc->pSortedLeaves[i], 0, pDesc->leavesCount-1, i); } } if (pDesc->sortedBy < 3) memcpy_4(pDesc->pSortedLeaves[pDesc->sortedBy], pDesc->pSrcLeaves, dataSize); XMVECTOR leftCost, rightCost, totalCost; XMVECTOR bestCost = XMVectorReplicate(1.0e+30f); UINT bestAxis = 3; UINT bestSplitPos = 0; int i; QueryPerformanceCounter(&start); for (UINT axis = 0; axis<3; axis++) { //calculate possible left node aabbs pDesc->LeftAABBs[0] = pDesc->pSortedLeaves[axis][0]->box; XMVECTOR prevMin = pDesc->LeftAABBs[0].Min; XMVECTOR prevMax = pDesc->LeftAABBs[0].Max; for (i = 1; i<pDesc->leavesCount; i++) { prevMin = XMVectorMin(prevMin, pDesc->pSortedLeaves[axis][i]->box.Min); prevMax = XMVectorMax(prevMax, pDesc->pSortedLeaves[axis][i]->box.Max); pDesc->LeftAABBs[i].Min = prevMin; pDesc->LeftAABBs[i].Max = prevMax; } //calculate possible right node aabbs pDesc->RightAABBs[pDesc->leavesCount-1] = pDesc->pSortedLeaves[axis][pDesc->leavesCount-1]->box; prevMin = pDesc->RightAABBs[pDesc->leavesCount-1].Min; prevMax = pDesc->RightAABBs[pDesc->leavesCount-1].Max; for (i = pDesc->leavesCount-2; i>=0; i--) { prevMin = XMVectorMin(prevMin, pDesc->pSortedLeaves[axis][i]->box.Min); prevMax = XMVectorMax(prevMax, pDesc->pSortedLeaves[axis][i]->box.Max); pDesc->RightAABBs[i].Min = prevMin; pDesc->RightAABBs[i].Max = prevMax; } UINT splitpos; UINT max_splitpos = pDesc->leavesCount-1; XMVECTOR leftCount, rightcount; switch (pDesc->heuristics) { case SURFACE_AREA: for (splitpos = 2; splitpos<max_splitpos; splitpos++) { leftCost = pDesc->LeftAABBs[splitpos].getSurfaceArea(); rightCost = pDesc->RightAABBs[splitpos+1].getSurfaceArea(); leftCount = XMConvertVectorUIntToFloat(XMVectorReplicateInt(splitpos + 1), 0); rightcount = XMConvertVectorUIntToFloat(XMVectorReplicateInt(max_splitpos - splitpos), 0); totalCost = leftCost*leftCount + rightCost*rightcount; if (XMVector3Greater(bestCost, totalCost)) { bestAxis = axis; bestSplitPos = splitpos; bestCost = totalCost; } } break; case VOLUME: for (splitpos = 2; splitpos<max_splitpos; splitpos++) { leftCost = pDesc->LeftAABBs[splitpos].getVolume(); rightCost = pDesc->RightAABBs[splitpos+1].getVolume(); leftCount = XMVectorReplicate((float)(splitpos + 1)); rightcount = XMVectorReplicate((float)(max_splitpos - splitpos)); totalCost = leftCost*leftCount + rightCost*rightcount; if (XMVector3Greater(bestCost, totalCost)) { bestAxis = axis; bestSplitPos = splitpos; bestCost = totalCost; } } break; } } QueryPerformanceCounter(&stop); g_sortingTime.QuadPart += stop.QuadPart - start.QuadPart; if (bestAxis >= 3) { bestSplitPos = 1; bestAxis = 0; /* m_pLeaves = (rtBIHLeaf**)pDesc->pLeavesMemPool->alloc(dataSize); memcpy_4(m_pLeaves, pDesc->pSrcLeaves, dataSize); m_Flags = BIH_LEAF | (pDesc->leavesCount << 2); return; */ } // m_pChild = (rtBIHNode*)pDesc->pNodesMemPool->alloc(sizeof(rtBIHNode)*2); UINT childLeavesCount; rtNodeBuildDesc desc; desc.heuristics = pDesc->heuristics; desc.pLeavesMemPool = pDesc->pLeavesMemPool; desc.pNodesMemPool = pDesc->pNodesMemPool; desc.LeftAABBs = pDesc->LeftAABBs; desc.RightAABBs = pDesc->RightAABBs; desc.pSortedLeaves[0] = pDesc->pSortedLeaves[0]; desc.pSortedLeaves[1] = pDesc->pSortedLeaves[1]; desc.pSortedLeaves[2] = pDesc->pSortedLeaves[2]; desc.sortedBy = bestAxis; //construct left node m_pChild[0] = rtBIHNode(); m_pChild[0].m_ID = *pCounter; m_pChild[0].m_pParent = this; desc.leavesCount = bestSplitPos+1; desc.pSrcLeaves = pDesc->pSortedLeaves[bestAxis]; (*pCounter)++; m_pChild[0].buildSubNodes(&desc, pCounter); //construct right node m_pChild[1] = rtBIHNode(); m_pChild[1].m_ID = *pCounter; m_pChild[1].m_pParent = this; desc.leavesCount = pDesc->leavesCount - (bestSplitPos+1); desc.pSrcLeaves = &(pDesc->pSortedLeaves[bestAxis][bestSplitPos+1]); (*pCounter)++; m_pChild[1].buildSubNodes(&desc, pCounter); m_Flags = bestAxis; }
BSphere ComputeBoundingSphereFromPoints(const XMFLOAT3* points, uint32 numPoints, uint32 stride, BBox *optionalBBoxOut) { BSphere sphere; Assert_(numPoints > 0); Assert_(points); // Find the points with minimum and maximum x, y, and z XMVECTOR MinX, MaxX, MinY, MaxY, MinZ, MaxZ; MinX = MaxX = MinY = MaxY = MinZ = MaxZ = XMLoadFloat3(points); GetBoundCornersFromPoints(points, numPoints, stride, MinX, MaxX, MinY, MaxY, MinZ, MaxZ); /*for (uint32 i = 1; i < numPoints; i++) { XMVECTOR Point = XMLoadFloat3((XMFLOAT3*)((BYTE*)points + i * stride)); float px = XMVectorGetX(Point); float py = XMVectorGetY(Point); float pz = XMVectorGetZ(Point); if (px < XMVectorGetX(MinX)) MinX = Point; if (px > XMVectorGetX(MaxX)) MaxX = Point; if (py < XMVectorGetY(MinY)) MinY = Point; if (py > XMVectorGetY(MaxY)) MaxY = Point; if (pz < XMVectorGetZ(MinZ)) MinZ = Point; if (pz > XMVectorGetZ(MaxZ)) MaxZ = Point; }*/ if (optionalBBoxOut != NULL) { float maxx = XMVectorGetX(MaxX); float maxy = XMVectorGetY(MaxY); float maxz = XMVectorGetZ(MaxZ); float minx = XMVectorGetX(MinX); float miny = XMVectorGetY(MinY); float minz = XMVectorGetZ(MinZ); optionalBBoxOut->Max.x = maxx; optionalBBoxOut->Max.y = maxy; optionalBBoxOut->Max.z = maxz; optionalBBoxOut->Min.x = minx; optionalBBoxOut->Min.y = miny; optionalBBoxOut->Min.z = minz; } // Use the min/max pair that are farthest apart to form the initial sphere. XMVECTOR DeltaX = MaxX - MinX; XMVECTOR DistX = XMVector3Length(DeltaX); XMVECTOR DeltaY = MaxY - MinY; XMVECTOR DistY = XMVector3Length(DeltaY); XMVECTOR DeltaZ = MaxZ - MinZ; XMVECTOR DistZ = XMVector3Length(DeltaZ); XMVECTOR Center; XMVECTOR Radius; if (XMVector3Greater(DistX, DistY)) { if (XMVector3Greater(DistX, DistZ)) { // Use min/max x. Center = (MaxX + MinX) * 0.5f; Radius = DistX * 0.5f; } else { // Use min/max z. Center = (MaxZ + MinZ) * 0.5f; Radius = DistZ * 0.5f; } } else // Y >= X { if (XMVector3Greater(DistY, DistZ)) { // Use min/max y. Center = (MaxY + MinY) * 0.5f; Radius = DistY * 0.5f; } else { // Use min/max z. Center = (MaxZ + MinZ) * 0.5f; Radius = DistZ * 0.5f; } } // Add any points not inside the sphere. for (uint32 i = 0; i < numPoints; i++) { XMVECTOR Point = XMLoadFloat3((XMFLOAT3*)((BYTE*)points + i * stride)); XMVECTOR Delta = Point - Center; XMVECTOR Dist = XMVector3Length(Delta); if (XMVector3Greater(Dist, Radius)) { // Adjust sphere to include the new point. Radius = (Radius + Dist) * 0.5f; Center += (XMVectorReplicate(1.0f) - Radius * XMVectorReciprocal(Dist)) * Delta; } } XMStoreFloat3(&sphere.Center, Center); XMStoreFloat(&sphere.Radius, Radius); return sphere; }