예제 #1
0
bool QuadTree::Pick(D3DXVECTOR3 vPickRayDir, D3DXVECTOR3 vPickRayOrig, BoxNode box)
{
	/*
		|\
		| \
		|__\	*/
	D3DXVECTOR3 v0 = box.minB;
	D3DXVECTOR3 v1 = D3DXVECTOR3(box.minB.x, pLand->getHeight(box.minB.x, box.maxB.z)+1, box.maxB.z);
	D3DXVECTOR3 v2 = D3DXVECTOR3(box.maxB.x, pLand->getHeight(box.maxB.x, box.minB.z)+1, box.minB.z);

	/*	___
		\  |
		 \ |
		  \|	*/
	D3DXVECTOR3 v3 = v1;
	D3DXVECTOR3 v4 = v2;
	D3DXVECTOR3 v5 = box.maxB;

	//Check if the pick ray passes through triangles
	if( IntersectTriangle( vPickRayOrig, vPickRayDir, v0, v1, v2) )
		return true;
	else if( IntersectTriangle( vPickRayOrig, vPickRayDir, v3, v4, v5) )
		return true;

	return false;
}
예제 #2
0
bool RayTesselatedTrianglePrimitive::Intersect(const Ray& ray, Intersection* intersection) {
    Vec3f v0, v1, v2;
    _ResolveVertexAttrib(v0,v1,v2,triangles->pos);
    float t, b1, b2, rayEpsilon;
    bool hit = IntersectTriangle(v0,v1,v2,ray, &t, &b1, &b2, &rayEpsilon);

    if(hit) {
        // geometry
        intersection->t = t;
        intersection->rayEpsilon = rayEpsilon;
        intersection->dp.P = ray.Eval(t);
        intersection->dp.uv = Vec2f(b1,b2);
        if(triangles->normal.empty()) {
            intersection->dp.Ng = triangles->faceNormal[idx];
            intersection->dp.N = triangles->faceNormal[idx];
        } else {
            intersection->dp.Ng = ElementOperations::TriangleNormal(v0,v1,v2);
            intersection->dp.N = _InterpolateVertexAttrib(b1,b2,triangles->normal).GetNormalized();
        }
        intersection->dp.GenerateTuTv();

        // shading
        if(triangles->uv.empty()) {
            intersection->dp.st = intersection->dp.uv;
        } else {
            intersection->dp.st = _InterpolateVertexAttrib(b1,b2,triangles->uv);
        }

        // material
        intersection->m = material;
    }

    return hit;
}
예제 #3
0
bool IsShadowed(int currPrimitiveNum, Ray &rayToLight, float distanceToLight, Primitive *primitives, int numPrimitives)
{  
  TraceResult traceResult;
  traceResult.hit=false;
  // check all spheres 
  for(int i=0; i<numPrimitives; i++)
    {
      if( i == currPrimitiveNum ) continue;//no auto
      
      switch(primitives[i].type)
        {
	case SPHERE_TYPE: 
	  traceResult = IntersectSphere(*primitives[i].sphereProperties, rayToLight);
	  break;
	case PLANE_TYPE:
	  traceResult = IntersectPlane(*primitives[i].planeProperties, rayToLight);
	  break;
	case CYLINDER_TYPE:
	  traceResult = IntersectCylinder(*primitives[i].cylinderProperties, rayToLight);
	  break;
	case TRIANGLE_TYPE:
	  traceResult = IntersectTriangle(*primitives[i].triangleProperties, rayToLight);
	  break;
	default:
	  continue; 
	  break;
        }
        
      if( traceResult.hit && (traceResult.distance < distanceToLight) )
	return true;
        
    }
    
  return false;
}
예제 #4
0
Bool kDOPTree::LineCheck( kDOPNode* pNode, const Ray3f& pRay ) const
{
    if( Intersect( pRay, pNode->mBoundingBox ) )
    {
        // At the root.
        if( pNode->mTriangleIndices.size() != 0 )
        {
            // Check each triangles.
            const Trianglef* tri;
            for( UInt32 i = 0; i < pNode->mTriangleIndices.size(); i++ )
            {
                tri = &mTriangles[pNode->mTriangleIndices[i]];
                if( IntersectTriangle( mVertices[tri->mIndices[0]], mVertices[tri->mIndices[1]], mVertices[tri->mIndices[2]], pRay ) )
                    return true;
            }

            return false;
        }
        else
        {
            // Check childs.
            return LineCheck( mNodes[pNode->mChildsIndex + 0], pRay ) ||
                   LineCheck( mNodes[pNode->mChildsIndex + 1], pRay );
        }
    }

    return false;
}
예제 #5
0
bool TriObj::TraceBVHNode(const Ray& ray, HitInfo& hInfo, int hitSide, unsigned nodeID) const
{
	bool isHit = false;
	if(bvh.IsLeafNode(nodeID))
	{
		if(Box(bvh.GetNodeBounds(nodeID)).IntersectRay(ray,hInfo.z))
		{
			unsigned int noOfFacesInLeafNode = bvh.GetNodeElementCount(nodeID);
			
			for (int i = 0; i < noOfFacesInLeafNode; i++)
			{
				isHit |= IntersectTriangle(ray, hInfo, hitSide, bvh.GetNodeElements(nodeID)[i]);
			}
		}
		else
		{
			isHit = false;
		}
	}
	else
	{
		isHit |= TraceBVHNode(ray, hInfo, hitSide, bvh.GetFirstChildNode(nodeID));
		isHit |= TraceBVHNode(ray, hInfo, hitSide, bvh.GetSecondChildNode(nodeID));
	}
	
	return isHit;
}
예제 #6
0
/** Intersects the whole primitive. If hit, it returns a distance other than -1 */
float EditorLinePrimitive::IntersectPrimitive(D3DXVECTOR3* RayOrigin, D3DXVECTOR3* RayDirection, float Epsilon)
{
	UINT i;
	float Shortest = -1;

	// Bring the ray into object space
	D3DXMATRIX invWorld;
	D3DXMatrixInverse(&invWorld, NULL, &WorldMatrix);

	D3DXVECTOR3 Origin;
	D3DXVECTOR3 Dir;
	D3DXVec3TransformCoord(&Origin, RayOrigin, &invWorld);
	D3DXVec3TransformNormal(&Dir, RayDirection, &invWorld);

	// Go through all line segments and intersect them
	for(i = 0; i < NumVertices; i+=2)
	{	
		D3DXVECTOR3 vx[2];
		D3DXVec3TransformCoord(&vx[0], Vertices[i].Position.toD3DXVECTOR3(), &WorldMatrix);
		D3DXVec3TransformCoord(&vx[1], Vertices[i+1].Position.toD3DXVECTOR3(), &WorldMatrix);

		//float Dist = IntersectLineSegment(&Origin, &Dir, Vertices[i].Position.toD3DXVECTOR3(), Vertices[i+1].Position.toD3DXVECTOR3(), Epsilon);
		float Dist = IntersectLineSegment(RayOrigin, RayDirection, &vx[0], &vx[1], Epsilon);
		if(Dist < Shortest || Shortest == -1)
		{
			Shortest = Dist / Scale.x;
		}
	}

	if(NumSolidVertices>0)
	{
		FLOAT fBary1, fBary2;
		FLOAT fDist;
		int NumIntersections=0;
		Shortest = FLT_MAX;
		
		for( DWORD i = 0; i < NumSolidVertices; i+=3 )
		{
			D3DXVECTOR3 v0 = *SolidVertices[i + 0].Position.toD3DXVECTOR3();
			D3DXVECTOR3 v1 = *SolidVertices[i + 1].Position.toD3DXVECTOR3();
			D3DXVECTOR3 v2 = *SolidVertices[i + 2].Position.toD3DXVECTOR3();

			// Check if the pick ray passes through this point
			if( IntersectTriangle( &Origin, &Dir, v0, v1, v2,
				&fDist, &fBary1, &fBary2 ) )
			{
				if( fDist < Shortest  || Shortest == -1)
				{
					NumIntersections++;
					Shortest=0;
								
					//if( NumIntersections == MAX_INTERSECTIONS )
					//	break;
				}
			}
		}
	}

	return Shortest;
}
예제 #7
0
파일: Object.cpp 프로젝트: Mootie/ATools
bool CObject::Pick(const D3DXVECTOR3& origin, const D3DXVECTOR3& dir, float& dist)
{
	static int indexTable[12 * 3] =
	{
		3, 2, 6, 3, 6, 7,
		0, 3, 7, 0, 7, 4,
		1, 2, 6, 1, 6, 5,
		0, 1, 2, 0, 2, 3,
		0, 4, 5, 0, 5, 1,
		4, 5, 6, 4, 6, 7
	};

	bool pick = false;
	float tempDist;
	dist = 65535.0f;

	for (int i = 0; i < 12 * 3; i += 3)
	{
		if (IntersectTriangle(m_bounds[indexTable[i]], m_bounds[indexTable[i + 1]], m_bounds[indexTable[i + 2]], origin, dir, tempDist) && tempDist < dist)
		{
			dist = tempDist;
			pick = true;
		}
	}

	if (pick)
	{
		if (m_modelProp->modelType == MODELTYPE_SFX)
			return true;
		else
			return m_model->Pick(m_TM, origin, dir, dist);
	}

	return false;
}
예제 #8
0
	bool operator()(const G3D::Ray& ray, uint32 entry, float& distance,
			bool /*pStopAtFirstHit*/) {
		bool result = IntersectTriangle(triangles[entry], vertices, ray,
				distance);
		if (result)
			hit = true;
		return hit;
	}
