bool UnitSquare::intersect( Ray3D& ray, const Matrix4x4& worldToModel, const Matrix4x4& modelToWorld ) { // TODO: implement intersection code for UnitSquare, which is // defined on the xy-plane, with vertices (0.5, 0.5, 0), // (-0.5, 0.5, 0), (-0.5, -0.5, 0), (0.5, -0.5, 0), and normal // (0, 0, 1). // // Your goal here is to fill ray.intersection with correct values // should an intersection occur. This includes intersection.point, // intersection.normal, intersection.none, intersection.t_hit. // // HINT: Remember to first transform the ray into object space // to simplify the intersection test. Ray3D modelRay; // To store transformed model space ray. Vector3D surfaceNormal(0, 0, 1); // Constant surface normal. double t; // Intersection parameter. // Transform ray to model space. modelRay.origin = worldToModel * ray.origin; modelRay.dir = worldToModel * ray.dir;; // Compute intersection between ray and XY-plane. double d_dot_n = modelRay.dir.dot(surfaceNormal); // TODO: NEED MORE STABLE FLOAT EQUAL CHECK! if (d_dot_n == 0.0) { // Ray is parallel to plane. return false; } // Compute intersection and check if it occurs infront or behind the camera. t = -(Vector3D(modelRay.origin[0], modelRay.origin[1], modelRay.origin[2]).dot(surfaceNormal)) / d_dot_n; if (t < ray.intersection.t_min || t > ray.intersection.t_max) { return false; } if (!ray.intersection.none && t > ray.intersection.t_hit) { return false; } // Compute intersection point and check againt unit square bounds. Point3D intPoint = modelRay.origin + (t * modelRay.dir); if (!(intPoint[0] >= -0.5 && intPoint[0] <= 0.5 && intPoint[1] >= -0.5 && intPoint[1] <= 0.5)) { return false; } // Transform and set intersection info. ray.intersection.point = modelToWorld * intPoint; ray.intersection.normal = transNorm(worldToModel, surfaceNormal); ray.intersection.normal.normalize(); ray.intersection.t_hit = t; ray.intersection.none = false; ray.intersection.inside = false; return true; }
/* recalcul des normales */ void updtNorms(void) { int i,j; int ptrFlSize = sizeof(GLfloat*); char errMsg[] = "Erreur après realloc."; /* normales des faces dans lesquelles les sommets sont compris */ GLfloat** vrtxFacesNorm[VERTICES_BOX01]; GLfloat faceNormals[FACES_BOX01][3]; GLint currSize[VERTICES_BOX01]; for(i = 0; i < FACES_BOX01; i++) surfaceNormal( &vertices[3*faces[i][0]], &vertices[3*faces[i][1]], &vertices[3*faces[i][2]], &faceNormals[i][0]); memset(currSize, 0, VERTICES_BOX01*sizeof(GLint)); memset(vrtxFacesNorm, 0, VERTICES_BOX01*sizeof(GLfloat**)); /* initialisaition de vrtxFacesNorm */ for(i = 0; i < FACES_BOX01; i++) { for(j = 0; j < 3; j++) { currSize[faces[i][j]]++; vrtxFacesNorm[faces[i][j]] = (GLfloat**)realloc(vrtxFacesNorm[faces[i][j]], currSize[faces[i][j]]*ptrFlSize); if (vrtxFacesNorm[faces[i][j]] == NULL) { // AnsiToOem(errMsg, errMsg); printf(errMsg); exit(1); } vrtxFacesNorm[faces[i][j]][currSize[faces[i][j]]-1] = &faceNormals[i][0]; } } /* calcul des normales des sommets */ for(i = 0; i < VERTICES_BOX01; i++) vertexNormal(vrtxFacesNorm[i], currSize[i], &norm[i*3]); }
// vMarchCube1 performs the Marching Cubes algorithm on a single cube GLvoid MarchingCubes::vMarchCube1(const GLint &iX, const GLint &iY, const GLint &iZ, const GLfloat& isoValue) { GLfloat fX(iX*m_stepSize); GLfloat fY(iY*m_stepSize); GLfloat fZ(iZ*m_stepSize); GLint iCorner, iVertex, iVertexTest, iEdge, iTriangle, iFlagIndex, iEdgeFlags; GLfloat fOffset; GLfloat afCubeValue[8]; GLvector asEdgeVertex[12]; GLvector asEdgeNorm[12]; // Make a local copy of the values at the cube's corners for (iVertex = 0; iVertex < 8; iVertex++) { afCubeValue[iVertex] = (*m_grid)(iX + s_vertexIndexOffset[iVertex][0], iY + s_vertexIndexOffset[iVertex][1], iZ + s_vertexIndexOffset[iVertex][2]); } // Find which vertices are inside of the surface and which are outside iFlagIndex = 0; for (iVertexTest = 0; iVertexTest < 8; iVertexTest++) { if (afCubeValue[iVertexTest] <= isoValue) iFlagIndex |= 1<<iVertexTest; } // Find which edges are intersected by the surface iEdgeFlags = s_cubeEdgeFlags[iFlagIndex]; // If the cube is entirely inside or outside of the surface, then there will // be no intersections if(iEdgeFlags == 0) return; // Find the point of intersection of the surface with each edge // Then find the normal to the surface at those points for (iEdge = 0; iEdge < 12; iEdge++) { // if there is an intersection on this edge if (iEdgeFlags & (1<<iEdge)) { fOffset = getOffset(afCubeValue[ s_edgeConnection[iEdge][0] ], afCubeValue[ s_edgeConnection[iEdge][1] ], isoValue); asEdgeVertex[iEdge].fX = fX + (s_vertexOffset[ s_edgeConnection[iEdge][0] ][0] + fOffset * s_edgeDirection[iEdge][0]) * m_stepSize; asEdgeVertex[iEdge].fY = fY + (s_vertexOffset[ s_edgeConnection[iEdge][0] ][1] + fOffset * s_edgeDirection[iEdge][1]) * m_stepSize; asEdgeVertex[iEdge].fZ = fZ + (s_vertexOffset[ s_edgeConnection[iEdge][0] ][2] + fOffset * s_edgeDirection[iEdge][2]) * m_stepSize; surfaceNormal(asEdgeNorm[iEdge], asEdgeVertex[iEdge].fX, asEdgeVertex[iEdge].fY, asEdgeVertex[iEdge].fZ); if (isoValue < 0) { asEdgeNorm[iEdge].fX = - asEdgeNorm[iEdge].fX; asEdgeNorm[iEdge].fY = - asEdgeNorm[iEdge].fY; asEdgeNorm[iEdge].fZ = - asEdgeNorm[iEdge].fZ; } } } // Draw the triangles that were found. There can be up to five per cube for (iTriangle = 0; iTriangle < 5; iTriangle++) { if (s_triangleConnectionTable[iFlagIndex][3*iTriangle] < 0) break; for (iCorner = 0; iCorner < 3; iCorner++) { iVertex = s_triangleConnectionTable[iFlagIndex][3*iTriangle+iCorner]; m_surfaceData.push_back(asEdgeNorm[iVertex].fX); m_surfaceData.push_back(asEdgeNorm[iVertex].fY); m_surfaceData.push_back(asEdgeNorm[iVertex].fZ); m_surfaceData.push_back(asEdgeVertex[iVertex].fX); m_surfaceData.push_back(asEdgeVertex[iVertex].fY); m_surfaceData.push_back(asEdgeVertex[iVertex].fZ); } } }