void CObjectNode::RenderPatch(int nSeedU, int nSeedV, CMultiTexData* pTexData, int nTexData) { CObjectNode* pN1; CObjectNode* pN2; CObjectNode* pN3; CObjectNode* pN4; CNodeData aEdges[4][64]; CNodeData aHLine1[64]; CNodeData aHLine2[64]; CNodeData* pHLine1 = aHLine1; CNodeData* pHLine2 = aHLine2; CNodeData* pTmp; float fU, fV; int nV, nU, nTex; CNodeData cE1, cE2, cE3, cE4, cE; /* calculate edge 1 */ pN2 = pN1 = GetValidLeft(); pN1 = pN1->GetValidUp(); pN3 = pN2->GetValidDown(); pN4 = pN3->GetValidDown(); aEdges[0][0] = pN2->m_cNodeData; for (nV = 1; nV != nSeedV - 1; nV++) { fV = (float)nV / (float)(nSeedV - 1); SInterpolate(aEdges[0][nV], pN1, pN2, pN3, pN4, fV); } aEdges[0][nSeedV - 1] = pN3->m_cNodeData; /* calculate edge 2 */ pN1 = GetValidUp(); pN2 = this; pN3 = GetValidDown(); pN4 = pN3->GetValidDown(); aEdges[1][0] = pN2->m_cNodeData; for (nV = 1; nV != nSeedV - 1; nV++) { fV = (float)nV / (float)(nSeedV - 1); SInterpolate(aEdges[1][nV], pN1, pN2, pN3, pN4, fV); } aEdges[1][nSeedV - 1] = pN3->m_cNodeData; /* calculate edge 3 */ pN2 = pN1 = GetValidRight(); pN1 = pN1->GetValidUp(); pN3 = pN2->GetValidDown(); pN4 = pN3->GetValidDown(); aEdges[2][0] = pN2->m_cNodeData; for (nV = 1; nV != nSeedV - 1; nV++) { fV = (float)nV / (float)(nSeedV - 1); SInterpolate(aEdges[2][nV], pN1, pN2, pN3, pN4, fV); } aEdges[2][nSeedV - 1] = pN3->m_cNodeData; /* calculate edge 4 */ pN2 = pN2->GetValidRight(); pN1 = pN2->GetValidUp(); pN3 = pN2->GetValidDown(); pN4 = pN3->GetValidDown(); aEdges[3][0] = pN2->m_cNodeData; for (nV = 1; nV != nSeedV - 1; nV++) { fV = (float)nV / (float)(nSeedV - 1); SInterpolate(aEdges[3][nV], pN1, pN2, pN3, pN4, fV); } aEdges[3][nSeedV - 1] = pN3->m_cNodeData; /* make faces */ int nWrap; if (m_nWarapUV) nWrap = 1; else if (GetValidLeft()->m_nWarapUV) nWrap = -1; else nWrap = 0; /* if (nWrap == 0) pHLine1[0] = aEdges[1][0]; else if (nWrap > 0) { pHLine1[0] = aEdges[1][0]; pHLine1[0].m_cTexel.fU += 1.0f; } else { pHLine1[0] = aEdges[1][0]; } */ for (nU = 0; nU != nSeedU ; nU++) { fU = (float)nU/(float)(nSeedU - 1); SInterpolate(pHLine1[nU], aEdges[0][0], aEdges[1][0], aEdges[2][0], aEdges[3][0], fU, nWrap); } //pHLine1[nSeedU - 1] = aEdges[2][0]; for (nV = 1; nV != nSeedV; nV++) { //pHLine2[0] = aEdges[1][nV]; for (nU = 0; nU != nSeedU; nU++) { fU = (float)nU/(float)(nSeedU - 1); SInterpolate(pHLine2[nU], aEdges[0][nV], aEdges[1][nV], aEdges[2][nV], aEdges[3][nV], fU, nWrap); } //pHLine2[0] = aEdges[2][nV]; /* oki.. we've got here a strip, so render it */ #ifdef GL_VERSION_ES_CM_1_1 glClientActiveTexture(GL_TEXTURE0); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); #endif for (nTex = 0; nTex != nTexData; nTex++) { if (pTexData[nTex].m_nGLTexName) { glBindTexture(GL_TEXTURE_2D, *pTexData[nTex].m_nGLTexName); #ifndef GL_VERSION_ES_CM_1_1 glBegin(GL_TRIANGLES); #endif if (pTexData[nTex].m_nMaterial & 1) { for (nU = 0; nU != nSeedU - 1; nU++) { glFace(pHLine1[nU], pHLine1[nU + 1], pHLine2[nU], pTexData[nTex].m_fAlpha, pTexData[nTex].m_fUShift, pTexData[nTex].m_fVShift); glFace(pHLine1[nU + 1], pHLine2[nU + 1], pHLine2[nU], pTexData[nTex].m_fAlpha, pTexData[nTex].m_fUShift, pTexData[nTex].m_fVShift); } } else if (pTexData[nTex].m_nMaterial & 2) { for (nU = 0; nU != nSeedU - 1; nU++) { glEnv(pHLine1[nU], pHLine1[nU + 1], pHLine2[nU], pTexData[nTex].m_fAlpha); glEnv(pHLine1[nU + 1], pHLine2[nU + 1], pHLine2[nU], pTexData[nTex].m_fAlpha); } } #ifndef GL_VERSION_ES_CM_1_1 glEnd(); #endif } } #ifdef GL_VERSION_ES_CM_1_1 glFaceFlush(); glEnvFlush(); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); #endif pTmp = pHLine1; pHLine1 = pHLine2; pHLine2 = pTmp; } }
void CalculateBasisComponents(const MDoubleArray& weights, const BaryCoords& coords, const MIntArray& triangleVertices, const MPointArray& points, const MFloatVectorArray& normals, const MIntArray& sampleIds, double* alignedStorage, MPoint& origin, MVector& up, MVector& normal) { // Start with the recreated point and normal using the barycentric coordinates of the hit point. unsigned int hitIndex = weights.length()-1; #ifdef __AVX__ __m256d originV = Dot4<MPoint>(coords[0], coords[1], coords[2], 0.0, points[triangleVertices[0]], points[triangleVertices[1]], points[triangleVertices[2]], MPoint::origin); __m256d hitNormalV = Dot4<MVector>(coords[0], coords[1], coords[2], 0.0, normals[triangleVertices[0]], normals[triangleVertices[1]], normals[triangleVertices[2]], MVector::zero); __m256d hitWeightV = _mm256_set1_pd(weights[hitIndex]); // Create the barycentric point and normal. __m256d normalV = _mm256_mul_pd(hitNormalV, hitWeightV); // Then use the weighted adjacent data. for (unsigned int j = 0; j < hitIndex; j += 4) { __m256d tempNormal = Dot4<MVector>(weights[j], weights[j+1], weights[j+2], weights[j+3], normals[sampleIds[j]], normals[sampleIds[j+1]], normals[sampleIds[j+2]], normals[sampleIds[j+3]]); normalV = _mm256_add_pd(tempNormal, normalV); } _mm256_store_pd(alignedStorage, originV); origin.x = alignedStorage[0]; origin.y = alignedStorage[1]; origin.z = alignedStorage[2]; _mm256_store_pd(alignedStorage, normalV); normal.x = alignedStorage[0]; normal.y = alignedStorage[1]; normal.z = alignedStorage[2]; // Calculate the up vector const MPoint& pt1 = points[triangleVertices[0]]; const MPoint& pt2 = points[triangleVertices[1]]; __m256d p1 = _mm256_set_pd(pt1.w, pt1.z, pt1.y, pt1.x); __m256d p2 = _mm256_set_pd(pt2.w, pt2.z, pt2.y, pt2.x); p1 = _mm256_add_pd(p1, p2); __m256d half = _mm256_set_pd(0.5, 0.5, 0.5, 0.5); p1 = _mm256_mul_pd(p1, half); __m256d upV = _mm256_sub_pd(p1, originV); _mm256_store_pd(alignedStorage, upV); up.x = alignedStorage[0]; up.y = alignedStorage[1]; up.z = alignedStorage[2]; #else MVector hitNormal; // Create the barycentric point and normal. for (int i = 0; i < 3; ++i) { origin += points[triangleVertices[i]] * coords[i]; hitNormal += MVector(normals[triangleVertices[i]]) * coords[i]; } // Use crawl data to calculate normal normal = hitNormal * weights[hitIndex]; for (unsigned int j = 0; j < hitIndex; j++) { normal += MVector(normals[sampleIds[j]]) * weights[j]; } // Calculate the up vector // The triangle vertices are sorted by decreasing barycentric coordinates so the first two are // the two closest vertices in the triangle. up = ((points[triangleVertices[0]] + points[triangleVertices[1]]) * 0.5) - origin; #endif normal.normalize(); GetValidUp(weights, points, sampleIds, origin, normal, up); }