예제 #9
0
float IntersectTriangle_KDtree(float *Di,int *Uaxis,int *Vaxis,int *Waxis,float *lambda_num,float *bnu,float *bnv,float *cnu,float *cnv,float *Cu,float *Cv,float *nu,float *nv,float *vu,float *vv,KDtree *kd,float min_lambda,float max_lambda,float *C,int *jmax) {
  // Base case:
  if((kd->left==NULL) && (kd->right==NULL)) {
    // Intersect with leaf node's triangles:
    return IntersectTriangle(Di,Uaxis,Vaxis,Waxis,lambda_num,bnu,bnv,cnu,cnv,Cu,Cv,nu,nv,vu,vv,kd->leaves,kd->dim,jmax);
  }

  float val_min = Di[kd->dim]*min_lambda+C[kd->dim];
  float val_max = Di[kd->dim]*max_lambda+C[kd->dim];

  // Check to see which side of plane (or both) ray lies on:
  if((val_min<=kd->split_direction) && (val_max<=kd->split_direction)) {
    // Go left:
    if(kd->left) {
      return IntersectTriangle_KDtree(Di,Uaxis,Vaxis,Waxis,lambda_num,bnu,bnv,cnu,cnv,Cu,Cv,nu,nv,vu,vv,kd->left,min_lambda,max_lambda,C,jmax);
    }
    else return -INF;
  }
  else if((val_min>kd->split_direction) && (val_max>kd->split_direction)) {
    // Go right:
    if(kd->right) {
      return IntersectTriangle_KDtree(Di,Uaxis,Vaxis,Waxis,lambda_num,bnu,bnv,cnu,cnv,Cu,Cv,nu,nv,vu,vv,kd->right,min_lambda,max_lambda,C,jmax);
    }
    else return -INF;
  }
  else {
    // Intersect ray with splitting direction plane:
    float lambda = (kd->split_direction-C[kd->dim])/Di[kd->dim];

    // Try partition that is closest to camera center:
    float maxLambda = -INF;
    if(C[kd->dim]<=kd->split_direction) {
      if(kd->left) {
	maxLambda = IntersectTriangle_KDtree(Di,Uaxis,Vaxis,Waxis,lambda_num,bnu,bnv,cnu,cnv,Cu,Cv,nu,nv,vu,vv,kd->left,min_lambda,lambda,C,jmax);
      }
    }
    else if(kd->right) {
      maxLambda = IntersectTriangle_KDtree(Di,Uaxis,Vaxis,Waxis,lambda_num,bnu,bnv,cnu,cnv,Cu,Cv,nu,nv,vu,vv,kd->right,min_lambda,lambda,C,jmax);
    }
    if((min_lambda>=maxLambda)&&(maxLambda>=lambda)) return maxLambda;

    // Otherwise, try other partition:
    if(C[kd->dim]<=kd->split_direction) {
      if(kd->right) {
	maxLambda = IntersectTriangle_KDtree(Di,Uaxis,Vaxis,Waxis,lambda_num,bnu,bnv,cnu,cnv,Cu,Cv,nu,nv,vu,vv,kd->right,lambda,max_lambda,C,jmax);
      }
    }
    else if(kd->left) {
      maxLambda = IntersectTriangle_KDtree(Di,Uaxis,Vaxis,Waxis,lambda_num,bnu,bnv,cnu,cnv,Cu,Cv,nu,nv,vu,vv,kd->left,lambda,max_lambda,C,jmax);
    }
    
    return maxLambda;
  }
}
예제 #10
0
bool CUtils::IntersectTriangle(const CRay &i_Ray,
                               CIntersactionInfo &io_IntersectionInfo,
                               const CVector3DF& i_vA,
                               const CVector3DF& i_vB,
                               const CVector3DF& i_vC,
                               const CVector3DF& i_vABar,
                               const CVector3DF& i_vBBar,
                               const CVector3DF& i_vCBar)
{
    if (!IntersectTriangle(i_Ray, io_IntersectionInfo, i_vA, i_vB, i_vC))
    {
        return false;
    }

    const CVector3DF vPA = i_vABar * io_IntersectionInfo.m_vBarCoordsLocal.X();
    const CVector3DF vPB = i_vBBar * io_IntersectionInfo.m_vBarCoordsLocal.Y();
    const CVector3DF vPC = i_vCBar * io_IntersectionInfo.m_vBarCoordsLocal.Z();

    io_IntersectionInfo.m_vBarCoordsGlobal = vPA + vPB + vPC;

    return true;
}
예제 #11
0
BOOL CBuildingCollisionMng::SelBuilding(
										FLOAT fOrigx, FLOAT fOrigy, FLOAT fOrigz,	// 射线的原点。
										FLOAT fDirx,  FLOAT fDiry,  FLOAT fDirz,	// 射线的方向。
										INT	  ix, INT iz,							// 选中地图的位置
										FLOAT& fPosx, FLOAT& fPosy, FLOAT& fPosz	// 返回建筑物的行走面位置。
										)
{
	FLOAT fDistance = 1000;

	INT iL = ix - BUILD_COLLISION_SEARCH_RANGE;
	INT iR = ix + BUILD_COLLISION_SEARCH_RANGE;
	INT iT = iz - BUILD_COLLISION_SEARCH_RANGE;
	INT iB = iz + BUILD_COLLISION_SEARCH_RANGE;

	POINT_2D pos;
	INT iSize = 0;
	POINT_3D Orig;	// 射线的原点。
	POINT_3D Dir;	// 射线的方向。
	POINT_3D v1;
	POINT_3D v2;
	POINT_3D v3;

	FLOAT fd = 0;
	FLOAT fv = 0;
	FLOAT fu = 0;

	Orig.fx = fOrigx;
	Orig.fy = fOrigy;
	Orig.fz = fOrigz;

	Dir.fx = fDirx;
	Dir.fy = fDiry;
	Dir.fz = fDirz;

	BOOL bReturn = FALSE;


	for(INT i = iL; i < iR; i++)
		for(INT j = iT; j < iB; j++)
		{
			pos.iX = i;
			pos.iY = j;
			if(0 == m_triInfoMap.count(pos))
			{
				continue;
			}

			TRI_INFO_VECTOR& triInfo = m_triInfoMap[pos];
			iSize = (INT)triInfo.size();
			for(INT iRri = 0; iRri < iSize; iRri++)
			{
				v1.fx = triInfo[iRri].v1.fx;
				v1.fy = triInfo[iRri].v1.fy;
				v1.fz = triInfo[iRri].v1.fz;

				v2.fx = triInfo[iRri].v2.fx;
				v2.fy = triInfo[iRri].v2.fy;
				v2.fz = triInfo[iRri].v2.fz;

				v3.fx = triInfo[iRri].v3.fx;
				v3.fy = triInfo[iRri].v3.fy;
				v3.fz = triInfo[iRri].v3.fz;

				if(IntersectTriangle(Orig, Dir, v1, v2, v3, &fd, &fu, &fv))
				{
					if(fDistance > fd)
					{
						fDistance = fd;
						fPosx = (1- fv - fu)*v1.fx + fu*v2.fx + fv*v3.fx;
						fPosy = (1- fv - fu)*v1.fy + fu*v2.fy + fv*v3.fy;
						fPosz = (1- fv - fu)*v1.fz + fu*v2.fz + fv*v3.fz;
					}

					bReturn = true;
				}

			}// for(INT iRri = 0; iRri < iSize; i++)

		}

	return bReturn;
}
예제 #12
0
v3 GetNormal(const RCONVEXPOLYGONINFO *poly, const rvector &position,
	int au, int av)
{
	int nSelPolygon = -1, nSelEdge = -1;
	float fMinDist = FLT_MAX;

	if (poly->nVertices == 3)
		nSelPolygon = 0;
	else
	{
		rvector pnormal(poly->plane.a, poly->plane.b, poly->plane.c);

		for (int i = 0; i < poly->nVertices - 2; i++)
		{
			const auto& a = poly->pVertices[0];
			const auto& b = poly->pVertices[i + 1];
			const auto& c = poly->pVertices[i + 2];

			if (IntersectTriangle(a, b, c, position + pnormal, -pnormal, nullptr))
			{
				nSelPolygon = i;
				nSelEdge = -1;
				break;
			}
			else
			{
				float dist = GetDistance(position, a, b);
				if (dist < fMinDist) { fMinDist = dist; nSelPolygon = i; nSelEdge = 0; }
				dist = GetDistance(position, b, c);
				if (dist < fMinDist) { fMinDist = dist; nSelPolygon = i; nSelEdge = 1; }
				dist = GetDistance(position, c, a);
				if (dist < fMinDist) { fMinDist = dist; nSelPolygon = i; nSelEdge = 2; }
			}
		}
	}

	auto& v0 = poly->pVertices[0];
	auto& v1 = poly->pVertices[nSelPolygon + 1];
	auto& v2 = poly->pVertices[nSelPolygon + 2];

	auto& n0 = poly->pNormals[0];
	auto& n1 = poly->pNormals[nSelPolygon + 1];
	auto& n2 = poly->pNormals[nSelPolygon + 2];

	v3 pos;
	if (nSelEdge != -1)
	{
		auto& e0 = nSelEdge == 0 ? v0 : nSelEdge == 1 ? v1 : v2;
		auto& e1 = nSelEdge == 0 ? v1 : nSelEdge == 1 ? v2 : v0;

		auto dir = Normalized(e1 - e0);

		pos = e0 + DotProduct(dir, position - e0) * dir;
	}
	else
		pos = position;

	auto a = v1 - v0;
	auto b = v2 - v1;
	auto x = pos - v0;

	float f = b[au] * x[av] - b[av] * x[au];
	if (IS_ZERO(f))
		return n0;

	float t = (a[av] * x[au] - a[au] * x[av]) / f;

	auto tem = InterpolatedVector(n1, n2, t);

	auto inter = a + t*b;

	int axisfors;
	if (fabs(inter.x) > fabs(inter.y) && fabs(inter.x) > fabs(inter.z))
		axisfors = 0;
	else if (fabs(inter.y) > fabs(inter.z))
		axisfors = 1;
	else
		axisfors = 2;

	float s = x[axisfors] / inter[axisfors];
	return InterpolatedVector(n0, tem, s);
}
예제 #13
0
//////////////////////////////////////////////////////////////////////////
// Given the position, normal, and set of rays compute the bent normal and
// occlusion term.
//////////////////////////////////////////////////////////////////////////
void
ComputeOcclusion (NmRawPointD* newPos, NmRawPointD* newNorm, int numTris,
                  NmRawTriangle* tri, AtiOctree* octree, int numRays,
                  NmRawPointD* rays, double* rayWeights,
                  NmRawPointD* bentNormal, double* occlusion,
                  int& gMaxCells, AtiOctreeCell** &gCell)
{
#ifdef _DEBUG
 if ((newPos == NULL) || (newNorm == NULL) || (tri == NULL) ||
  (octree == NULL) || (rays == NULL) || (rayWeights == NULL) ||
  (bentNormal == NULL) || (occlusion == NULL))
 {
  //NmPrint ("ERROR: Incorrect arguments passed!\n");
  exit (-1);
 }
#endif
 // Clear results. 
 // Bent normal should at minimum be the regular normal (I think).
 bentNormal->x = newNorm->x;
 bentNormal->y = newNorm->y;
 bentNormal->z = newNorm->z;
 (*occlusion) = 0.0;
 double hit = 0.0f;
 double num = 0.0f;

 // Compute offset vertex
 NmRawPointD pos;
 pos.x = newPos->x + (newNorm->x * gDistanceOffset);
 pos.y = newPos->y + (newNorm->y * gDistanceOffset);
 pos.z = newPos->z + (newNorm->z * gDistanceOffset);

 // Compute rotation matrix to match hemisphere to normal
 double rotMat[16];
 FromToRotation (rotMat, gZVec, newNorm->v);

 // Shoot the rays
 for (int r = 0; r < numRays; r++)
 {
  // First rotate the ray into position
  NmRawPointD oRay;
  oRay.x = rays[r].x*rotMat[0] + rays[r].y*rotMat[4] + rays[r].z*rotMat[8];
  oRay.y = rays[r].x*rotMat[1] + rays[r].y*rotMat[5] + rays[r].z*rotMat[9];
  oRay.z = rays[r].x*rotMat[2] + rays[r].y*rotMat[6] + rays[r].z*rotMat[10];

  // Walk the Octree to find triangle intersections.
  bool intersect = false;
  int numCells = 0;
  int cellCount = 0;
  int triCount = 0;
  AddCell (octree->m_root, &numCells, gMaxCells, gCell);
  while ((numCells > 0) && !intersect)
  {
   // Take the cell from the list.
   cellCount++;
   numCells--;
   AtiOctreeCell* currCell = gCell[numCells];

   // See if this is a leaf node
   bool leaf = true;
   for (int c = 0; c < 8; c++)
   {
    if (currCell->m_children[c] != NULL)
    {
     leaf = false;
     break;
    }
   }

   // If we are a leaf check the triangles
   if (leaf)
   {
    // Run through the triangles seeing if the ray intersects.
    for (int t = 0; t < currCell->m_numItems; t++)
    {
     // Save off current triangle.
     NmRawTriangle* currTri = &(tri[currCell->m_item[t]]);
     triCount++;

     // See if it intersects.
     double oT, oU, oV;
     if (IntersectTriangle (pos.v, oRay.v, currTri->vert[0].v,
      currTri->vert[1].v, currTri->vert[2].v,
      &oT, &oU, &oV))
     {
      if (oT > 0.0f)
      {
       intersect = true;
       break;
      }
     }
    } // end for t (num triangles in this cell)
   } // end if leaf
   else
   {  // Non-leaf, add the children to the list if their bounding
    // box intersects the ray.
    for (int c = 0; c < 8; c++)
    {
     if (currCell->m_children[c] != NULL)
     {
      // Save off current child.
      AtiOctreeCell* child = currCell->m_children[c];

      // If the ray intersects the box
      if (RayIntersectsBox (&pos, &oRay, &child->m_boundingBox))
      {
       AddCell (child, &numCells, gMaxCells, gCell);
      } // end if the ray intersects this bounding box.
      // else do nothing, we'll never intersect any triangles
      // for it's children.
     } // end if we have a cell
    } // end for c (8 children)
   } // end else non-leaf node.
  } // end while cells

  // Update our running results based on if we found and intersection.
  num += rayWeights[r];
  if (!intersect)
  {
   bentNormal->x += (oRay.x * rayWeights[r]);
   bentNormal->y += (oRay.y * rayWeights[r]);
   bentNormal->z += (oRay.z * rayWeights[r]);
  }
  else
  {
   hit += rayWeights[r];
  }
  /*      
  // Save off some stats.
  if (triCount > gAOMaxTrisTested)
  {
  gAOMaxTrisTested = triCount;
  }
  if (cellCount > gAOMaxCellsTested)
  {
  gAOMaxCellsTested = cellCount;
  }
  */
 } // end for r (number of rays)

 // Normalize result
 Normalize (bentNormal->v);
 (*occlusion) = (num - hit) / num;
} // end of ComputeOcclusion
예제 #14
0
//////////////////////////////////////////////////////////////////////////
// Figure out if we have an intersection from the given point, if we do
// make sure it's the "best" one. Returns true if it found an intersection
// false otherwise. It places the normal into newNormal and position into
// newPos.
//////////////////////////////////////////////////////////////////////////
inline bool
FindBestIntersection (NmRawPointD& pos, NmRawPointD& norm, AtiOctree* octree,
                      NmRawTriangle* highTris, NmTangentMatrix* hTangentSpace,
                      float* bumpMap, int bumpHeight, int bumpWidth,
                      double newNorm[3], double newPos[3],
                      double* displacement,
                      int gNormalRules,
                      double gMaxAngle,
                      double gDistance,
                      double gEpsilon,
                      int& gMaxCells, AtiOctreeCell** &gCell)
{
 // Clear outputs.
 newNorm[0] = 0.0;
 newNorm[1] = 0.0;
 newNorm[2] = 0.0;
 newPos[0] = 0.0;
 newPos[1] = 0.0;
 newPos[2] = 0.0;

 // Create negative normal
 NmRawPointD negNorm;
 negNorm.x = -norm.x;
 negNorm.y = -norm.y;
 negNorm.z = -norm.z;

 // Some stats.
 int cellCount = 0;
 int hitTriCount = 0;
 int triCount = 0;

 // Walk the octree looking for intersections.
 NmRawPointD intersect;
 NmRawPointD lastIntersect;
 int numCells = 0;
 AddCell (octree->m_root, &numCells, gMaxCells, gCell);
 while (numCells > 0)
 {
  // Take the cell from the list.
  cellCount++;
  numCells--;
  AtiOctreeCell* currCell = gCell[numCells];

  // See if this is a leaf node
  bool leaf = true;
  for (int c = 0; c < 8; c++)
  {
   if (currCell->m_children[c] != NULL)
   {
    leaf = false;
    break;
   }
  }

  // If we are a leaf check the triangles
  if (leaf)
  {
   // Run through the triangles seeing if the ray intersects.
   for (int t = 0; t < currCell->m_numItems; t++)
   {
    // Save off current triangle.
    NmRawTriangle* hTri = &highTris[currCell->m_item[t]];

    // See if it intersects.
    triCount++;
    if (IntersectTriangle (pos.v, norm.v, hTri->vert[0].v,
     hTri->vert[1].v, hTri->vert[2].v,
     &intersect.x, &intersect.y,
     &intersect.z))
    {
     // Keep some statistics.
     hitTriCount++;

     // Figure out new normal and position
     double b0 = 1.0 - intersect.y - intersect.z;
     double np[3]; 
     double nn[3];
     BaryInterpolate (hTri, b0, intersect.y, intersect.z, np, nn);

     // Debug this intersection test if requested.

     // See if this should be the normal for the map.
     if (IntersectionIsBetter (gNormalRules, &norm,
      nn, &intersect,
      newNorm, &lastIntersect,
      gMaxAngle,
      gDistance,
      gEpsilon))
     {
      // Perturb by bump map
      if (bumpMap != NULL)
      {
       GetPerturbedNormal (hTri, b0, intersect.y,
        intersect.z, bumpMap,
        bumpWidth, bumpHeight,
        hTangentSpace[currCell->m_item[t]].m,
        nn);
      }

      // Copy over values
      memcpy (newNorm, nn, sizeof (double)*3);
      memcpy (newPos, np, sizeof (double)*3);
      memcpy (&lastIntersect, &intersect,
       sizeof (NmRawPointD));
     } // end if this intersection is better
#ifdef DEBUG_INTERSECTION
     else if (gDbgIntersection)
     {
      NmPrint ("      <<< Intersection is worse!\n");
     }
#endif
    } // end if we have an intersection
   } // end for t (num triangles in this cell)
  } // end if leaf
  else
  {  // Non-leaf, add the children to the list if their bounding
   // box intersects the ray.
   for (int c = 0; c < 8; c++)
   {
    if (currCell->m_children[c] != NULL)
    {
     // Save off current child.
     AtiOctreeCell* child = currCell->m_children[c];

     // If the ray intersects the box
     if (RayIntersectsBox (&pos, &norm, &child->m_boundingBox))
     {
      AddCell (child, &numCells, gMaxCells, gCell);
     } // end if the ray intersects this bounding box.
     else if (RayIntersectsBox (&pos, &negNorm, &child->m_boundingBox))
     {
      AddCell (child, &numCells, gMaxCells, gCell);
     } // end if the ray intersects this bounding box.
     // else do nothing, we'll never intersect any triangles
     // for it's children.
    } // end if we have a cell
   } // end for c (8 children)
  } // end else non-leaf node.
 } // end while cells

 /*
 // Save off some stats.
 if (triCount > gMaxTrisTested)
 {
 gMaxTrisTested = triCount;
 }
 if (hitTriCount > gMaxTrisHit)
 {
 gMaxTrisHit = hitTriCount;
 }
 if (cellCount > gMaxCellsTested)
 {
 gMaxCellsTested = cellCount;
 }
 */
 // Test if we found an intersection.
 if ( (newNorm[0] != 0.0) || (newNorm[1] != 0.0) || (newNorm[2] != 0.0) )
 {
  (*displacement) = lastIntersect.x;
  return true;
 }
 return false;
} // end of FindBestIntersection
예제 #15
0
bool CObject3D::Pick(const D3DXMATRIX& world, const D3DXVECTOR3& origin, const D3DXVECTOR3& dir, float& dist)
{
#ifdef WORLD_EDITOR
	float tempDist;
	bool pick = false;
	dist = 65535.0f;
	D3DXMATRIX invTM, TM;
	D3DXVECTOR3 invOrigin, invDir;
	GMObject* obj;
	ushort* IB, *IIB;
	int faceCount, i, j, boneID;
	D3DXMATRIX* bones, *invBones;

	for (i = 0; i < m_groups[0].objectCount; i++)
	{
		obj = &m_groups[0].objects[i];
		if (obj->type == GMT_SKIN)
		{
			D3DXMatrixInverse(&invTM, null, &world);
			D3DXVec3TransformCoord(&invOrigin, &origin, &invTM);
			invTM._41 = 0;	invTM._42 = 0;	invTM._43 = 0;
			D3DXVec3TransformCoord(&invDir, &dir, &invTM);

			const SkinVertex* VB = (SkinVertex*)obj->vertices;
			IB = obj->indices;
			faceCount = obj->faceListCount;
			IIB = obj->IIB;

			if (m_externBones)
			{
				bones = m_externBones;
				invBones = m_externInvBones;
			}
			else
			{
				bones = m_baseBones;
				invBones = m_baseInvBones;
			}

			const int vertexCount = obj->vertexCount;
			if (vertexCount > 4096)
				continue;

			const int* physique = obj->physiqueVertices;
			static D3DXVECTOR3 temp[4096];

			for (j = 0; j < vertexCount; j++)
			{
				boneID = physique[*IIB++];
				TM = invBones[boneID] * bones[boneID];
				D3DXVec3TransformCoord(&temp[j], &VB[j].p, &TM);
			}

			for (j = 0; j < faceCount; j++)
			{
				const D3DXVECTOR3& v1 = temp[*IB++];
				const D3DXVECTOR3& v2 = temp[*IB++];
				const D3DXVECTOR3& v3 = temp[*IB++];

				if (IntersectTriangle(v1, v2, v3, invOrigin, invDir, tempDist) && tempDist < dist)
				{
					pick = true;
					dist = tempDist;
				}
			}
		}
		else
		{
			if (m_groups[0].updates)
			{
				TM = m_groups[0].updates[i] * world;
				D3DXMatrixInverse(&invTM, null, &TM);
				D3DXVec3TransformCoord(&invOrigin, &origin, &invTM);
				invTM._41 = 0;	invTM._42 = 0;	invTM._43 = 0;
				D3DXVec3TransformCoord(&invDir, &dir, &invTM);

				const NormalVertex* VB = (NormalVertex*)obj->vertices;
				IB = obj->indices;
				faceCount = obj->faceListCount;

				for (j = 0; j < faceCount; j++)
				{
					const D3DXVECTOR3& v1 = VB[*IB++].p;
					const D3DXVECTOR3& v2 = VB[*IB++].p;
					const D3DXVECTOR3& v3 = VB[*IB++].p;

					if (IntersectTriangle(v1, v2, v3, invOrigin, invDir, tempDist) && tempDist < dist)
					{
						pick = true;
						dist = tempDist;
					}
				}
			}
		}
	}

	return pick;
#else // WORLD_EDITOR
	return false;
#endif // WORLD_EDITOR
}
예제 #16
0
bool RayTesselatedTrianglePrimitive::Intersect(const Ray& ray) {
    Vec3f v0, v1, v2;
    _ResolveVertexAttrib(v0,v1,v2,triangles->pos);
    float t, b1, b2, rayEpsilon;
    return IntersectTriangle(v0,v1,v2,ray, &t, &b1, &b2, &rayEpsilon);
}