Exemple #1
0
void GjkCollisionState::reset(const MatrixF& a2w, const MatrixF& b2w)
{
   VectorF zero(0,0,0),sa,sb;
   a2w.mulP(a->support(zero),&sa);
   b2w.mulP(b->support(zero),&sb);
   v = sa - sb;
   dist = v.len();
}
Exemple #2
0
void BoxConvex::emitEdge(S32 v1,S32 v2,const MatrixF& mat,ConvexFeature* cf)
{
   S32 vc = cf->mVertexList.size();
   cf->mVertexList.increment(2);
   Point3F *vp = cf->mVertexList.begin();
   mat.mulP(getVertex(v1),&vp[vc]);
   mat.mulP(getVertex(v2),&vp[vc + 1]);

   cf->mEdgeList.increment();
   ConvexFeature::Edge& edge = cf->mEdgeList.last();
   edge.vertex[0] = vc;
   edge.vertex[1] = vc + 1;
}
void GFXDrawUtil::_drawSolidCapsule( const GFXStateBlockDesc &desc, const Point3F &center, F32 radius, F32 height, const ColorI &color, const MatrixF *xfm )
{	
   MatrixF mat;
   if ( xfm )
      mat = *xfm;      
   else
      mat = MatrixF::Identity;

   S32 numPoints = sizeof(circlePoints)/sizeof(Point2F);
   GFXVertexBufferHandle<GFXVertexPC> verts(mDevice, numPoints * 2 + 2, GFXBufferTypeVolatile);
   verts.lock();

   for (S32 i=0; i<numPoints + 1; i++)
   {
      S32 imod = i % numPoints;      
      verts[2 * i].point = Point3F( circlePoints[imod].x * radius, circlePoints[imod].y * radius, height );
      verts[2 * i].color = color;
      verts[2 * i + 1].point = Point3F( circlePoints[imod].x * radius, circlePoints[imod].y * radius, -height );
      verts[2 * i + 1].color = color;
   }

   S32 totalNumPnts = numPoints * 2 + 2;

   // Apply xfm if we were passed one.
   for ( U32 i = 0; i < totalNumPnts; i++ )
      mat.mulP( verts[i].point );

   // Apply position offset
   for ( U32 i = 0; i < totalNumPnts; i++ )
      verts[i].point += center;

   verts.unlock();

   mDevice->setStateBlockByDesc( desc );

   mDevice->setVertexBuffer( verts );
   mDevice->setupGenericShaders();

   mDevice->drawPrimitive( GFXTriangleStrip, 0, 2 * numPoints );

   Point3F sphereCenter;
   MatrixF sphereMat;

   if ( xfm )
      sphereMat = *xfm;
   else
      sphereMat = MatrixF::Identity;   

   sphereCenter.set( 0, 0, 0.5f * height );
   mat.mulV( sphereCenter );
   sphereCenter += center;

   drawSphere( desc, radius, sphereCenter, color, true, false, &sphereMat );

   sphereCenter.set( 0, 0, -0.5f * height );
   mat.mulV( sphereCenter );
   sphereCenter += center;

   drawSphere( desc, radius, sphereCenter, color, false, true, &sphereMat );
}
Exemple #4
0
void BoxConvex::emitFace(S32 fi,const MatrixF& mat,ConvexFeature* cf)
{
   Face& face = sFace[fi];

   // Emit vertices
   S32 vc = cf->mVertexList.size();
   cf->mVertexList.increment(4);
   Point3F *vp = cf->mVertexList.begin();
   for (S32 v = 0; v < 4; v++)
      mat.mulP(getVertex(face.vertex[v]),&vp[vc + v]);

   // Emit edges
   cf->mEdgeList.increment(4);
   ConvexFeature::Edge* edge = cf->mEdgeList.end() - 4;
   for (S32 e = 0; e < 4; e++) {
      edge[e].vertex[0] = vc + e;
      edge[e].vertex[1] = vc + ((e + 1) & 3);
   }

   // Emit 2 triangle faces
   cf->mFaceList.increment(2);
   ConvexFeature::Face* ef = cf->mFaceList.end() - 2;
   mat.getColumn(face.axis,&ef->normal);
   if (face.flip)
      ef[0].normal.neg();
   ef[1].normal = ef[0].normal;
   ef[1].vertex[0] = ef[0].vertex[0] = vc;
   ef[1].vertex[1] = ef[0].vertex[2] = vc + 2;
   ef[0].vertex[1] = vc + 1;
   ef[1].vertex[2] = vc + 3;
}
Exemple #5
0
void BtBody::applyImpulse( const Point3F &origin, const Point3F &force )
{
   AssertFatal( mActor, "BtBody::applyImpulse - The actor is null!" );
   AssertFatal( isDynamic(), "BtBody::applyImpulse - This call is only for dynamics!" );

   // Convert the world position to local
   MatrixF trans = btCast<MatrixF>( mActor->getCenterOfMassTransform() );
   trans.inverse();
   Point3F localOrigin( origin );
   trans.mulP( localOrigin );

   if ( mCenterOfMass )
   {
      Point3F relOrigin( localOrigin );
      mCenterOfMass->mulP( relOrigin );
      Point3F relForce( force );
      mCenterOfMass->mulV( relForce );
      mActor->applyImpulse( btCast<btVector3>( relForce ), btCast<btVector3>( relOrigin ) );
   }
   else
      mActor->applyImpulse( btCast<btVector3>( force ), btCast<btVector3>( localOrigin ) );

   if ( !mActor->isActive() )
      mActor->activate();
}
Exemple #6
0
//----------------------------------------------------------------------------
// Create ring
//----------------------------------------------------------------------------
SplashRing Splash::createRing()
{
   SplashRing ring;
   U32 numPoints = mDataBlock->numSegments + 1;

   Point3F ejectionAxis( 0.0, 0.0, 1.0 );

   Point3F axisx;
   if (mFabs(ejectionAxis.z) < 0.999f)
      mCross(ejectionAxis, Point3F(0, 0, 1), &axisx);
   else
      mCross(ejectionAxis, Point3F(0, 1, 0), &axisx);
   axisx.normalize();

   for( U32 i=0; i<numPoints; i++ )
   {
      F32 t = F32(i) / F32(numPoints);

      AngAxisF thetaRot( axisx, mDataBlock->ejectionAngle * (M_PI / 180.0));
      AngAxisF phiRot(   ejectionAxis, t * (M_PI * 2.0));

      Point3F pointAxis = ejectionAxis;

      MatrixF temp;
      thetaRot.setMatrix(&temp);
      temp.mulP(pointAxis);
      phiRot.setMatrix(&temp);
      temp.mulP(pointAxis);

      Point3F startOffset = axisx;
      temp.mulV( startOffset );
      startOffset *= mDataBlock->startRadius;

      SplashRingPoint point;
      point.position = getPosition() + startOffset;
      point.velocity = pointAxis * mDataBlock->velocity;

      ring.points.push_back( point );
   }

   ring.color = mDataBlock->colors[0];
   ring.lifetime = mDataBlock->ringLifetime;
   ring.elapsedTime = 0.0;
   ring.v = mDataBlock->texFactor * mFmod( mElapsedTime, 1.0 );

   return ring;
}
Exemple #7
0
bool GjkCollisionState::intersect(const MatrixF& a2w, const MatrixF& b2w)
{
   num_iterations = 0;
   MatrixF w2a,w2b;

   w2a = a2w;
   w2b = b2w;
   w2a.inverse();
   w2b.inverse();
   reset(a2w,b2w);

   bits = 0;
   all_bits = 0;

   do {
      nextBit();

      VectorF va,sa;
      w2a.mulV(-v,&va);
      p[last] = a->support(va);
      a2w.mulP(p[last],&sa);

      VectorF vb,sb;
      w2b.mulV(v,&vb);
      q[last] = b->support(vb);
      b2w.mulP(q[last],&sb);

      VectorF w = sa - sb;
      if (mDot(v,w) > 0)
         return false;
      if (degenerate(w)) {
         ++num_irregularities;
         return false;
      }

      y[last] = w;
      all_bits = bits | last_bit;

      ++num_iterations;
      if (!closest(v) || num_iterations > sIteration) {
         ++num_irregularities;
         return false;
      }
   }
   while (bits < 15 && v.lenSquared() > sEpsilon2);
   return true;
}
Exemple #8
0
void TerrainConvex::getFeatures(const MatrixF& mat,const VectorF& n, ConvexFeature* cf)
{
   U32 i;
   cf->material = 0;
   cf->object = mObject;

   // Plane is normal n + support point
   PlaneF plane;
   plane.set(support(n),n);
   S32 vertexCount = cf->mVertexList.size();

   // Emit vertices on the plane
   S32* vertexListPointer;
   if (halfA)
      vertexListPointer = square ? sVertexList[(split45 << 1) | 1]: sVertexList[4];
   else
      vertexListPointer = square ? sVertexList[(split45 << 1)]    : sVertexList[4];

   S32 pm = 0;
   S32 numVerts = *vertexListPointer;
   vertexListPointer += 1;
   for (i = 0; i < numVerts; i++)
   {
      Point3F& cp = point[vertexListPointer[i]];
      cf->mVertexList.increment();
      mat.mulP(cp,&cf->mVertexList.last());
      pm |= 1 << vertexListPointer[i];
   }

   // Emit Edges
   S32* ep = (square && halfA)?
      (split45 ? sEdgeList45A[pm]: sEdgeList135A[pm]):
      (split45 ? sEdgeList45[pm]: sEdgeList135[pm]);

   S32 numEdges = *ep;
   S32 edgeListStart = cf->mEdgeList.size();
   cf->mEdgeList.increment(numEdges);
   ep += 1;
   for (i = 0; i < numEdges; i++)
   {
      cf->mEdgeList[edgeListStart + i].vertex[0] = vertexCount + ep[i * 2 + 0];
      cf->mEdgeList[edgeListStart + i].vertex[1] = vertexCount + ep[i * 2 + 1];
   }

   // Emit faces
   S32* fp = split45 ? sFaceList45[pm]: sFaceList135[pm];
   S32 numFaces = *fp;
   fp += 1;
   S32 faceListStart = cf->mFaceList.size();
   cf->mFaceList.increment(numFaces);
   for (i = 0; i < numFaces; i++)
   {
      cf->mFaceList[faceListStart + i].normal    = normal[fp[i * 4 + 0]];
      cf->mFaceList[faceListStart + i].vertex[0] = vertexCount + fp[i * 4 + 1];
      cf->mFaceList[faceListStart + i].vertex[1] = vertexCount + fp[i * 4 + 2];
      cf->mFaceList[faceListStart + i].vertex[2] = vertexCount + fp[i * 4 + 3];
   }
}
Exemple #9
0
void GjkCollisionState::getCollisionInfo(const MatrixF& mat, Collision* info)
{
   AssertFatal(false, "GjkCollisionState::getCollisionInfo() - There remain scaling problems here.");
   // This assumes that the shapes do not intersect
   Point3F pa,pb;
   if (bits) {
      getClosestPoints(pa,pb);
      mat.mulP(pa,&info->point);
      b->getTransform().mulP(pb,&pa);
      info->normal = info->point - pa;
   }
   else {
      mat.mulP(p[last],&info->point);
      info->normal = v;
   }
   info->normal.normalize();
   info->object = b->getObject();
}
void ForestConvex::getFeatures( const MatrixF &mat, const VectorF &n, ConvexFeature *cf )
{
   cf->material = 0;
   cf->object = mObject;

   TSShapeInstance *si = mData->getShapeInstance();

   TSShape::ConvexHullAccelerator* pAccel =
      si->getShape()->getAccelerator(mData->getCollisionDetails()[hullId]);
   AssertFatal(pAccel != NULL, "Error, no accel!");

   F32 currMaxDP = mDot(pAccel->vertexList[0], n);
   U32 index = 0;
   U32 i;
   for (i = 1; i < pAccel->numVerts; i++) 
   {
      F32 dp = mDot(pAccel->vertexList[i], n);
      if (dp > currMaxDP) 
      {
         currMaxDP = dp;
         index = i;
      }
   }

   const U8* emitString = pAccel->emitStrings[index];
   U32 currPos = 0;
   U32 numVerts = emitString[currPos++];
   for (i = 0; i < numVerts; i++) 
   {
      cf->mVertexList.increment();
      U32 index = emitString[currPos++];
      mat.mulP(pAccel->vertexList[index], &cf->mVertexList.last());
   }

   U32 numEdges = emitString[currPos++];
   for (i = 0; i < numEdges; i++) 
   {
      U32 ev0 = emitString[currPos++];
      U32 ev1 = emitString[currPos++];
      cf->mEdgeList.increment();
      cf->mEdgeList.last().vertex[0] = ev0;
      cf->mEdgeList.last().vertex[1] = ev1;
   }

   U32 numFaces = emitString[currPos++];
   for (i = 0; i < numFaces; i++) 
   {
      cf->mFaceList.increment();
      U32 plane = emitString[currPos++];
      mat.mulV(pAccel->normalList[plane], &cf->mFaceList.last().normal);
      for (U32 j = 0; j < 3; j++)
         cf->mFaceList.last().vertex[j] = emitString[currPos++];
   }
}
//----------------------------------------------------------------------------
AwTextureTarget *AwShape::processAwesomiumHit (const Point3F &start, const Point3F &end)
{
	if (!mTextureTarget)
	{
		return NULL;
	}

	Point3F localStart, localEnd;
	MatrixF mat = getTransform();
	mat.scale (Point3F (getScale ()));
	mat.inverse ();

	mat.mulP (start, &localStart);
	mat.mulP (end, &localEnd);

	RayInfo info;
	info.generateTexCoord = true;
	if (!mShapeInstance || !mShapeInstance->castRayOpcode (0, localStart, localEnd, &info))
	{
		return NULL;
	}

	if (info.texCoord.x != -1 && info.texCoord.y != -1 && info.material == mMatInstance)
	{
		Point2I pnt (info.texCoord.x * mTextureTarget->getResolution ().x, info.texCoord.y * mTextureTarget->getResolution ().y);
		
		AwManager::sCursor->setPosition (pnt);

		if (mIsMouseDown)
		{
			mTextureTarget->injectMouseDown ();
		}
		else
		{
			mTextureTarget->injectMouseUp ();
		}

		return mTextureTarget;
	}
	return NULL;
}
Exemple #12
0
MatrixF PlaneReflector::getFrustumClipProj( MatrixF &modelview )
{
   static MatrixF rotMat(EulerF( static_cast<F32>(M_PI / 2.f), 0.0, 0.0));
   static MatrixF invRotMat(EulerF( -static_cast<F32>(M_PI / 2.f), 0.0, 0.0));


   MatrixF revModelview = modelview;
   revModelview = rotMat * revModelview;  // add rotation to modelview because it needs to be removed from projection

   // rotate clip plane into modelview space
   Point4F clipPlane;
   Point3F pnt = refplane * -(refplane.d + 0.0 );
   Point3F norm = refplane;

   revModelview.mulP( pnt );
   revModelview.mulV( norm );
   norm.normalize();

   clipPlane.set( norm.x, norm.y, norm.z, -mDot( pnt, norm ) );


   // Manipulate projection matrix
   //------------------------------------------------------------------------
   MatrixF proj = GFX->getProjectionMatrix();
   proj.mul( invRotMat );  // reverse rotation imposed by Torque
   proj.transpose();       // switch to row-major order

   // Calculate the clip-space corner point opposite the clipping plane
   // as (sgn(clipPlane.x), sgn(clipPlane.y), 1, 1) and
   // transform it into camera space by multiplying it
   // by the inverse of the projection matrix
   Vector4F	q;
   q.x = sgn(clipPlane.x) / proj(0,0);
   q.y = sgn(clipPlane.y) / proj(1,1);
   q.z = -1.0F;
   q.w = ( 1.0F - proj(2,2) ) / proj(3,2);

   F32 a = 1.0 / (clipPlane.x * q.x + clipPlane.y * q.y + clipPlane.z * q.z + clipPlane.w * q.w);

   Vector4F c = clipPlane * a;

   // CodeReview [ags 1/23/08] Come up with a better way to deal with this.
   if(GFX->getAdapterType() == OpenGL)
      c.z += 1.0f;

   // Replace the third column of the projection matrix
   proj.setColumn( 2, c );
   proj.transpose(); // convert back to column major order
   proj.mul( rotMat );  // restore Torque rotation

   return proj;
}
void AppMesh::computeBounds(Box3F& bounds)
{
   bounds = Box3F::Invalid;

   if ( isSkin() )
   {
      // Need to skin the mesh before we can compute the bounds

      // Setup bone transforms
      Vector<MatrixF> boneTransforms;
      boneTransforms.setSize( nodeIndex.size() );
      for (S32 iBone = 0; iBone < boneTransforms.size(); iBone++)
      {
         MatrixF nodeMat = bones[iBone]->getNodeTransform( TSShapeLoader::DefaultTime );
         TSShapeLoader::zapScale(nodeMat);
         boneTransforms[iBone].mul( nodeMat, initialTransforms[iBone] );
      }

      // Multiply verts by weighted bone transforms
      for (S32 iVert = 0; iVert < initialVerts.size(); iVert++)
         points[iVert].set( Point3F::Zero );

      for (S32 iWeight = 0; iWeight < vertexIndex.size(); iWeight++)
      {
         const S32& vertIndex = vertexIndex[iWeight];
         const MatrixF& deltaTransform = boneTransforms[ boneIndex[iWeight] ];

         Point3F v;
         deltaTransform.mulP( initialVerts[vertIndex], &v );
         v *= weight[iWeight];

         points[vertIndex] += v;
      }

      // compute bounds for the skinned mesh
      for (S32 iVert = 0; iVert < initialVerts.size(); iVert++)
         bounds.extend( points[iVert] );
   }
   else
   {
      MatrixF transform = getMeshTransform(TSShapeLoader::DefaultTime);
      TSShapeLoader::zapScale(transform);

      for (S32 iVert = 0; iVert < points.size(); iVert++)
      {
         Point3F p;
         transform.mulP(points[iVert], &p);
         bounds.extend(p);
      }
   }
}
Exemple #14
0
void OrientedBox3F::set( const MatrixF& transform, const Box3F& aabb )
{
   mCenter = aabb.getCenter();
   transform.mulP( mCenter );

   mAxes[ RightVector ] = transform.getRightVector();
   mAxes[ ForwardVector ] = transform.getForwardVector();
   mAxes[ UpVector ] = transform.getUpVector();

   mHalfExtents[ 0 ] = aabb.len_x() / 2.f;
   mHalfExtents[ 1 ] = aabb.len_y() / 2.f;
   mHalfExtents[ 2 ] = aabb.len_z() / 2.f;

   _initPoints();
}
Exemple #15
0
void BoxConvex::getFeatures(const MatrixF& mat,const VectorF& n, ConvexFeature* cf)
{
   cf->material = 0;
   cf->object = mObject;

   S32 v = 0;
   v += (n.x >= 0)? 1: 0;
   v += (n.y >= 0)? 2: 0;
   v += (n.z >= 0)? 4: 0;

   PlaneF plane;
   plane.set(getVertex(v),n);

   // Emit vertex and edge
   S32 mask = 0;
   Corner& corner = sCorner[v];
   mask |= isOnPlane(getVertex(corner.a),plane)? 1: 0;
   mask |= isOnPlane(getVertex(corner.b),plane)? 2: 0;
   mask |= isOnPlane(getVertex(corner.c),plane)? 4: 0;

   switch(mask) {
      case 0: {
         cf->mVertexList.increment();
         mat.mulP(getVertex(v),&cf->mVertexList.last());
         break;
      }
      case 1:
         emitEdge(v,corner.a,mat,cf);
         break;
      case 2:
         emitEdge(v,corner.b,mat,cf);
         break;
      case 4:
         emitEdge(v,corner.c,mat,cf);
         break;
      case 1 | 2:
         emitFace(corner.ab,mat,cf);
         break;
      case 2 | 4:
         emitFace(corner.bc,mat,cf);
         break;
      case 1 | 4:
         emitFace(corner.ac,mat,cf);
         break;
   }
}
Exemple #16
0
bool TSMesh::getFeatures( S32 frame, const MatrixF& mat, const VectorF&, ConvexFeature* cf, U32& )
{
   S32 firstVert = vertsPerFrame * frame;
   S32 i;
   S32 base = cf->mVertexList.size();

   for ( i = 0; i < vertsPerFrame; i++ ) 
   {
      cf->mVertexList.increment();
      mat.mulP( mVertexData[firstVert + i].vert(), &cf->mVertexList.last() );
   }

   // add the polys...
   for ( i = 0; i < primitives.size(); i++ )
   {
      TSDrawPrimitive & draw = primitives[i];
      U32 start = draw.start;

      AssertFatal( draw.matIndex & TSDrawPrimitive::Indexed,"TSMesh::buildPolyList (1)" );

      // gonna depend on what kind of primitive it is...
      if ( (draw.matIndex & TSDrawPrimitive::TypeMask) == TSDrawPrimitive::Triangles)
      {
         for ( S32 j = 0; j < draw.numElements; j += 3 )
         {
            PlaneF plane( cf->mVertexList[base + indices[start + j + 0]],
                          cf->mVertexList[base + indices[start + j + 1]],
                          cf->mVertexList[base + indices[start + j + 2]]);

            cf->mFaceList.increment();
            cf->mFaceList.last().normal = plane;

            cf->mFaceList.last().vertex[0] = base + indices[start + j + 0];
            cf->mFaceList.last().vertex[1] = base + indices[start + j + 1];
            cf->mFaceList.last().vertex[2] = base + indices[start + j + 2];

            for ( U32 l = 0; l < 3; l++ ) 
            {
               U32 newEdge0, newEdge1;
               U32 zero = base + indices[start + j + l];
               U32 one  = base + indices[start + j + ((l+1)%3)];
               newEdge0 = getMin( zero, one );
               newEdge1 = getMax( zero, one );
               bool found = false;
               for ( S32 k = 0; k < cf->mEdgeList.size(); k++
void ProcessedFFMaterial::_setSecondaryLightInfo(const MatrixF &_objTrans, LightInfo* light)
{
   // set object transform
   MatrixF objTrans = _objTrans;
   objTrans.inverse();

   // fill in secondary light
   //-------------------------
   GFXLightInfo xlatedLight;
   light->setGFXLight(&xlatedLight);

   Point3F lightPos = light->getPosition();
   Point3F lightDir = light->getDirection();
   objTrans.mulP(lightPos);
   objTrans.mulV(lightDir);

   xlatedLight.mPos = lightPos;
   xlatedLight.mDirection = lightDir;

   GFX->setLight(1, &xlatedLight);
}
void ProcessedFFMaterial::_setPrimaryLightInfo(const MatrixF &_objTrans, LightInfo* light, U32 pass)
{
   // Just in case
   GFX->setGlobalAmbientColor(ColorF(0.0f, 0.0f, 0.0f, 1.0f));
   if ( light->getType() == LightInfo::Ambient )
   {
      // Ambient light
      GFX->setGlobalAmbientColor( light->getAmbient() );
      return;
   }

   GFX->setLight(0, NULL);
   GFX->setLight(1, NULL);
   // This is a quick hack that lets us use FF lights
   GFXLightMaterial lightMat;
   lightMat.ambient = ColorF(1.0f, 1.0f, 1.0f, 1.0f);
   lightMat.diffuse = ColorF(1.0f, 1.0f, 1.0f, 1.0f);
   lightMat.emissive = ColorF(0.0f, 0.0f, 0.0f, 0.0f);
   lightMat.specular = ColorF(0.0f, 0.0f, 0.0f, 0.0f);
   lightMat.shininess = 128.0f;
   GFX->setLightMaterial(lightMat);   

   // set object transform
   MatrixF objTrans = _objTrans;
   objTrans.inverse();

   // fill in primary light
   //-------------------------
   GFXLightInfo xlatedLight;
   light->setGFXLight(&xlatedLight);
   Point3F lightPos = light->getPosition();
   Point3F lightDir = light->getDirection();
   objTrans.mulP(lightPos);
   objTrans.mulV(lightDir);

   xlatedLight.mPos = lightPos;
   xlatedLight.mDirection = lightDir;

   GFX->setLight(0, &xlatedLight);
}
Exemple #19
0
void AITurretShape::_renderScanner( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat )
{
   GFXStateBlockDesc desc;
   desc.setBlend(false, GFXBlendSrcAlpha, GFXBlendInvSrcAlpha);
   desc.setZReadWrite(false,true);
   desc.fillMode = GFXFillWireframe;

   // Render the scan box
   GFX->getDrawUtil()->drawCube(desc, mTransformedScanBox.getExtents(), mTransformedScanBox.getCenter(), ColorI(255, 0, 0));

   // Render a line from the scan node to the max scan distance
   MatrixF nodeMat;
   if (getNodeTransform(mDataBlock->scanNode, nodeMat))
   {
      Point3F start;
      nodeMat.getColumn(3, &start);

      Point3F end(0.0f, mScanDistance, 0.0f);
      nodeMat.mulP(end);

      GFX->getDrawUtil()->drawLine(start, end, ColorI(255, 255, 0));
   }
}
void AdvancedLightBinManager::LightMaterialInfo::setLightParameters( const LightInfo *lightInfo, const SceneRenderState* renderState, const MatrixF &worldViewOnly )
{
   MaterialParameters *matParams = matInstance->getMaterialParameters();

   // Set color in the right format, set alpha to the luminance value for the color.
   ColorF col = lightInfo->getColor();

   // TODO: The specularity control of the light
   // is being scaled by the overall lumiance.
   //
   // Not sure if this may be the source of our
   // bad specularity results maybe?
   //

   const Point3F colorToLumiance( 0.3576f, 0.7152f, 0.1192f );
   F32 lumiance = mDot(*((const Point3F *)&lightInfo->getColor()), colorToLumiance );
   col.alpha *= lumiance;

   matParams->setSafe( lightColor, col );
   matParams->setSafe( lightBrightness, lightInfo->getBrightness() );

   switch( lightInfo->getType() )
   {
   case LightInfo::Vector:
      {
         VectorF lightDir = lightInfo->getDirection();
         worldViewOnly.mulV(lightDir);
         lightDir.normalize();
         matParams->setSafe( lightDirection, lightDir );

         // Set small number for alpha since it represents existing specular in
         // the vector light. This prevents a divide by zero.
         ColorF ambientColor = renderState->getAmbientLightColor();
         ambientColor.alpha = 0.00001f;
         matParams->setSafe( lightAmbient, ambientColor );

         // If no alt color is specified, set it to the average of
         // the ambient and main color to avoid artifacts.
         //
         // TODO: Trilight disabled until we properly implement it
         // in the light info!
         //
         //ColorF lightAlt = lightInfo->getAltColor();
         ColorF lightAlt( ColorF::BLACK ); // = lightInfo->getAltColor();
         if ( lightAlt.red == 0.0f && lightAlt.green == 0.0f && lightAlt.blue == 0.0f )
            lightAlt = (lightInfo->getColor() + renderState->getAmbientLightColor()) / 2.0f;

         ColorF trilightColor = lightAlt;
         matParams->setSafe(lightTrilight, trilightColor);
      }
      break;

   case LightInfo::Spot:
      {
         const F32 outerCone = lightInfo->getOuterConeAngle();
         const F32 innerCone = getMin( lightInfo->getInnerConeAngle(), outerCone );
         const F32 outerCos = mCos( mDegToRad( outerCone / 2.0f ) );
         const F32 innerCos = mCos( mDegToRad( innerCone / 2.0f ) );
         Point4F spotParams(  outerCos, 
                              innerCos - outerCos, 
                              mCos( mDegToRad( outerCone ) ), 
                              0.0f );

         matParams->setSafe( lightSpotParams, spotParams );

         VectorF lightDir = lightInfo->getDirection();
         worldViewOnly.mulV(lightDir);
         lightDir.normalize();
         matParams->setSafe( lightDirection, lightDir );
      }
      // Fall through

   case LightInfo::Point:
   {
      const F32 radius = lightInfo->getRange().x;
      matParams->setSafe( lightRange, radius );

      Point3F lightPos;
      worldViewOnly.mulP(lightInfo->getPosition(), &lightPos);
      matParams->setSafe( lightPosition, lightPos );

      // Get the attenuation falloff ratio and normalize it.
      Point3F attenRatio = lightInfo->getExtended<ShadowMapParams>()->attenuationRatio;
      F32 total = attenRatio.x + attenRatio.y + attenRatio.z;
      if ( total > 0.0f )
         attenRatio /= total;

      Point2F attenParams( ( 1.0f / radius ) * attenRatio.y,
                           ( 1.0f / ( radius * radius ) ) * attenRatio.z );

      matParams->setSafe( lightAttenuation, attenParams );
      break;
   }

   default:
      AssertFatal( false, "Bad light type!" );
      break;
   }
}
void FontRenderBatcher::render( F32 rot, const Point2F &offset )
{
   if( mLength == 0 )
      return;

   GFX->setStateBlock(mFontSB);
   for(U32 i = 0; i < GFX->getNumSamplers(); i++)
      GFX->setTexture(i, NULL);

   MatrixF rotMatrix;

   bool doRotation = rot != 0.f;
   if(doRotation)
      rotMatrix.set( EulerF( 0.0, 0.0, mDegToRad( rot ) ) );

   // Write verts out.
   U32 currentPt = 0;
   GFXVertexBufferHandle<GFXVertexPCT> verts(GFX, mLength * 6, GFXBufferTypeVolatile);
   verts.lock();

   for( S32 i = 0; i < mSheets.size(); i++ )
   {
      // Do some early outs...
      if(!mSheets[i])
         continue;

      if(!mSheets[i]->numChars)
         continue;

      mSheets[i]->startVertex = currentPt;
      const GFXTextureObject *tex = mFont->getTextureHandle(i);

      for( S32 j = 0; j < mSheets[i]->numChars; j++ )
      {
         // Get some general info to proceed with...
         const CharMarker &m = mSheets[i]->charIndex[j];
         const PlatformFont::CharInfo &ci = mFont->getCharInfo( m.c );

         // Where are we drawing it?
         F32 drawY = offset.y + mFont->getBaseline() - ci.yOrigin * TEXT_MAG;
         F32 drawX = offset.x + m.x + ci.xOrigin;

         // Figure some values.
         const F32 texWidth = (F32)tex->getWidth();
         const F32 texHeight = (F32)tex->getHeight();
         const F32 texLeft   = (F32)(ci.xOffset)             / texWidth;
         const F32 texRight  = (F32)(ci.xOffset + ci.width)  / texWidth;
         const F32 texTop    = (F32)(ci.yOffset)             / texHeight;
         const F32 texBottom = (F32)(ci.yOffset + ci.height) / texHeight;

         const F32 fillConventionOffset = GFX->getFillConventionOffset();
         const F32 screenLeft   = drawX - fillConventionOffset;
         const F32 screenRight  = drawX - fillConventionOffset + ci.width * TEXT_MAG;
         const F32 screenTop    = drawY - fillConventionOffset;
         const F32 screenBottom = drawY - fillConventionOffset + ci.height * TEXT_MAG;

         // Build our vertices. We NEVER read back from the buffer, that's
         // incredibly slow, so for rotation do it into tmp. This code is
         // ugly as sin.
         Point3F tmp;

         tmp.set( screenLeft, screenTop, 0.f );
         if(doRotation)
            rotMatrix.mulP( tmp, &verts[currentPt].point);
         else
            verts[currentPt].point = tmp;
         verts[currentPt].color = m.color;
         verts[currentPt].texCoord.set( texLeft, texTop );
         currentPt++;

         tmp.set( screenLeft, screenBottom, 0.f );
         if(doRotation)
            rotMatrix.mulP( tmp, &verts[currentPt].point);
         else
            verts[currentPt].point = tmp;
         verts[currentPt].color = m.color;
         verts[currentPt].texCoord.set( texLeft, texBottom );
         currentPt++;

         tmp.set( screenRight, screenBottom, 0.f );
         if(doRotation)
            rotMatrix.mulP( tmp, &verts[currentPt].point);
         else
            verts[currentPt].point = tmp;
         verts[currentPt].color = m.color;
         verts[currentPt].texCoord.set( texRight, texBottom );
         currentPt++;

         tmp.set( screenRight, screenBottom, 0.f );
         if(doRotation)
            rotMatrix.mulP( tmp, &verts[currentPt].point);
         else
            verts[currentPt].point = tmp;
         verts[currentPt].color = m.color;
         verts[currentPt].texCoord.set( texRight, texBottom );
         currentPt++;

         tmp.set( screenRight, screenTop, 0.f );
         if(doRotation)
            rotMatrix.mulP( tmp, &verts[currentPt].point);
         else
            verts[currentPt].point = tmp;
         verts[currentPt].color = m.color;
         verts[currentPt].texCoord.set( texRight, texTop );
         currentPt++;

         tmp.set( screenLeft, screenTop, 0.f );
         if(doRotation)
            rotMatrix.mulP( tmp, &verts[currentPt].point);
         else
            verts[currentPt].point = tmp;
         verts[currentPt].color = m.color;
         verts[currentPt].texCoord.set( texLeft, texTop );
         currentPt++;
      }
   }

   verts->unlock();

   AssertFatal(currentPt <= mLength * 6, "FontRenderBatcher::render - too many verts for length of string!");

   GFX->setVertexBuffer(verts);
   GFX->setupGenericShaders( GFXDevice::GSAddColorTexture );

   // Now do an optimal render!
   for( S32 i = 0; i < mSheets.size(); i++ )
   {
      if(!mSheets[i])
         continue;

      if(!mSheets[i]->numChars )
         continue;
      
      GFX->setTexture( 0, mFont->getTextureHandle(i) );
      GFX->drawPrimitive(GFXTriangleList, mSheets[i]->startVertex, mSheets[i]->numChars * 2);
   }
}
Exemple #22
0
//--------------------------------------
static void m_matF_x_scale_x_planeF_C(const F32* m, const F32* s, const F32* p, F32* presult)
{
   // We take in a matrix, a scale factor, and a plane equation.  We want to output
   //  the resultant normal
   // We have T = m*s
   // To multiply the normal, we want Inv(Tr(m*s))
   //  Inv(Tr(ms)) = Inv(Tr(s) * Tr(m))
   //              = Inv(Tr(m)) * Inv(Tr(s))
   //
   //  Inv(Tr(s)) = Inv(s) = [ 1/x   0   0  0]
   //                        [   0 1/y   0  0]
   //                        [   0   0 1/z  0]
   //                        [   0   0   0  1]
   //
   // Since m is an affine matrix,
   //  Tr(m) = [ [       ] 0 ]
   //          [ [   R   ] 0 ]
   //          [ [       ] 0 ]
   //          [ [ x y z ] 1 ]
   //
   // Inv(Tr(m)) = [ [    -1 ] 0 ]
   //              [ [   R   ] 0 ]
   //              [ [       ] 0 ]
   //              [ [ A B C ] 1 ]
   // Where:
   //
   //  P = (x, y, z)
   //  A = -(Row(0, r) * P);
   //  B = -(Row(1, r) * P);
   //  C = -(Row(2, r) * P);

   MatrixF invScale(true);
   F32* pScaleElems = invScale;
   pScaleElems[MatrixF::idx(0, 0)] = 1.0f / s[0];
   pScaleElems[MatrixF::idx(1, 1)] = 1.0f / s[1];
   pScaleElems[MatrixF::idx(2, 2)] = 1.0f / s[2];

   const Point3F shear( m[MatrixF::idx(3, 0)], m[MatrixF::idx(3, 1)], m[MatrixF::idx(3, 2)] );

   const Point3F row0(m[MatrixF::idx(0, 0)], m[MatrixF::idx(0, 1)], m[MatrixF::idx(0, 2)]);
   const Point3F row1(m[MatrixF::idx(1, 0)], m[MatrixF::idx(1, 1)], m[MatrixF::idx(1, 2)]);
   const Point3F row2(m[MatrixF::idx(2, 0)], m[MatrixF::idx(2, 1)], m[MatrixF::idx(2, 2)]);

   const F32 A = -mDot(row0, shear);
   const F32 B = -mDot(row1, shear);
   const F32 C = -mDot(row2, shear);

   MatrixF invTrMatrix(true);
   F32* destMat = invTrMatrix;
   destMat[MatrixF::idx(0, 0)] = m[MatrixF::idx(0, 0)];
   destMat[MatrixF::idx(1, 0)] = m[MatrixF::idx(1, 0)];
   destMat[MatrixF::idx(2, 0)] = m[MatrixF::idx(2, 0)];
   destMat[MatrixF::idx(0, 1)] = m[MatrixF::idx(0, 1)];
   destMat[MatrixF::idx(1, 1)] = m[MatrixF::idx(1, 1)];
   destMat[MatrixF::idx(2, 1)] = m[MatrixF::idx(2, 1)];
   destMat[MatrixF::idx(0, 2)] = m[MatrixF::idx(0, 2)];
   destMat[MatrixF::idx(1, 2)] = m[MatrixF::idx(1, 2)];
   destMat[MatrixF::idx(2, 2)] = m[MatrixF::idx(2, 2)];
   destMat[MatrixF::idx(0, 3)] = A;
   destMat[MatrixF::idx(1, 3)] = B;
   destMat[MatrixF::idx(2, 3)] = C;
   invTrMatrix.mul(invScale);

   Point3F norm(p[0], p[1], p[2]);
   Point3F point = norm * -p[3];
   invTrMatrix.mulP(norm);
   norm.normalize();

   MatrixF temp;
   memcpy(temp, m, sizeof(F32) * 16);
   point.x *= s[0];
   point.y *= s[1];
   point.z *= s[2];
   temp.mulP(point);

   PlaneF resultPlane(point, norm);
   presult[0] = resultPlane.x;
   presult[1] = resultPlane.y;
   presult[2] = resultPlane.z;
   presult[3] = resultPlane.d;
}
Exemple #23
0
void TSStaticPolysoupConvex::getFeatures(const MatrixF& mat,const VectorF& n, ConvexFeature* cf)
{
   cf->material = 0;
   cf->object = mObject;

   // For a tetrahedron this is pretty easy... first
   // convert everything into world space.
   Point3F tverts[4];
   mat.mulP(verts[0], &tverts[0]);
   mat.mulP(verts[1], &tverts[1]);
   mat.mulP(verts[2], &tverts[2]);
   mat.mulP(verts[3], &tverts[3]);

   // points...
   S32 firstVert = cf->mVertexList.size();
   cf->mVertexList.increment(); cf->mVertexList.last() = tverts[0];
   cf->mVertexList.increment(); cf->mVertexList.last() = tverts[1];
   cf->mVertexList.increment(); cf->mVertexList.last() = tverts[2];
   cf->mVertexList.increment(); cf->mVertexList.last() = tverts[3];

   //    edges...
   cf->mEdgeList.increment();
   cf->mEdgeList.last().vertex[0] = firstVert+0;
   cf->mEdgeList.last().vertex[1] = firstVert+1;

   cf->mEdgeList.increment();
   cf->mEdgeList.last().vertex[0] = firstVert+1;
   cf->mEdgeList.last().vertex[1] = firstVert+2;

   cf->mEdgeList.increment();
   cf->mEdgeList.last().vertex[0] = firstVert+2;
   cf->mEdgeList.last().vertex[1] = firstVert+0;

   cf->mEdgeList.increment();
   cf->mEdgeList.last().vertex[0] = firstVert+3;
   cf->mEdgeList.last().vertex[1] = firstVert+0;

   cf->mEdgeList.increment();
   cf->mEdgeList.last().vertex[0] = firstVert+3;
   cf->mEdgeList.last().vertex[1] = firstVert+1;

   cf->mEdgeList.increment();
   cf->mEdgeList.last().vertex[0] = firstVert+3;
   cf->mEdgeList.last().vertex[1] = firstVert+2;

   //    triangles...
   cf->mFaceList.increment();
   cf->mFaceList.last().normal = PlaneF(tverts[2], tverts[1], tverts[0]);
   cf->mFaceList.last().vertex[0] = firstVert+2;
   cf->mFaceList.last().vertex[1] = firstVert+1;
   cf->mFaceList.last().vertex[2] = firstVert+0;

   cf->mFaceList.increment();
   cf->mFaceList.last().normal = PlaneF(tverts[1], tverts[0], tverts[3]);
   cf->mFaceList.last().vertex[0] = firstVert+1;
   cf->mFaceList.last().vertex[1] = firstVert+0;
   cf->mFaceList.last().vertex[2] = firstVert+3;

   cf->mFaceList.increment();
   cf->mFaceList.last().normal = PlaneF(tverts[2], tverts[1], tverts[3]);
   cf->mFaceList.last().vertex[0] = firstVert+2;
   cf->mFaceList.last().vertex[1] = firstVert+1;
   cf->mFaceList.last().vertex[2] = firstVert+3;

   cf->mFaceList.increment();
   cf->mFaceList.last().normal = PlaneF(tverts[0], tverts[2], tverts[3]);
   cf->mFaceList.last().vertex[0] = firstVert+0;
   cf->mFaceList.last().vertex[1] = firstVert+2;
   cf->mFaceList.last().vertex[2] = firstVert+3;

   // All done!
}
Exemple #24
0
void FlyingVehicle::updateForces(F32 /*dt*/)
{
   PROFILE_SCOPE( FlyingVehicle_UpdateForces );

   MatrixF currPosMat;
   mRigid.getTransform(&currPosMat);
   mRigid.atRest = false;

   Point3F massCenter;
   currPosMat.mulP(mDataBlock->massCenter,&massCenter);

   Point3F xv,yv,zv;
   currPosMat.getColumn(0,&xv);
   currPosMat.getColumn(1,&yv);
   currPosMat.getColumn(2,&zv);
   F32 speed = mRigid.linVelocity.len();

   Point3F force  = Point3F(0, 0, sFlyingVehicleGravity * mRigid.mass * mGravityMod);
   Point3F torque = Point3F(0, 0, 0);

   // Drag at any speed
   force  -= mRigid.linVelocity * mDataBlock->minDrag;
   torque -= mRigid.angMomentum * mDataBlock->rotationalDrag;

   // Auto-stop at low speeds
   if (speed < mDataBlock->maxAutoSpeed) {
      F32 autoScale = 1 - speed / mDataBlock->maxAutoSpeed;

      // Gyroscope
      F32 gf = mDataBlock->autoAngularForce * autoScale;
      torque -= xv * gf * mDot(yv,Point3F(0,0,1));

      // Manuevering jets
      F32 sf = mDataBlock->autoLinearForce * autoScale;
      force -= yv * sf * mDot(yv, mRigid.linVelocity);
      force -= xv * sf * mDot(xv, mRigid.linVelocity);
   }

   // Hovering Jet
   F32 vf = -sFlyingVehicleGravity * mRigid.mass * mGravityMod;
   F32 h  = getHeight();
   if (h <= 1) {
      if (h > 0) {
         vf -= vf * h * 0.1;
      } else {
         vf += mDataBlock->jetForce * -h;
      }
   }
   force += zv * vf;

   // Damping "surfaces"
   force -= xv * mDot(xv,mRigid.linVelocity) * mDataBlock->horizontalSurfaceForce;
   force -= zv * mDot(zv,mRigid.linVelocity) * mDataBlock->verticalSurfaceForce;

   // Turbo Jet
   if (mJetting) {
      if (mThrustDirection == ThrustForward)
         force += yv * mDataBlock->jetForce * mCeilingFactor;
      else if (mThrustDirection == ThrustBackward)
         force -= yv * mDataBlock->jetForce * mCeilingFactor;
      else
         force += zv * mDataBlock->jetForce * mDataBlock->vertThrustMultiple * mCeilingFactor;
   }

   // Maneuvering jets
   force += yv * (mThrust.y * mDataBlock->maneuveringForce * mCeilingFactor);
   force += xv * (mThrust.x * mDataBlock->maneuveringForce * mCeilingFactor);

   // Steering
   Point2F steering;
   steering.x = mSteering.x / mDataBlock->maxSteeringAngle;
   steering.x *= mFabs(steering.x);
   steering.y = mSteering.y / mDataBlock->maxSteeringAngle;
   steering.y *= mFabs(steering.y);
   torque -= xv * steering.y * mDataBlock->steeringForce;
   torque -= zv * steering.x * mDataBlock->steeringForce;

   // Roll
   torque += yv * steering.x * mDataBlock->steeringRollForce;
   F32 ar = mDataBlock->autoAngularForce * mDot(xv,Point3F(0,0,1));
   ar -= mDataBlock->rollForce * mDot(xv, mRigid.linVelocity);
   torque += yv * ar;

   // Add in force from physical zones...
   force += mAppliedForce;

   // Container buoyancy & drag
   force -= Point3F(0, 0, 1) * (mBuoyancy * sFlyingVehicleGravity * mRigid.mass * mGravityMod);
   force -= mRigid.linVelocity * mDrag;

   //
   mRigid.force  = force;
   mRigid.torque = torque;
}
Exemple #25
0
void AITurretShape::_trackTarget(F32 dt)
{
   // Only on server
   if (isClientObject())
      return;

   // We can only track a target if we have one
   if (!mTarget.isValid())
      return;

   Point3F targetPos = mTarget.target->getBoxCenter();

   // Can we see the target?
   MatrixF aimMat;
   getAimTransform(aimMat);
   Point3F start;
   aimMat.getColumn(3, &start);
   RayInfo ri;

   Point3F sightPoint;

   disableCollision();
   bool los = _testTargetLineOfSight(start, mTarget.target, sightPoint);
   enableCollision();

   if (!los)
   {
      // Target is blocked.  Should we try to track from its last
      // known position and velocity?
      SimTime curTime = Sim::getCurrentTime();
      if ( (curTime - mTarget.lastSightTime) > (mDataBlock->trackLostTargetTime * 1000.0f) )
      {
         // Time's up.  Stop tracking.
         _cleanupTargetAndTurret();
         return;
      }
      
      // Use last known information to attempt to
      // continue to track target for a while.
      targetPos = mTarget.lastPos + mTarget.lastVel * F32(curTime - mTarget.lastSightTime) / 1000.0f;
   }
   else
   {
      // Target is visible

      // We only track targets that are alive
      if (mTarget.target->getDamageState() != Enabled)
      {
         // We can't track any more
         _cleanupTargetAndTurret();
         return;
      }

      targetPos = sightPoint;

      // Store latest target info
      mTarget.lastPos = targetPos;
      mTarget.lastVel = mTarget.target->getVelocity();
      mTarget.lastSightTime = Sim::getCurrentTime();
   }

   // Calculate angles to face the target, specifically the part that we can see
   VectorF toTarget;
   MatrixF mat;
   S32 node = mDataBlock->aimNode;
   if (node != -1)
   {
      // Get the current position of our node
      MatrixF* nodeTrans = &mShapeInstance->mNodeTransforms[node];
      Point3F currentPos;
      nodeTrans->getColumn(3, &currentPos);

      // Turn this into a matrix we can use to put the target
      // position into our space.
      MatrixF nodeMat(true);
      nodeMat.setColumn(3, currentPos);
      mat.mul(mObjToWorld, nodeMat);
      mat.affineInverse();
   }
   else
   {
      mat = mWorldToObj;
   }
   mat.mulP(targetPos, &toTarget);

   // lead the target
   F32 timeToTargetSquared = (mWeaponLeadVelocitySquared > 0) ? toTarget.lenSquared() / mWeaponLeadVelocitySquared : 0;
   if (timeToTargetSquared > 1.0)
   {
      targetPos = targetPos + (mTarget.lastVel * mSqrt(timeToTargetSquared));
      mat.mulP(targetPos, &toTarget);
   }

   F32 yaw, pitch;
   MathUtils::getAnglesFromVector(toTarget, yaw, pitch);
   if (yaw > M_PI_F)
      yaw = yaw - M_2PI_F;
   //if (pitch > M_PI_F)
   //   pitch = -(pitch - M_2PI_F);

   Point3F rot(-pitch, 0.0f, yaw);

   // If we have a rotation rate make sure we follow it
   if (mHeadingRate > 0)
   {
      F32 rate = mHeadingRate * dt;
      F32 rateCheck = mFabs(rot.z - mRot.z);
      if (rateCheck > rate)
      {
         // This will clamp the new value to the rate regardless if it
         // is increasing or decreasing.
         rot.z = mClampF(rot.z, mRot.z-rate, mRot.z+rate);
      }
   }
   if (mPitchRate > 0)
   {
      F32 rate = mPitchRate * dt;
      F32 rateCheck = mFabs(rot.x - mRot.x);
      if (rateCheck > rate)
      {
         // This will clamp the new value to the rate regardless if it
         // is increasing or decreasing.
         rot.x = mClampF(rot.x, mRot.x-rate, mRot.x+rate);
      }
   }

   // Test if the rotation to the target is outside of our limits
   if (_outsideLimits(rot))
   {
      // We can't track any more
      _cleanupTargetAndTurret();
      return;
   }

   // Test if the target is out of weapons range
   if (toTarget.lenSquared() > mWeaponRangeSquared)
   {
      // We can't track any more
      _cleanupTargetAndTurret();
      return;
   }

   mRot = rot;

   _setRotation( mRot );
   setMaskBits(TurretUpdateMask);
}
void AtlasConvex::getFeatures(const MatrixF& mat,const VectorF& n, ConvexFeature* cf)
{
   cf->material = 0;
   cf->object = mObject;

   // For a tetrahedron this is pretty easy.

   //    points...
   S32 firstVert = cf->mVertexList.size();
   cf->mVertexList.increment(); mat.mulP(point[0], &cf->mVertexList.last());
   cf->mVertexList.increment(); mat.mulP(point[1], &cf->mVertexList.last());
   cf->mVertexList.increment(); mat.mulP(point[2], &cf->mVertexList.last());
   cf->mVertexList.increment(); mat.mulP(point[3], &cf->mVertexList.last());

   //    edges...
   cf->mEdgeList.increment(); 
   cf->mEdgeList.last().vertex[0] = firstVert+0;
   cf->mEdgeList.last().vertex[1] = firstVert+1;

   cf->mEdgeList.increment(); 
   cf->mEdgeList.last().vertex[0] = firstVert+1;
   cf->mEdgeList.last().vertex[1] = firstVert+2;

   cf->mEdgeList.increment(); 
   cf->mEdgeList.last().vertex[0] = firstVert+2;
   cf->mEdgeList.last().vertex[1] = firstVert+0;

   cf->mEdgeList.increment(); 
   cf->mEdgeList.last().vertex[0] = firstVert+3;
   cf->mEdgeList.last().vertex[1] = firstVert+0;

   cf->mEdgeList.increment(); 
   cf->mEdgeList.last().vertex[0] = firstVert+3;
   cf->mEdgeList.last().vertex[1] = firstVert+1;

   cf->mEdgeList.increment(); 
   cf->mEdgeList.last().vertex[0] = firstVert+3;
   cf->mEdgeList.last().vertex[1] = firstVert+2;

   //    triangles...
   cf->mFaceList.increment();
   cf->mFaceList.last().normal;
   mat.mulV(normal, &cf->mFaceList.last().normal);
   cf->mFaceList.last().vertex[0] = firstVert+0;
   cf->mFaceList.last().vertex[1] = firstVert+1;
   cf->mFaceList.last().vertex[2] = firstVert+2;

   cf->mFaceList.increment();
   mat.mulV(PlaneF(point[0], point[1], point[3]), &cf->mFaceList.last().normal);
   cf->mFaceList.last().vertex[0] = firstVert+3;
   cf->mFaceList.last().vertex[1] = firstVert+0;
   cf->mFaceList.last().vertex[2] = firstVert+1;

   cf->mFaceList.increment();
   mat.mulV(PlaneF(point[1], point[2], point[3]), &cf->mFaceList.last().normal);
   cf->mFaceList.last().vertex[0] = firstVert+3;
   cf->mFaceList.last().vertex[1] = firstVert+1;
   cf->mFaceList.last().vertex[2] = firstVert+2;

   cf->mFaceList.increment();
   mat.mulV(PlaneF(point[2], point[0], point[3]), &cf->mFaceList.last().normal);
   cf->mFaceList.last().vertex[0] = firstVert+3;
   cf->mFaceList.last().vertex[1] = firstVert+0;
   cf->mFaceList.last().vertex[2] = firstVert+2;

   // All done!
}
Exemple #27
0
void Polytope::buildBox(const MatrixF& transform,const Box3F& box)
{
   // Box is assumed to be axis aligned in the source space.
   // Transform into geometry space
   Point3F xvec,yvec,zvec,min;
   transform.getColumn(0,&xvec);
   xvec *= box.len_x();
   transform.getColumn(1,&yvec);
   yvec *= box.len_y();
   transform.getColumn(2,&zvec);
   zvec *= box.len_z();
   transform.mulP(box.minExtents,&min);

   // Initial vertices
   mVertexList.setSize(8);
   mVertexList[0].point = min;
   mVertexList[1].point = min + yvec;
   mVertexList[2].point = min + xvec + yvec;
   mVertexList[3].point = min + xvec;
   mVertexList[4].point = mVertexList[0].point + zvec;
   mVertexList[5].point = mVertexList[1].point + zvec;
   mVertexList[6].point = mVertexList[2].point + zvec;
   mVertexList[7].point = mVertexList[3].point + zvec;
   S32 i;
   for (i = 0; i < 8; i++)
      mVertexList[i].side = 0;

   // Initial faces
   mFaceList.setSize(6);
   for (S32 f = 0; f < 6; f++) {
      Face& face = mFaceList[f];
      face.original = true;
      face.vertex = 0;
   }

   mFaceList[0].plane.set(mVertexList[0].point,xvec);
   mFaceList[0].plane.invert();
   mFaceList[1].plane.set(mVertexList[2].point,yvec);
   mFaceList[2].plane.set(mVertexList[2].point,xvec);
   mFaceList[3].plane.set(mVertexList[0].point,yvec);
   mFaceList[3].plane.invert();
   mFaceList[4].plane.set(mVertexList[0].point,zvec);
   mFaceList[4].plane.invert();
   mFaceList[5].plane.set(mVertexList[4].point,zvec);

   // Initial edges
   mEdgeList.setSize(12);
   Edge* edge = mEdgeList.begin();
   S32 nextEdge = 0;
   for (i = 0; i < 4; i++) {
      S32 n = (i == 3)? 0: i + 1;
      S32 p = (i == 0)? 3: i - 1;
      edge->vertex[0] = i;
      edge->vertex[1] = n;
      edge->face[0] = i;
      edge->face[1] = 4;
      edge->next = ++nextEdge;
      edge++;
      edge->vertex[0] = 4 + i;
      edge->vertex[1] = 4 + n;
      edge->face[0] = i;
      edge->face[1] = 5;
      edge->next = ++nextEdge;
      edge++;
      edge->vertex[0] = i;
      edge->vertex[1] = 4 + i;
      edge->face[0] = i;
      edge->face[1] = p;
      edge->next = ++nextEdge;
      edge++;
   }
   edge[-1].next = -1;

   // Volume
   mVolumeList.setSize(1);
   Volume& volume = mVolumeList.last();
   volume.edgeList = 0;
   volume.material = -1;
   volume.object = 0;
   sideCount = 0;
}
bool SceneCullingState::isOccludedByTerrain( SceneObject* object ) const
{
   PROFILE_SCOPE( SceneCullingState_isOccludedByTerrain );

   // Don't try to occlude globally bounded objects.
   if( object->isGlobalBounds() )
      return false;

   const Vector< SceneObject* >& terrains = getSceneManager()->getContainer()->getTerrains();
   const U32 numTerrains = terrains.size();

   for( U32 terrainIdx = 0; terrainIdx < numTerrains; ++ terrainIdx )
   {
      TerrainBlock* terrain = dynamic_cast< TerrainBlock* >( terrains[ terrainIdx ] );
      if( !terrain )
         continue;

      MatrixF terrWorldTransform = terrain->getWorldTransform();

      Point3F localCamPos = getCameraState().getViewPosition();
      terrWorldTransform.mulP(localCamPos);
      F32 height;
      terrain->getHeight( Point2F( localCamPos.x, localCamPos.y ), &height );
      bool aboveTerrain = ( height <= localCamPos.z );

      // Don't occlude if we're below the terrain.  This prevents problems when
      //  looking out from underground bases...
      if( !aboveTerrain )
         continue;

      const Box3F& oBox = object->getObjBox();
      F32 minSide = getMin(oBox.len_x(), oBox.len_y());
      if (minSide > 85.0f)
         continue;

      const Box3F& rBox = object->getWorldBox();
      Point3F ul(rBox.minExtents.x, rBox.minExtents.y, rBox.maxExtents.z);
      Point3F ur(rBox.minExtents.x, rBox.maxExtents.y, rBox.maxExtents.z);
      Point3F ll(rBox.maxExtents.x, rBox.minExtents.y, rBox.maxExtents.z);
      Point3F lr(rBox.maxExtents.x, rBox.maxExtents.y, rBox.maxExtents.z);

      terrWorldTransform.mulP(ul);
      terrWorldTransform.mulP(ur);
      terrWorldTransform.mulP(ll);
      terrWorldTransform.mulP(lr);

      Point3F xBaseL0_s = ul - localCamPos;
      Point3F xBaseL0_e = lr - localCamPos;
      Point3F xBaseL1_s = ur - localCamPos;
      Point3F xBaseL1_e = ll - localCamPos;

      static F32 checkPoints[3] = {0.75, 0.5, 0.25};
      RayInfo rinfo;
      for( U32 i = 0; i < 3; i ++ )
      {
         Point3F start = (xBaseL0_s * checkPoints[i]) + localCamPos;
         Point3F end   = (xBaseL0_e * checkPoints[i]) + localCamPos;

         if (terrain->castRay(start, end, &rinfo))
            continue;

         terrain->getHeight(Point2F(start.x, start.y), &height);
         if ((height <= start.z) == aboveTerrain)
            continue;

         start = (xBaseL1_s * checkPoints[i]) + localCamPos;
         end   = (xBaseL1_e * checkPoints[i]) + localCamPos;

         if (terrain->castRay(start, end, &rinfo))
            continue;

         Point3F test = (start + end) * 0.5;
         if (terrain->castRay(localCamPos, test, &rinfo) == false)
            continue;

         return true;
      }
   }

   return false;
}
Exemple #29
0
F32 GjkCollisionState::distance(const MatrixF& a2w, const MatrixF& b2w,
   const F32 dontCareDist, const MatrixF* _w2a, const MatrixF* _w2b)
{
   num_iterations = 0;
   MatrixF w2a,w2b;

   if (_w2a == NULL || _w2b == NULL) {
      w2a = a2w;
      w2b = b2w;
      w2a.inverse();
      w2b.inverse();
   }
   else {
      w2a = *_w2a;
      w2b = *_w2b;
   }

   reset(a2w,b2w);
   bits = 0;
   all_bits = 0;
   F32 mu = 0;

   do {
      nextBit();

      VectorF va,sa;
      w2a.mulV(-v,&va);
      p[last] = a->support(va);
      a2w.mulP(p[last],&sa);

      VectorF vb,sb;
      w2b.mulV(v,&vb);
      q[last] = b->support(vb);
      b2w.mulP(q[last],&sb);

      VectorF w = sa - sb;
      F32 nm = mDot(v, w) / dist;
      if (nm > mu)
         mu = nm;
      if (mu > dontCareDist)
         return mu;
      if (mFabs(dist - mu) <= dist * rel_error)
         return dist;

      ++num_iterations;
      if (degenerate(w) || num_iterations > sIteration) {
         ++num_irregularities;
         return dist;
      }

      y[last] = w;
      all_bits = bits | last_bit;

      if (!closest(v)) {
         ++num_irregularities;
         return dist;
      }

      dist = v.len();
   }
   while (bits < 15 && dist > sTolerance) ;

   if (bits == 15 && mu <= 0)
      dist = 0;
   return dist;
}
bool ForestItem::castRay( const Point3F &start, const Point3F &end, RayInfo *outInfo, bool rendered ) const
{
   if ( !mWorldBox.collideLine( start, end ) )
      return false;

   Point3F s, e;
   MatrixF mat = getTransform();
   mat.scale( Point3F(mScale) );
   mat.inverse();

   mat.mulP( start, &s );
   mat.mulP( end, &e );

   TSForestItemData *data = (TSForestItemData*)mDataBlock;
   TSShapeInstance *si = data->getShapeInstance();

   if ( !si ) 
      return false;
   
   if ( rendered )
   {
      // Always raycast against detail level zero
      // because it makes lots of things easier.
      if ( !si->castRayRendered( s, e, outInfo, 0 ) )
         return false;

      if ( outInfo->userData != NULL )
         *(ForestItem*)(outInfo->userData) = *this;

      return true;
   }

   RayInfo shortest;  
   shortest.t = 1e8;
   bool gotMatch = false;
   S32 detail;

   const Vector<S32> &details = data->getLOSDetails();
   for (U32 i = 0; i < details.size(); i++) 
   {
      detail = details[i];
      if (detail != -1) 
      {
         //si->animate(data->mLOSDetails[i]);

         if ( si->castRayOpcode( detail, s, e, outInfo ) )         
         {
            if (outInfo->t < shortest.t)
            {
               gotMatch = true;
               shortest = *outInfo;      
            }
         }
      }
   }

   if ( !gotMatch )
      return false;

   // Copy out the shortest time...
   *outInfo = shortest;

   if ( outInfo->userData != NULL )
      *(ForestItem*)(outInfo->userData) = *this;

   return true;   
}