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;
}
Example #2
0
/* 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]);
}
Example #3
0
// 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);
       }
   }
}