Beispiel #1
0
void Projectile::interpolateTick(F32 delta)
{
   Parent::interpolateTick(delta);

   if( mHasExploded )
      return;

   Point3F interpPos = mCurrDeltaBase + mCurrBackDelta * delta;
   Point3F dir = mCurrVelocity;
   if(dir.isZero())
      dir.set(0,0,1);
   else
      dir.normalize();

   MatrixF xform(true);
	xform = MathUtils::createOrientFromDir(dir);
   xform.setPosition(interpPos);
   setRenderTransform(xform);

   // fade out the projectile image
   S32 time = (S32)(mCurrTick - delta);
   if(time > mDataBlock->fadeDelay)
   {
      F32 fade = F32(time - mDataBlock->fadeDelay);
      mFadeValue = 1.0 - (fade / F32(mDataBlock->lifetime));
   }
   else
      mFadeValue = 1.0;

   updateSound();
}
Beispiel #2
0
void Etherform::updateCameraPos(F32 delta)
{
	//
	// Update 3rd person camera position.
	//

	F32 min,max;
	Point3F offset;
	MatrixF rot;
	this->getCameraParameters(&min,&max,&offset,&rot);

	Point3F vec = mCameraTargetPos - mCameraPos;
	F32    dist = vec.len();

	if(dist == 0)
	{
		// Catch camera position up to its target position.
		mCameraPos = mCameraTargetPos;
	}
	else if(dist > max)
	{
		// Catch camera up to max allowed dist from target position.
		vec.normalize(); vec.neg();
		mCameraPos = mCameraTargetPos + vec * max;
	}
	else
	{
		// Move camera pos towards its target pos.
#if 0
		F32 speed = mDataBlock->accelerationForce;
		speed *= 1 - (1/vec.lenSquared());

		vec.normalize();
		mCameraPos += vec * speed * delta;
#else
		//F32 speedScale = this->getVelocity().len() / mDataBlock->accelerationForce;
		F32 speedScale = 4; //mDataBlock->accelerationForce / 2;
		F32 distScale = 1 - (1/vec.lenSquared());
		vec *= speedScale * distScale * delta;
		if(vec.len() > dist)
			mCameraPos = mCameraTargetPos;
		else
			mCameraPos += vec;
#endif
	}
}
void PathCamera::calculateLookDirMat(Point3F dir)
{
	mLookDirMat.identity();

	if(dir == Point3F(0.f, 0.f, 0.f))
	{
		mUseLookDirMatrix = false;
		return;
	}

	Point3F left = mCross(dir, Point3F(0.f, 0.f, 1.f));
	left.normalize();
	Point3F up = mCross(left, dir);
	up.normalize();

	mLookDirMat.setColumn(0, Point4F(left.x, left.y, left.z, 0.f));			
	mLookDirMat.setColumn(1, Point4F(dir.x, dir.y, dir.z, 0.f));	
	mLookDirMat.setColumn(2, Point4F(up.x, up.y, up.z, 0.f));		

	mUseLookDirMatrix = true;	
}
Beispiel #4
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;
}
//.logicking >>
void PathCamera::setLookDir(Point3F dir)
{
	if(dir == Point3F(0.f, 0.f, 0.f))
	{
		mLookDirVector = dir;	
		setMaskBits(LookDirVectorMask);
	}
	else
	{
		dir.normalize();	
		mLookDirVector = dir;	
		calculateLookDirMat(mLookDirVector);
		setMaskBits(LookDirVectorMask);
	}	
}
Beispiel #6
0
//----------------------------------------------------------------------------
// Update ring
//----------------------------------------------------------------------------
void Splash::updateRing( SplashRing& ring, F32 dt )
{
   for( U32 i=0; i<ring.points.size(); i++ )
   {
      if( mDead )
      {
         Point3F vel = ring.points[i].velocity;
         vel.normalize();
         vel *= mDataBlock->acceleration;
         ring.points[i].velocity += vel * dt;
      }

      ring.points[i].velocity += Point3F( 0.0f, 0.0f, -9.8f ) * dt;
      ring.points[i].position += ring.points[i].velocity * dt;
   }
}
Beispiel #7
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;
}
void PathCamera::calculateAim(Point3F currentPosition)
{
	if(mAimTarget == -1 && mAimOffset == Point3F(0.f, 0.f, 0.f))	
	{
		calculateLookDirMat(mLookDirVector);
		return;
	}

	Point3F dir = mAimOffset;

	if(mAimTarget > 0)
	{	
		SceneObject* obj = NULL;
		Sim::findObject(mAimTarget, obj);
		if(obj)
			dir += obj->getPosition();
	}

	dir = dir - currentPosition;
	dir.normalize();
	calculateLookDirMat(dir);
}
void AppMesh::computeNormals()
{
   // Clear normals
   normals.setSize( points.size() );
   for (S32 iNorm = 0; iNorm < normals.size(); iNorm++)
      normals[iNorm] = Point3F::Zero;

   // Sum triangle normals for each vertex
   for (S32 iPrim = 0; iPrim < primitives.size(); iPrim++)
   {
      const TSDrawPrimitive& prim = primitives[iPrim];

      for (S32 iInd = 0; iInd < prim.numElements; iInd += 3)
      {
         // Compute the normal for this triangle
         S32 idx0 = indices[prim.start + iInd + 0];
         S32 idx1 = indices[prim.start + iInd + 1];
         S32 idx2 = indices[prim.start + iInd + 2];

         const Point3F& v0 = points[idx0];
         const Point3F& v1 = points[idx1];
         const Point3F& v2 = points[idx2];

         Point3F n;
         mCross(v2 - v0, v1 - v0, &n);
         n.normalize();    // remove this to use 'weighted' normals (large triangles will have more effect)

         normals[idx0] += n;
         normals[idx1] += n;
         normals[idx2] += n;
      }
   }

   // Normalize the vertex normals (this takes care of averaging the triangle normals)
   for (S32 iNorm = 0; iNorm < normals.size(); iNorm++)
      normals[iNorm].normalize();
}
Beispiel #10
0
void ScatterSky::_debugRender( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat )
{
   GFXStateBlockDesc desc;
   desc.fillMode = GFXFillSolid;
   desc.setBlend( false, GFXBlendOne, GFXBlendZero );
   desc.setZReadWrite( false, false );
   GFXStateBlockRef sb = GFX->GFX->createStateBlock( desc );

   GFX->setStateBlock( sb );

   PrimBuild::begin( GFXLineStrip, mSkyPoints.size() );
   PrimBuild::color3i( 255, 0, 255 );

   for ( U32 i = 0; i < mSkyPoints.size(); i++ )
   {
      Point3F pnt = mSkyPoints[i];
      pnt.normalize();
      pnt *= 500;
      pnt += state->getCameraPosition();
      PrimBuild::vertex3fv( pnt );
   }

   PrimBuild::end();
}
void SimPlanet::load()
{
   unload();
   
   if ((textureTag != 0) && (!manager->isServer())) {
      ResourceManager &rm = *SimResource::get(manager);
      const char *filename = SimTagDictionary::getString(manager, textureTag);
   
      // load the texture
      hTexture = rm.load(filename);
      AssertWarn((bool)hTexture, 
         avar("Error reading bitmap file \"%s\"", filename));
      // don't want to assert fatal because we don't want to bring down
      // the mission editor
      if ((bool)hTexture) {
         planet.texture = (GFXBitmap *)hTexture;
         addToSet(SimRenderSetId);
         inRenderSet = true;
      }         
   }   
   else
      planet.texture = NULL;

   // calculate planet position in world coordinates
   // add 90 to azimuth so that zero is at up Y axis
   if (incidence > 89.0f)
      incidence = 89.0f;
   if (incidence < -89.0f)
      incidence = -89.0f;
   const float az = azimuth + 90.0f;
   const float c = planet.distance*m_cos(DEGRAD*incidence);
   planet.position = Point3F(c*m_cos(DEGRAD*az), c*m_sin(DEGRAD*az), planet.distance*m_sin(DEGRAD*incidence));

   // initialize light if any
   Point3F direction = planet.position;
   direction.normalize();
   direction *= -1.0f;

   if (castShadows) {
      // set static data items
      shadowDirection = direction;
      shadows = true;
   }


   light.setAim(direction);
   //light.setType(TS::Light::LightDirectional);
   light.setType(TS::Light::LightDirectionalWrap);
   light.setIntensity(intensity.red, intensity.green, intensity.blue);
   if (intensity.red > 0.0f || intensity.green > 0.0f || intensity.blue > 0.0f 
      || ambient.red > 0.0f || ambient.green > 0.0f || ambient.blue > 0.0f) {
      addToSet(SimLightSetId);
      inLightSet = true;
      lensFlare.setColor(intensity);
   }
   planet.lensFlare = useLensFlare ? &lensFlare : NULL;

   // initialize static texture coordinates
   textCoord[0].x = 0.0f;  textCoord[0].y = 0.0f;
   textCoord[1].x = 1.0f;  textCoord[1].y = 0.0f;
   textCoord[2].x = 1.0f;  textCoord[2].y = 1.0f;
   textCoord[3].x = 0.0f;  textCoord[3].y = 1.0f;

   setMaskBits(Modified);
}
void BaseShadowRenderImage::preRenderShadow(TSRenderContext & rc, float curTime)
{
   if (!castShadow)
      return;
      
	// do visibility check for shadow
   Point3F center;
   m_mul(shape->getShape().fCenter,transform,&center);
	SphereF shadowSphere = SphereF(center,shape->getShape().fRadius);
	int shadowVis = rc.getCamera()->testVisibility(shadowSphere);
	if ( shadowVis==TS::ClipNoneVis )
   {
      shadowSettings.shadowDetail = -1;
      return;
   }

   // shape detail to use for shadows
   if (!shadowOwnDetail)
   {
      projSize = rc.getCamera()->transformProjectRadius( center, shape->getShape().fRadius );
      float adjustedSize = shadowDetailScale * projSize;
                           
      shadowSettings.shadowDetail = shape->getShape().selectDetail( adjustedSize );

      if (shadowSettings.shadowDetail==-1)
         return;
   }

   // first pass at shadow details
   setShadowDetailsA(rc);

   // set shadow details may veto shadow
   if (shadowSettings.shadowDetail==-1)
      return;

   // set light direction, but only if different than before
   Point3F * pLight = &lightDirection;
   Point3F tempDirection;
   if (swingDown != 0.0f)
   {
      tempDirection = (lightDirection * (1.0f - swingDown)) + (Point3F(0, 0, -1) * swingDown);
      tempDirection.normalize();
      pLight = &tempDirection;
   }
   if (m_dot(*pLight,lastLight) < 0.999)
   {
      shadow.setLight( *pLight, shape);
      lastLight = *pLight;
      nextShadowUpdateTime = -1;
   }

   // set position of shadow
   shadow.setPosition(transform.p);

   if (shadowSettings.cacheProjection)
   {
      if (shadowSettings.recacheProjection)
      {
         shadow.calcSourceWindow(shape,transform);
         getPolys();
         shadow.cachePolys();
         shadowSettings.recacheProjection = false;
      }
   }
   else
   {
      shadow.calcSourceWindow(shape,transform);
      getPolys();
      Point3F cc = rc.getCamera()->getTCW().p;
      Point3F camY = transform.p-cc;
      camY.normalize();
      shadow.getPlanes(cc,camY);
   }
   
   setShadowDetails(rc);
   
   // set shadow details may veto shadow
   if (shadowSettings.shadowDetail==-1)
      return;

   if (shadowSettings.shadowDetail < shadowSettings.hiShadowDetail)
      shadowSettings.shadowDetail = shadowSettings.hiShadowDetail;

   // adjust next update time...
   nextShadowUpdateTime += shadowSettings.updateDelta - prevShadowUpdateDelta;
   prevShadowUpdateDelta = shadowSettings.updateDelta;

   // adjust bmp dim...
   int newBmpDim = shadowSettings.bmpDim;
   if (newBmpDim != prevBmpDim)
   {
      prevBmpDim = newBmpDim;
      shadow.setBitmapSize(deviceManager.getGFXDeviceManager(),newBmpDim,rc.getSurface());
      nextShadowUpdateTime = -1;
   }

   shadow.setAlphaLevel(alphaLevel);

   // create the shadow bitmap if needed
   if (curTime > nextShadowUpdateTime)
   {
      if (shadowSettings.useFloor)
      {
         SimContainerQuery query;
         Box3F & box = query.box;
         box.fMin    = box.fMax = center;
         box.fMin.z += shape->getShape().fRadius;
         box.fMax.z -= shape->getShape().fRadius * 1.5f;
         query.id = -1;
         query.type = -1;
         query.mask = shadowSettings.projectTerrainOnly ? SimTerrainObjectType : projectionMask;
         SimCollisionInfo collision;
         if (root->findLOS(query,&collision))
         {
            Point3F n,p;
            m_mul(collision.surfaces[0].position,collision.surfaces.tWorld,&p);
            m_mul(collision.surfaces[0].normal,(RMat3F&)collision.surfaces.tWorld,&n);
            p -= transform.p;
            Point3F lift = n;
            lift *= shadowSettings.liftFloor;
            p += lift;
            shadow.setFloor(p,n);
         }
         else
            shadow.clearFloor();
      }
      else
         shadow.clearFloor();

      shape->setDetailLevel(shadowSettings.shadowDetail);
      shape->animate();
      GFXPalette * pal = SimGame::get()->getWorld(SimGame::CLIENT)->getPalette();
      AssertFatal(pal, "invalid palette");
      // getShadowBitmap assumes calcSourceWindow already called...
      // ...but that's ok because we called it above
      shadow.getShadowBitmap(shape,pal,transform,shadowSettings.blurMethod);
      nextShadowUpdateTime = curTime + shadowSettings.updateDelta;
   }

	AssertFatal(root,
		"shadowRenderImage::preRenderShadow:  cannot cast shadow before \'root\' container set");

   // this'll keep track of how many shadows are out there
   if (shadowNum < 0)
      shadowNum=1; // first preRender this render cycle
   else
      shadowNum++;
}
Beispiel #13
0
void CloudLayer::_initBuffers()
{      
   // Vertex Buffer...

   Point3F vertScale( 16.0f, 16.0f, mHeight );
   F32 zOffset = -( mCos( mSqrt( 1.0f ) ) + 0.01f );
   
   mVB.set( GFX, smVertCount, GFXBufferTypeStatic );   
   GFXCloudVertex *pVert = mVB.lock(); 
   if(!pVert) return;

   for ( U32 y = 0; y < smVertStride; y++ )
   {
      F32 v = ( (F32)y / (F32)smStrideMinusOne - 0.5f ) * 2.0f;

      for ( U32 x = 0; x < smVertStride; x++ )
      {
         F32 u = ( (F32)x / (F32)smStrideMinusOne - 0.5f ) * 2.0f;

         F32 sx = u;
         F32 sy = v;
         F32 sz = mCos( mSqrt( sx*sx + sy*sy ) ) + zOffset;
         //F32 sz = 1.0f;
         pVert->point.set( sx, sy, sz );
         pVert->point *= vertScale;

         // The vert to our right.
         Point3F rpnt;

         F32 ru = ( (F32)( x + 1 ) / (F32)smStrideMinusOne - 0.5f ) * 2.0f;
         F32 rv = v;

         rpnt.x = ru;
         rpnt.y = rv;
         rpnt.z = mCos( mSqrt( rpnt.x*rpnt.x + rpnt.y*rpnt.y ) ) + zOffset;
         rpnt *= vertScale;

         // The vert to our front.
         Point3F fpnt;

         F32 fu = u;
         F32 fv = ( (F32)( y + 1 ) / (F32)smStrideMinusOne - 0.5f ) * 2.0f;

         fpnt.x = fu;
         fpnt.y = fv;
         fpnt.z = mCos( mSqrt( fpnt.x*fpnt.x + fpnt.y*fpnt.y ) ) + zOffset;
         fpnt *= vertScale;

         Point3F fvec = fpnt - pVert->point;
         fvec.normalize();

         Point3F rvec = rpnt - pVert->point;
         rvec.normalize();

         pVert->normal = mCross( fvec, rvec );
         pVert->normal.normalize();
         pVert->binormal = fvec;
         pVert->tangent = rvec;
         pVert->texCoord.set( u, v );   
         pVert++;
      }
   }

   mVB.unlock();


   // Primitive Buffer...   

   mPB.set( GFX, smTriangleCount * 3, smTriangleCount, GFXBufferTypeStatic );

   U16 *pIdx = NULL;   
   mPB.lock(&pIdx);     
   U32 curIdx = 0; 

   for ( U32 y = 0; y < smStrideMinusOne; y++ )
   {
      for ( U32 x = 0; x < smStrideMinusOne; x++ )
      {
         U32 offset = x + y * smVertStride;

         pIdx[curIdx] = offset;
         curIdx++;
         pIdx[curIdx] = offset + 1;
         curIdx++;
         pIdx[curIdx] = offset + smVertStride + 1;
         curIdx++;

         pIdx[curIdx] = offset;
         curIdx++;
         pIdx[curIdx] = offset + smVertStride + 1;
         curIdx++;
         pIdx[curIdx] = offset + smVertStride;
         curIdx++;
      }
   }

   mPB.unlock();   
}
Beispiel #14
0
void TSMesh::innerRender( TSMaterialList *materials, const TSRenderState &rdata, TSVertexBufferHandle &vb, GFXPrimitiveBufferHandle &pb )
{
   PROFILE_SCOPE( TSMesh_InnerRender );

   if( vertsPerFrame <= 0 ) 
      return;

   F32 meshVisibility = rdata.getFadeOverride() * mVisibility;
   if ( meshVisibility < VISIBILITY_EPSILON )
      return;

   const SceneRenderState *state = rdata.getSceneState();
   RenderPassManager *renderPass = state->getRenderPass();

   MeshRenderInst *coreRI = renderPass->allocInst<MeshRenderInst>();
   coreRI->type = RenderPassManager::RIT_Mesh;

   const MatrixF &objToWorld = GFX->getWorldMatrix();

   // Sort by the center point or the bounds.
   if ( rdata.useOriginSort() )
      coreRI->sortDistSq = ( objToWorld.getPosition() - state->getCameraPosition() ).lenSquared();
   else
   {
      Box3F rBox = mBounds;
      objToWorld.mul( rBox );
      coreRI->sortDistSq = rBox.getSqDistanceToPoint( state->getCameraPosition() );      
   }

   if (getFlags(Billboard))
   {
      Point3F camPos = state->getDiffuseCameraPosition();
      Point3F objPos;
      objToWorld.getColumn(3, &objPos);
      Point3F targetVector = camPos - objPos;
      if(getFlags(BillboardZAxis))
         targetVector.z = 0.0f;
      targetVector.normalize();
      MatrixF orient = MathUtils::createOrientFromDir(targetVector);
      orient.setPosition(objPos);
      orient.scale(objToWorld.getScale());

      coreRI->objectToWorld = renderPass->allocUniqueXform( orient );
   }
   else
      coreRI->objectToWorld = renderPass->allocUniqueXform( objToWorld );

   coreRI->worldToCamera = renderPass->allocSharedXform(RenderPassManager::View);
   coreRI->projection = renderPass->allocSharedXform(RenderPassManager::Projection);

   AssertFatal( vb.isValid(), "TSMesh::innerRender() - Got invalid vertex buffer!" );
   AssertFatal( pb.isValid(), "TSMesh::innerRender() - Got invalid primitive buffer!" );

   coreRI->vertBuff = &vb;
   coreRI->primBuff = &pb;
   coreRI->defaultKey2 = (U32) coreRI->vertBuff;

   coreRI->materialHint = rdata.getMaterialHint();

   coreRI->visibility = meshVisibility;  
   coreRI->cubemap = rdata.getCubemap();

   // NOTICE: SFXBB is removed and refraction is disabled!
   //coreRI->backBuffTex = GFX->getSfxBackBuffer();

   for ( S32 i = 0; i < primitives.size(); i++ )
   {
      const TSDrawPrimitive &draw = primitives[i];

      // We need to have a material.
      if ( draw.matIndex & TSDrawPrimitive::NoMaterial )
         continue;

#ifdef TORQUE_DEBUG
      // for inspection if you happen to be running in a debugger and can't do bit 
      // operations in your head.
      S32 triangles = draw.matIndex & TSDrawPrimitive::Triangles;
      S32 strip = draw.matIndex & TSDrawPrimitive::Strip;
      S32 fan = draw.matIndex & TSDrawPrimitive::Fan;
      S32 indexed = draw.matIndex & TSDrawPrimitive::Indexed;
      S32 type = draw.matIndex & TSDrawPrimitive::TypeMask;
      TORQUE_UNUSED(triangles);
      TORQUE_UNUSED(strip);
      TORQUE_UNUSED(fan);
      TORQUE_UNUSED(indexed);
      TORQUE_UNUSED(type);
#endif

      const U32 matIndex = draw.matIndex & TSDrawPrimitive::MaterialMask;
      BaseMatInstance *matInst = materials->getMaterialInst( matIndex );

#ifndef TORQUE_OS_MAC

      // Get the instancing material if this mesh qualifies.
      if ( meshType != SkinMeshType && pb->mPrimitiveArray[i].numVertices < smMaxInstancingVerts )
         matInst = InstancingMaterialHook::getInstancingMat( matInst );

#endif

      // If we don't have a material instance after the overload then
      // there is nothing to render... skip this primitive.
      matInst = state->getOverrideMaterial( matInst );
      if ( !matInst || !matInst->isValid())
         continue;

      // If the material needs lights then gather them
      // here once and set them on the core render inst.
      if ( matInst->isForwardLit() && !coreRI->lights[0] && rdata.getLightQuery() )
         rdata.getLightQuery()->getLights( coreRI->lights, 8 );

      MeshRenderInst *ri = renderPass->allocInst<MeshRenderInst>();
      *ri = *coreRI;

      ri->matInst = matInst;
      ri->defaultKey = matInst->getStateHint();
      ri->primBuffIndex = i;

      // Translucent materials need the translucent type.
      if ( matInst->getMaterial()->isTranslucent() )
      {
         ri->type = RenderPassManager::RIT_Translucent;
         ri->translucentSort = true;
      }

      renderPass->addInst( ri );
   }
}
void PSSMLightShadowMap::_calcPlanesCullForShadowCasters(Vector< Vector<PlaneF> > &out, const Frustum &viewFrustum, const Point3F &_ligthDir)
{

#define ENABLE_CULL_ASSERT

   PROFILE_SCOPE(PSSMLightShadowMap_render_getCullFrustrum);

   Point3F ligthDir = _ligthDir;
   PlaneF lightFarPlane, lightNearPlane;
   MatrixF lightFarPlaneMat(true);
   MatrixF invLightFarPlaneMat(true);

   // init data
   {
      ligthDir.normalize();
      Point3F viewDir = viewFrustum.getTransform().getForwardVector();
      viewDir.normalize();
      const Point3F viewPosition = viewFrustum.getPosition();
      const F32 viewDistance = viewFrustum.getBounds().len();
      lightNearPlane = PlaneF(viewPosition + (viewDistance * -ligthDir), ligthDir);

      const Point3F lightFarPlanePos = viewPosition + (viewDistance * ligthDir);
      lightFarPlane = PlaneF(lightFarPlanePos, -ligthDir);

      lightFarPlaneMat = MathUtils::createOrientFromDir(-ligthDir);
      lightFarPlaneMat.setPosition(lightFarPlanePos);
      lightFarPlaneMat.invertTo(&invLightFarPlaneMat);
   }

   Vector<Point2F> projVertices;

   //project all frustum vertices into plane
   // all vertices are 2d and local to far plane
   projVertices.setSize(8);
   for (int i = 0; i < 8; ++i) //
   {
      const Point3F &point = viewFrustum.getPoints()[i];
#ifdef ENABLE_CULL_ASSERT
      AssertFatal( PlaneF::Front == lightNearPlane.whichSide(point), "" );
      AssertFatal( PlaneF::Front == lightFarPlane.whichSide(point), "" );
#endif

      Point3F localPoint(lightFarPlane.project(point));
      invLightFarPlaneMat.mulP(localPoint);
      projVertices[i] = Point2F(localPoint.x, localPoint.z);
   }

   //create hull arround projected proints
   Vector<Point2F> hullVerts;
   MathUtils::mBuildHull2D(projVertices, hullVerts);

   Vector<PlaneF> planes;
   planes.push_back(lightNearPlane);
   planes.push_back(lightFarPlane);

   //build planes
   for (int i = 0; i < (hullVerts.size() - 1); ++i)
   {
      Point2F pos2D = (hullVerts[i] + hullVerts[i + 1]) / 2;
      Point3F pos3D(pos2D.x, 0, pos2D.y);

      Point3F pos3DA(hullVerts[i].x, 0, hullVerts[i].y);
      Point3F pos3DB(hullVerts[i + 1].x, 0, hullVerts[i + 1].y);

      // move hull points to 3d space
      lightFarPlaneMat.mulP(pos3D);
      lightFarPlaneMat.mulP(pos3DA);
      lightFarPlaneMat.mulP(pos3DB);

      PlaneF plane(pos3D, MathUtils::mTriangleNormal(pos3DB, pos3DA, (pos3DA - ligthDir)));
      planes.push_back(plane);
   }

   //recalculate planes for each splits
   for (int split = 0; split < mNumSplits; ++split)
   {
      Frustum subFrustum(viewFrustum);
      subFrustum.cropNearFar(mSplitDist[split], mSplitDist[split + 1]);
      subFrustum.setFarDist(getMin(subFrustum.getFarDist()*2.5f, viewFrustum.getFarDist()));
      subFrustum.update();

      Vector<PlaneF> subPlanes = planes;

      for (int planeIdx = 0; planeIdx < subPlanes.size(); ++planeIdx)
      {
         PlaneF &plane = subPlanes[planeIdx];
         F32 minDist = 0;

         //calculate near vertex distance
         for (int vertexIdx = 0; vertexIdx < 8; ++vertexIdx)
         {
            Point3F point = subFrustum.getPoints()[vertexIdx];
            minDist = getMin(plane.distToPlane(point), minDist);
         }

         // move plane to near vertex
         Point3F newPos = plane.getPosition() + (plane.getNormal() * minDist);
         plane = PlaneF(newPos, plane.getNormal());

#ifdef ENABLE_CULL_ASSERT
         for(int x = 0; x < 8; ++x)
         {
            AssertFatal( PlaneF::Back != plane.whichSide( subFrustum.getPoints()[x] ), "");
         }
#endif
      }

      out.push_back(subPlanes);
   }

#undef ENABLE_CULL_ASSERT

}
Move HoverPodController::getMove(ShapeBase* obj)
{
	Move retMove = NullMove;

	GameConnection* client = NULL;
	if(!Sim::findObject(mClientId, client)) 
		return retMove;

	ShapeBase* control = client->getControlObject();
	if(control)
	{
		Move cMove = client->lastReceivedMove();

		Point3F v1, v2;
		control->getTransform().getColumn(0, &v1);
		control->getTransform().getColumn(1, &v2);
		Point3F pv = v1*cMove.x + v2*cMove.y;

		//pv = mDirection * mDot(pv, mDirection);

		obj->getTransform().getColumn(0, &v1);
		obj->getTransform().getColumn(1, &v2);
		retMove.x = mDot(v1, pv);
		retMove.y = mDot(v2, pv);
	}
	return retMove;
	
#if 0
   if(this->isServerObject() && this->isMounted())
   {
		Move mMove = NullMove;
		ShapeBase* mount = this->getObjectMount();
		if(mount->getType() & VehicleObjectType)
		{
			Vehicle* vehicle = (Vehicle*)mount;
			if(move && move->x != 0)
			{
				mMove.yaw = move->x;
			}
			else
			{
				Point3F zv; vehicle->getTransform().getColumn(2, &zv);
				zv.normalize();
				Point3F m = vehicle->getRigid().angMomentum;
				//Point3F v = vehicle->getRigid().angVelocity;
				F32 dot = mDot(zv, m);
				//Con::printf("%f / %f %f %f / %f %f %f", dot,
				//	m.x, m.y, m.z, v.x, v.y, v.z);
				mMove.yaw = dot / 50;
			}

			if(move)
				mMove.y = move->y;

		}
		else if(move)
		{
			Point3F v1, v2;
			this->getTransform().getColumn(0, &v1);
			this->getTransform().getColumn(1, &v2);
			Point3F pv = v1*move->x + v2*move->y;

			mount->getTransform().getColumn(0, &v1);
			mount->getTransform().getColumn(1, &v2);

			mMove.x = mDot(v1, pv);
			mMove.y = mDot(v2, pv);
		}
		mount->processTick(&mMove);
   }
#endif
void GuiRiverEditorCtrl::on3DMouseDown(const Gui3DMouseEvent & event)
{
   mGizmo->on3DMouseDown( event );

   if ( !isFirstResponder() )
      setFirstResponder();
	
	// Get the raycast collision position
   Point3F tPos;
   if ( !getStaticPos( event, tPos ) )
		return;  

   // Construct a LineSegment from the camera position to 1000 meters away in
   // the direction clicked.
   // If that segment hits the terrain, truncate the ray to only be that length.

   // We will use a LineSegment/Sphere intersection test to determine if a RiverNode
   // was clicked.   

   Point3F startPnt = event.pos;
   Point3F endPnt = event.pos + event.vec * 1000.0f;

   RayInfo ri;   

   if ( gServerContainer.castRay(startPnt, endPnt, StaticObjectType, &ri) )
      endPnt = ri.point;

   River *riverPtr = NULL;
   River *clickedRiverPtr = NULL;

   // Did we click on a river? check current selection first
   U32 insertNodeIdx = -1;
   Point3F collisionPnt;
   if ( mSelRiver != NULL && mSelRiver->collideRay( event.pos, event.vec, &insertNodeIdx, &collisionPnt ) )
   {
      clickedRiverPtr = mSelRiver;
   }
   else
   {
      for ( SimSetIterator iter(mRiverSet); *iter; ++iter )
      {
         riverPtr = static_cast<River*>( *iter );
         if ( riverPtr->collideRay( event.pos, event.vec, &insertNodeIdx, &collisionPnt ) )
         {
            clickedRiverPtr = riverPtr;
            break;
         }
      }
   }

   // Did we click on a riverNode?
   bool nodeClicked = false;   
   S32 clickedNodeIdx = -1;
   F32 clickedNodeDist = mNodeSphereRadius;

   // If we clicked on the currently selected river, only scan its nodes
   if ( mSelRiver != NULL && clickedRiverPtr == mSelRiver )
   {
      for ( U32 i = 0; i < mSelRiver->mNodes.size(); i++ )
      {
         const Point3F &nodePos = mSelRiver->mNodes[i].point;

         Point3F screenPos;
         project( nodePos, &screenPos );

         F32 dist = ( event.mousePoint - Point2I(screenPos.x, screenPos.y) ).len();
         if ( dist < clickedNodeDist )
         {
            clickedNodeDist = dist;
            clickedNodeIdx = i;
            nodeClicked = true;
         }
      }
   }
   else
   {
      for ( SimSetIterator iter(mRiverSet); *iter; ++iter )
      {
         riverPtr = static_cast<River*>( *iter );
         
         for ( U32 i = 0; i < riverPtr->mNodes.size(); i++ )
         {
            const Point3F &nodePos = riverPtr->mNodes[i].point;

            Point3F screenPos;
            project( nodePos, &screenPos );

            F32 dist = ( event.mousePoint - Point2I(screenPos.x, screenPos.y) ).len();
            if ( dist < clickedNodeDist )
            {
               // we found a hit!
               clickedNodeDist = dist;
               clickedNodeIdx = i;
               nodeClicked = true;
               clickedRiverPtr = riverPtr;
            }
         }
      }
   }
	
	// shortcuts
	bool dblClick = ( event.mouseClickCount > 1 );
	if( dblClick )
   { 
		if( mMode == mSelectRiverMode )
		{
			setMode( mAddRiverMode, true );
			return;
		}
		if( mMode == mAddNodeMode )
		{
			// Delete the node attached to the cursor.
			deleteSelectedNode();
			mMode = mAddRiverMode;
			return;
		}
	}

	//this check is here in order to bounce back from deleting a whole road with ctrl+z
	//this check places the editor back into addrivermode
	if ( mMode == mAddNodeMode )
	{
      if ( !mSelRiver )
         mMode = mAddRiverMode;
	}

	if ( mMode == mSelectRiverMode )
	{
      // Did not click on a River or a node.
      if ( !clickedRiverPtr  )
      {
         setSelectedRiver( NULL );
         setSelectedNode( -1 );
         
         return;
      }

      // Clicked on a River that wasn't the currently selected River.
      if ( clickedRiverPtr != mSelRiver )
      {
         setSelectedRiver( clickedRiverPtr );
         setSelectedNode( clickedNodeIdx );
         return;
      }

     // Clicked on a node in the currently selected River that wasn't
      // the currently selected node.
      if ( nodeClicked )
      {
         setSelectedNode( clickedNodeIdx );
         return;
      }
	}
   else if ( mMode == mAddRiverMode )
   {
		if ( nodeClicked )
      {
			// A double-click on a node in Normal mode means set AddNode mode.  
         if ( clickedNodeIdx == 0 )
         {
				setSelectedRiver( clickedRiverPtr );
				setSelectedNode( clickedNodeIdx );

				mAddNodeIdx = clickedNodeIdx;
            mMode = mAddNodeMode; 

            mSelNode = mSelRiver->insertNode( tPos, mDefaultWidth, mDefaultDepth, mDefaultNormal, mAddNodeIdx );
            mIsDirty = true;

				return;
         }
			else if ( clickedNodeIdx == clickedRiverPtr->mNodes.size() - 1 )
         {
				setSelectedRiver( clickedRiverPtr );
				setSelectedNode( clickedNodeIdx );

            mAddNodeIdx = U32_MAX;
				mMode = mAddNodeMode;

            mSelNode = mSelRiver->addNode( tPos, mDefaultWidth, mDefaultDepth, mDefaultNormal);
            mIsDirty = true;
				setSelectedNode( mSelNode );

				return;
         } 
		}

		if ( !isMethod( "createRiver" ) )
      {
			Con::errorf( "GuiRiverEditorCtrl::on3DMouseDown - createRiver method does not exist." );
         return;
      }

      const char *res = Con::executef( this, "createRiver" );

      River *newRiver;
      if ( !Sim::findObject( res, newRiver ) )
      {
         Con::errorf( "GuiRiverEditorCtrl::on3DMouseDown - createRiver method did not return a river object." );
         return;
      }                

      // Add to MissionGroup                              
      SimGroup *missionGroup;
      if ( !Sim::findObject( "MissionGroup", missionGroup ) )               
         Con::errorf( "GuiRiverEditorCtrl - could not find MissionGroup to add new River" );
      else
         missionGroup->addObject( newRiver );

      Point3F pos( endPnt );
      pos.z += mDefaultDepth * 0.5f;

      newRiver->insertNode( pos, mDefaultWidth, mDefaultDepth, mDefaultNormal, 0 );
      U32 newNode = newRiver->insertNode( pos, mDefaultWidth, mDefaultDepth, mDefaultNormal, 1 );

      // Always add to the end of the road, the first node is the start.
      mAddNodeIdx = U32_MAX;
      
      setSelectedRiver( newRiver );      
      setSelectedNode( newNode );

      mMode = mAddNodeMode;

      // Disable the hover node while in addNodeMode, we
      // don't want some random node enlarged.
      mHoverNode = -1;

      // Grab the mission editor undo manager.
      UndoManager *undoMan = NULL;
      if ( !Sim::findObject( "EUndoManager", undoMan ) )
      {
         Con::errorf( "GuiMeshRoadEditorCtrl::on3DMouseDown() - EUndoManager not found!" );
         return;           
      }

      // Create the UndoAction.
      MECreateUndoAction *action = new MECreateUndoAction("Create MeshRoad");
      action->addObject( newRiver );

      // Submit it.               
      undoMan->addAction( action );

		return;
   }
	else if ( mMode == mAddNodeMode )
	{
		// Oops the road got deleted, maybe from an undo action?
      // Back to NormalMode.
      if ( mSelRiver )
      {
			// A double-click on a node in Normal mode means set AddNode mode.  
         if ( clickedNodeIdx == 0 )
         {
				submitUndo( "Add Node" );
				mAddNodeIdx = clickedNodeIdx;
            mMode = mAddNodeMode;
            mSelNode = mSelRiver->insertNode( tPos, mDefaultWidth, mDefaultDepth, mDefaultNormal, mAddNodeIdx );
            mIsDirty = true;
				setSelectedNode( mSelNode );

				return;
         }
			else
         {
				if( clickedRiverPtr && clickedNodeIdx == clickedRiverPtr->mNodes.size() - 1 )
				{
					submitUndo( "Add Node" );
					mAddNodeIdx = U32_MAX;
					mMode = mAddNodeMode;
					U32 newNode = mSelRiver->addNode( tPos, mDefaultWidth, mDefaultDepth, mDefaultNormal);  
               mIsDirty = true;
					setSelectedNode( newNode );

					return;
				}
				else
				{
					submitUndo( "Insert Node" );
					// A single-click on empty space while in
					// AddNode mode means insert / add a node.
					//submitUndo( "Add Node" );
					//F32 width = mSelRiver->getNodeWidth( mSelNode );
					U32 newNode = mSelRiver->insertNode( tPos, mDefaultWidth, mDefaultDepth, mDefaultNormal, mAddNodeIdx);
               mIsDirty = true;
					setSelectedNode( newNode );

					return;
				}
			}
		}
	}
	else if ( mMode == mInsertPointMode && mSelRiver != NULL )
	{
		if ( clickedRiverPtr == mSelRiver )
      {
			// NOTE: I guess we have to determine the if the clicked ray intersects a road but not a specific node...
         // in order to handle inserting nodes in the same way as for DecalRoad

         U32 prevNodeIdx = insertNodeIdx;
         U32 nextNodeIdx = ( prevNodeIdx + 1 > mSelRiver->mNodes.size() - 1 ) ? prevNodeIdx : prevNodeIdx + 1;

         const RiverNode &prevNode = mSelRiver->mNodes[prevNodeIdx];
         const RiverNode &nextNode = mSelRiver->mNodes[nextNodeIdx];

         F32 width = ( prevNode.width + nextNode.width ) * 0.5f;
         F32 depth = ( prevNode.depth + nextNode.depth ) * 0.5f;
         Point3F normal = ( prevNode.normal + nextNode.normal ) * 0.5f;
         normal.normalize();

         submitUndo( "Insert Node" );
         U32 newNode = mSelRiver->insertNode( collisionPnt, width, depth, normal, insertNodeIdx + 1 );
         mIsDirty = true;
         setSelectedNode( newNode );

			return;
       }
	}
	else if ( mMode == mRemovePointMode && mSelRiver != NULL )
	{
		if ( nodeClicked && clickedRiverPtr == mSelRiver )
      {
			setSelectedNode( clickedNodeIdx );
         deleteSelectedNode();
         return;
      }
	}
	else if ( mMode == mMovePointMode )
	{
		if ( nodeClicked && clickedRiverPtr == mSelRiver )
      {
			setSelectedNode( clickedNodeIdx );
         return;
      }
	}
	else if ( mMode == mScalePointMode )
	{
		if ( nodeClicked && clickedRiverPtr == mSelRiver )
      {
			setSelectedNode( clickedNodeIdx );
         return;
      }
	}
	else if ( mMode == mRotatePointMode )
	{
		if ( nodeClicked && clickedRiverPtr == mSelRiver )
      {
			setSelectedNode( clickedNodeIdx );
         return;
      }
	}
}
void blTerrainProxy::lightVector(LightInfo * light)
{
   // Grab our terrain object
   TerrainBlock* terrain = getObject();
   if (!terrain)
      return;

   // Get the direction to the light (the inverse of the direction
   // the light is pointing)
   Point3F lightDir = -light->getDirection();
   lightDir.normalize();

   // Get the ratio between the light map pixel and world space (used below)   
   F32 lmTerrRatio = (F32)mTerrainBlockSize / (F32) mLightMapSize;
   lmTerrRatio *= terrain->getSquareSize();

   // Get the terrain position
   Point3F terrPos( terrain->getTransform().getPosition() );

   U32 i = 0;
   for (U32 y = 0; y < mLightMapSize; y++)
   {
      for (U32 x = 0; x < mLightMapSize; x++)
      {
         // Get the relative pixel position and scale it
         // by the ratio between lightmap and world space
         Point2F pixelPos(x, y);
         pixelPos *= lmTerrRatio;         
         
         // Start with a default normal of straight up
         Point3F normal(0.0f, 0.0f, 1.0f);
         
         // Try to get the actual normal from the terrain.
         // Note: this won't change the default normal if
         // it can't find a normal.
         terrain->getNormal(pixelPos, &normal);

         // The terrain lightmap only contains shadows.
         F32 shadowed = 0.0f;

         // Get the height at the lightmap pixel's position
         F32 height = 0.0f;
         terrain->getHeight(pixelPos, &height);

         // Calculate the 3D position of the pixel
         Point3F pixelPos3F(pixelPos.x, pixelPos.y, height);

         // Translate that position by the terrain's transform
         terrain->getTransform().mulP(pixelPos3F);

         // Offset slighting along the normal so that we don't
         // raycast into ourself
         pixelPos3F += (normal * 0.1f);

         // Calculate the light's position.
         // If it is a vector light like the sun (no position
         // just direction) then translate along that direction
         // a reasonable distance to get a point sufficiently
         // far away
         Point3F lightPos = light->getPosition();
         if(light->getType() == LightInfo::Vector)
         {
            lightPos = 1000.f * lightDir;            
            lightPos = pixelPos3F + lightPos;
         }

         // Cast a ray from the world space position of the lightmap pixel to the light source.
         // If we hit something then we are in shadow. This allows us to be shadowed by anything
         // that supports a castRay operation.
         RayInfo info;
         if(terrain->getContainer()->castRay(pixelPos3F, lightPos, STATIC_COLLISION_TYPEMASK, &info))
         {
            // Shadow the pixel.
            shadowed = 1.0f;
         }

         // Set the final lightmap color.
         mLightmap[i++] += ColorF::WHITE * mClampF( 1.0f - shadowed, 0.0f, 1.0f );
      }
   }
}
Beispiel #19
0
void Turret::shoot (bool playerControlled, Player* targetPlayer)
{
   if (data && data->isSustained == false) {
	   if (data && data->projectile.type == -1)
	   	{
	   		if (!isGhost())
	   			if (const char* script = scriptName("onFire"))
	   				Console->executef(2, script, scriptThis());
	   	}
	   else
	   	{
	   		float energy = getEnergy();
	   		if (waitTime <= manager->getCurrentTime() && data && energy >= data->minGunEnergy && data->projectile.type != -1)
	   			{
                  TMat3F muzzleTransform;
	   				getMuzzleTransform(0, &muzzleTransform);
	   				Projectile* bullet = createProjectile(data->projectile);

	   				if (!playerControlled && data->deflection)
	   					{
	   						static Random random;
	   						EulerF angles;
	   					   muzzleTransform.angles (&angles);
	   						angles.x += (random.getFloat() - 0.5) * M_2PI * data->deflection;
	   						angles.z += (random.getFloat() - 0.5) * M_2PI * data->deflection;
	   						muzzleTransform.set (angles, muzzleTransform.p);
	   					}
	   				else
	   					if (playerControlled)
	   						{
	   							Point3F start = muzzleTransform.p;
	   							muzzleTransform = getEyeTransform ();
	   							aimedTransform (&muzzleTransform, start);
	   							muzzleTransform.p = start;
	   						}

	   				bullet->initProjectile (muzzleTransform, Point3F (0, 0, 0), getId());

	   	         if (bullet->isTargetable() == true) {
	   	            if (targetPlayer != NULL) {
	   						if (GameBase* mo = targetPlayer->getMountObject())
	   		               bullet->setTarget(static_cast<ShapeBase*>(mo));
	   						else
	   		               bullet->setTarget(targetPlayer);
                     } else if (playerControlled) {
                        ShapeBase* pClosest   = NULL;
                        Point3F    closeHisPos;
                        float      closestVal = -2.0f;
                        SimSet::iterator itr;
                     
                        Point3F lookDir;
                        getEyeTransform().getRow(1, &lookDir);
                        lookDir.normalize();

                        SimContainerQuery collisionQuery;
                        SimCollisionInfo  info;
                        collisionQuery.id     = getId();
                        collisionQuery.type   = -1;
                        collisionQuery.mask   = Projectile::csm_collisionMask;
                        collisionQuery.detail = SimContainerQuery::DefaultDetail;
                        collisionQuery.box.fMin = getEyeTransform().p;
                        SimContainer* pRoot = (SimContainer*)manager->findObject(SimRootContainerId);

                        SimSet* pSet = dynamic_cast<SimSet*>(manager->findObject(PlayerSetId));
                        AssertFatal(pSet != NULL, "No player set?");
                        for (itr = pSet->begin(); itr != pSet->end(); itr++) {
                           Player* pPlayer = dynamic_cast<Player*>(*itr);

                           if (!pPlayer || pPlayer->getVisibleToTeam(getTeam()) == false)
                              continue;

                           collisionQuery.box.fMax = pPlayer->getBoxCenter();
                           if (pRoot->findLOS(collisionQuery, &info, SimCollisionImageQuery::High) == true) {
                              if (info.object != (SimObject*)pPlayer)
                                 continue;
                           }

                           Point3F hisPos = pPlayer->getBoxCenter();
                           hisPos -= getLinearPosition();
                           hisPos.normalize();

                           float prod = m_dot(hisPos, lookDir);
                           if (prod > 0.0f && prod > closestVal) {
                              closestVal = prod;
                              pClosest   = pPlayer;
                              closeHisPos = hisPos;
                           }
                        }

                        pSet = dynamic_cast<SimSet*>(manager->findObject(MoveableSetId));
                        AssertFatal(pSet != NULL, "No moveable set?");
                        for (itr = pSet->begin(); itr != pSet->end(); itr++) {
                           if (((*itr)->getType() & VehicleObjectType) == 0)
                              continue;

                           ShapeBase* pObject = dynamic_cast<ShapeBase*>(*itr);
                           
                           if (pObject->getVisibleToTeam(getTeam()) == false)
                              continue;

                           collisionQuery.box.fMax = pObject->getBoxCenter();
                           if (pRoot->findLOS(collisionQuery, &info, SimCollisionImageQuery::High) == true) {
                              if (info.object != (SimObject*)pObject)
                                 continue;
                           }

                           Point3F hisPos = pObject->getBoxCenter();
                           hisPos -= getLinearPosition();
                           hisPos.normalize();

                           float prod = m_dot(hisPos, lookDir);
                           if (prod > 0.0f && prod > closestVal) {
                              closestVal = prod;
                              closeHisPos = hisPos;
                              pClosest   = pObject;
                           }
                        }

                        // We need to find the current FOV, and take the percentage of
                        //  it specified in the .dat file for this turret.  Only if the
                        //  do product is greater than this, do we allow the target to
                        //  be set...
                        //
                        float myFov   = (fov / 2.0) * data->targetableFovRatio;
                        float compCos = cos(myFov);
                        if (compCos > 0.996f)   // hack for single precision math.  It's very
                           compCos = 0.996;     // hard to get more precise answers from the dot prod.

                        if (pClosest != NULL && closestVal > compCos)
                           bullet->setTarget(pClosest);
                     }
                  }

	   				if (data->maxGunEnergy)
	   					{
	   						float e;
	   						e = energy > data->maxGunEnergy ? data->maxGunEnergy : energy;

                        float pofm = e / float(data->maxGunEnergy);

	   						bullet->setEnergy (e, pofm);

	   						energy -= e;
	   						setEnergy (energy);
	   					}

                  SimGroup *grp = NULL;
                  if(SimObject *obj = manager->findObject("MissionCleanup"))
                     grp = dynamic_cast<SimGroup*>(obj);
                  if(!manager->registerObject(bullet))
                     delete bullet;
                  else
                  {
                     if(grp)
                        grp->addObject(bullet);
                     else
                        manager->addObject(bullet);
                  }

	   				waitTime = manager->getCurrentTime() + data->reloadDelay;

	   				if (animThread)
	   					{
	   						setFireThread ();
	   						animThread->SetPosition (0.0);
	   					}
	   				
	   				fireCount++;
	   				setMaskBits (ShootingMask);
	   			}
	   	}
   } else {
      if (data && data->projectile.type == -1) {
         if (!isGhost())
            if (const char* script = scriptName("onFire"))
               Console->executef(2, script, scriptThis());
      }
      else {
         float energy = getEnergy();
         if (waitTime <= manager->getCurrentTime() && data && energy >= data->minGunEnergy && data->projectile.type != -1) {
            TMat3F muzzleTransform;
            getMuzzleTransform(0, &muzzleTransform);
            Projectile* bullet = createProjectile(data->projectile);

            if (!playerControlled && data->deflection) {
               static Random random;
               EulerF angles;
               muzzleTransform.angles (&angles);
               angles.x += (random.getFloat() - 0.5) * M_2PI * data->deflection;
               angles.z += (random.getFloat() - 0.5) * M_2PI * data->deflection;
               muzzleTransform.set (angles, muzzleTransform.p);
            } else if (playerControlled) {
               Point3F start = muzzleTransform.p;
               muzzleTransform = getEyeTransform ();
               aimedTransform (&muzzleTransform, start);
               muzzleTransform.p = start;
            }

            bullet->initProjectile (muzzleTransform, Point3F (0, 0, 0), getId());
            AssertFatal(bullet->isSustained() == true, "Error, must be sustained bullet");
            SimGroup *grp = NULL;
            if(SimObject *obj = manager->findObject("MissionCleanup"))
               grp = dynamic_cast<SimGroup*>(obj);
            if(!manager->registerObject(bullet))
               delete bullet;
            else
            {
               if(grp)
                  grp->addObject(bullet);
               else
                  manager->addObject(bullet);
            }

            if (animThread) {
               setFireThread ();
               animThread->SetPosition (0.0);
            }
            
            fireCount++;
            setMaskBits (ShootingMask);

            m_fireState  = Firing;
            m_beganState = wg->currentTime;

            m_pProjectile = bullet;
            m_pTarget     = targetPlayer;
            
            if (m_pTarget)
               deleteNotify(m_pTarget);
         }
      }
   }
}
Beispiel #20
0
void HoverVehicle::updateForces(F32 /*dt*/)
{
    PROFILE_SCOPE( HoverVehicle_UpdateForces );

    Point3F gravForce(0, 0, sHoverVehicleGravity * mRigid.mass * mGravityMod);

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

    mThrustLevel = (mForwardThrust * mDataBlock->mainThrustForce    +
                    mReverseThrust * mDataBlock->reverseThrustForce +
                    mLeftThrust    * mDataBlock->strafeThrustForce  +
                    mRightThrust   * mDataBlock->strafeThrustForce);

    Point3F thrustForce = ((Point3F( 0,  1, 0) * (mForwardThrust * mDataBlock->mainThrustForce))    +
                           (Point3F( 0, -1, 0) * (mReverseThrust * mDataBlock->reverseThrustForce)) +
                           (Point3F(-1,  0, 0) * (mLeftThrust    * mDataBlock->strafeThrustForce))  +
                           (Point3F( 1,  0, 0) * (mRightThrust   * mDataBlock->strafeThrustForce)));
    currTransform.mulV(thrustForce);
    if (mJetting)
        thrustForce *= mDataBlock->turboFactor;

    Point3F torque(0, 0, 0);
    Point3F force(0, 0, 0);

    Point3F vel = mRigid.linVelocity;
    F32 baseStabLen = getBaseStabilizerLength();
    Point3F stabExtend(0, 0, -baseStabLen);
    currTransform.mulV(stabExtend);

    StabPoint stabPoints[2];
    stabPoints[0].osPoint = Point3F((mObjBox.minExtents.x + mObjBox.maxExtents.x) * 0.5,
                                    mObjBox.maxExtents.y,
                                    (mObjBox.minExtents.z + mObjBox.maxExtents.z) * 0.5);
    stabPoints[1].osPoint = Point3F((mObjBox.minExtents.x + mObjBox.maxExtents.x) * 0.5,
                                    mObjBox.minExtents.y,
                                    (mObjBox.minExtents.z + mObjBox.maxExtents.z) * 0.5);
    U32 j, i;
    for (i = 0; i < 2; i++) {
        currTransform.mulP(stabPoints[i].osPoint, &stabPoints[i].wsPoint);
        stabPoints[i].wsExtension = stabExtend;
        stabPoints[i].extension   = baseStabLen;
        stabPoints[i].wsVelocity  = mRigid.linVelocity;
    }

    RayInfo rinfo;

    mFloating = true;
    bool reallyFloating = true;
    F32 compression[2] = { 0.0f, 0.0f };
    F32  normalMod[2]  = { 0.0f, 0.0f };
    bool normalSet[2]  = { false, false };
    Point3F normal[2];

    for (j = 0; j < 2; j++) {
        if (getContainer()->castRay(stabPoints[j].wsPoint, stabPoints[j].wsPoint + stabPoints[j].wsExtension * 2.0,
                                    TerrainObjectType |
                                    WaterObjectType, &rinfo))
        {
            reallyFloating = false;

            if (rinfo.t <= 0.5) {
                // Ok, stab is in contact with the ground, let's calc the forces...
                compression[j] = (1.0 - (rinfo.t * 2.0)) * baseStabLen;
            }
            normalSet[j] = true;
            normalMod[j] = rinfo.t < 0.5 ? 1.0 : (1.0 - ((rinfo.t - 0.5) * 2.0));

            normal[j] = rinfo.normal;
        }

        if ( pointInWater( stabPoints[j].wsPoint ) )
            compression[j] = baseStabLen;
    }

    for (j = 0; j < 2; j++) {
        if (compression[j] != 0.0) {
            mFloating = false;

            // Spring force and damping
            Point3F springForce = -stabPoints[j].wsExtension;
            springForce.normalize();
            springForce *= compression[j] * mDataBlock->stabSpringConstant;

            Point3F springDamping = -stabPoints[j].wsExtension;
            springDamping.normalize();
            springDamping *= -getMin(mDot(springDamping, stabPoints[j].wsVelocity), 0.7f) * mDataBlock->stabDampingConstant;

            force += springForce + springDamping;
        }
    }

    // Gravity
    if (reallyFloating == false)
        force += gravForce;
    else
        force += gravForce * mDataBlock->floatingGravMag;

    // Braking
    F32 vellen = mRigid.linVelocity.len();
    if (mThrottle == 0.0f &&
            mLeftThrust == 0.0f &&
            mRightThrust == 0.0f &&
            vellen != 0.0f &&
            vellen < mDataBlock->brakingActivationSpeed)
    {
        Point3F dir = mRigid.linVelocity;
        dir.normalize();
        dir.neg();
        force += dir *  mDataBlock->brakingForce;
    }

    // Gyro Drag
    torque = -mRigid.angMomentum * mDataBlock->gyroDrag;

    // Move to proper normal
    Point3F sn, r;
    currTransform.getColumn(2, &sn);
    if (normalSet[0] || normalSet[1]) {
        if (normalSet[0] && normalSet[1]) {
            F32 dot = mDot(normal[0], normal[1]);
            if (dot > 0.999) {
                // Just pick the first normal.  They're too close to call
                if ((sn - normal[0]).lenSquared() > 0.00001) {
                    mCross(sn, normal[0], &r);
                    torque += r * mDataBlock->normalForce * normalMod[0];
                }
            } else {
                Point3F rotAxis;
                mCross(normal[0], normal[1], &rotAxis);
                rotAxis.normalize();

                F32 angle = mAcos(dot) * (normalMod[0] / (normalMod[0] + normalMod[1]));
                AngAxisF aa(rotAxis, angle);
                QuatF q(aa);
                MatrixF tempMat(true);
                q.setMatrix(&tempMat);
                Point3F newNormal;
                tempMat.mulV(normal[1], &newNormal);

                if ((sn - newNormal).lenSquared() > 0.00001) {
                    mCross(sn, newNormal, &r);
                    torque += r * (mDataBlock->normalForce * ((normalMod[0] + normalMod[1]) * 0.5));
                }
            }
        } else {
            Point3F useNormal;
            F32     useMod;
            if (normalSet[0]) {
                useNormal = normal[0];
                useMod    = normalMod[0];
            } else {
                useNormal = normal[1];
                useMod    = normalMod[1];
            }

            if ((sn - useNormal).lenSquared() > 0.00001) {
                mCross(sn, useNormal, &r);
                torque += r * mDataBlock->normalForce * useMod;
            }
        }
    } else {
        if ((sn - Point3F(0, 0, 1)).lenSquared() > 0.00001) {
            mCross(sn, Point3F(0, 0, 1), &r);
            torque += r * mDataBlock->restorativeForce;
        }
    }

    Point3F sn2;
    currTransform.getColumn(0, &sn);
    currTransform.getColumn(1, &sn2);
    mCross(sn, sn2, &r);
    r.normalize();
    torque -= r * (mSteering.x * mDataBlock->steeringForce);

    currTransform.getColumn(0, &sn);
    currTransform.getColumn(2, &sn2);
    mCross(sn, sn2, &r);
    r.normalize();
    torque -= r * (mSteering.x * mDataBlock->rollForce);

    currTransform.getColumn(1, &sn);
    currTransform.getColumn(2, &sn2);
    mCross(sn, sn2, &r);
    r.normalize();
    torque -= r * (mSteering.y * mDataBlock->pitchForce);

    // Apply drag
    Point3F vDrag = mRigid.linVelocity;
    if (!mFloating) {
        vDrag.convolve(Point3F(1, 1, mDataBlock->vertFactor));
    } else {
        vDrag.convolve(Point3F(0.25, 0.25, mDataBlock->vertFactor));
    }
    force -= vDrag * mDataBlock->dragForce;

    force += mFloating ? thrustForce * mDataBlock->floatingThrustFactor : thrustForce;

    // Add in physical zone force
    force += mAppliedForce;

    // Container buoyancy & drag
    force  += Point3F(0, 0,-mBuoyancy * sHoverVehicleGravity * mRigid.mass * mGravityMod);
    force  -= mRigid.linVelocity * mDrag;
    torque -= mRigid.angMomentum * mDrag;

    mRigid.force  = force;
    mRigid.torque = torque;
}
void PlanetRenderImage::render(TSRenderContext &rc)
{
   // A simple planet culling scheme would be to dot the line of sight
   // with the vector from the camera to the planet.  This would eliminate
   // the length test of v below (after m_cross((Point3F)plane, vpNormal, &v))
   GFXSurface *gfxSurface = rc.getSurface();

   gfxSurface->setHazeSource(GFX_HAZE_NONE);
   gfxSurface->setShadeSource(GFX_SHADE_CONSTANT);
   gfxSurface->setAlphaSource(GFX_ALPHA_NONE);
	gfxSurface->setFillMode(GFX_FILL_TEXTURE);
	gfxSurface->setTransparency(FALSE);
   gfxSurface->setTexturePerspective(FALSE);

   gfxSurface->setConstantShade(1.0f);

   int textureHeight;
   gfxSurface->setTextureMap(texture);
   textureHeight = texture->height;
   
   TSCamera *camera = rc.getCamera();
  
   TS::PointArray *pointArray = rc.getPointArray();
   pointArray->reset();
   pointArray->useIntensities(false);
   pointArray->useTextures(textCoord);
   pointArray->useTextures(true);
	pointArray->setVisibility( TS::ClipMask );

   // find out how high the bitmap is at 100% as projected onto the viewport,
   // texel:pixel will be 1:1 at 640x480
   //const RectF &worldVP  = camera->getWorldViewport();
   //const float h = textureHeight*((worldVP.upperL.y - worldVP.lowerR.y)/480.0f);
   //const float sz = 0.5*distance*(h/camera->getNearDist());

   // find the position of the planet
   Point3F displacement = camera->getTCW().p;
   //displacement.z *= -(distance - visibleDistance)/visibleDistance;
   displacement.z = -displacement.z*(distance/(visibleDistance*1.5f));
   Point3F pos = position;
   pos += displacement;
 
   // find the normal to the view plane in world coords
   Point3F v0(0.0f, 1.0f, 0.0f), vpNormal;
   m_mul(v0, (RMat3F)camera->getTCW(), &vpNormal);
   vpNormal.normalize();

   // construct the plane that the camera, planet pos & celestial NP all
   // lie on
   PlaneF plane(pos, camera->getTCW().p, 
      Point3F(displacement.x, displacement.y, displacement.z + distance));

   // the cross product of the VP normal and the normal to the plane just
   // constructed is the up vector for the planet
   Point3F v;
   m_cross((Point3F)plane, vpNormal, &v);
   if (IsEqual(v.len(), 0.0f))
      // planet is directly to the right or left of camera
      return;
   v.normalize();
   
   // cross the up with the normal and we get the right vector
   Point3F u;
   m_cross(vpNormal, v, &u);
   u *= size;
   v *= size;

   TS::VertexIndexPair V[6];
   Point3F ul = pos;
   ul -= u; ul += v;
   V[0].fVertexIndex   = pointArray->addPoint(ul);
   V[0].fTextureIndex  = 0;
   Point3F ur = pos;
   ur += u; ur += v;
   V[1].fVertexIndex   = pointArray->addPoint(ur);
   V[1].fTextureIndex  = 1;
   Point3F lr = pos;
   lr += u; lr -= v;
   V[2].fVertexIndex   = pointArray->addPoint(lr);
   V[2].fTextureIndex  = 2;
   Point3F ll = pos;
   ll -= u; ll -=v;
   V[3].fVertexIndex   = pointArray->addPoint(ll);
   V[3].fTextureIndex  = 3;
	if (gfxSurface->getCaps() & GFX_DEVCAP_SUPPORTS_CONST_ALPHA)
	   gfxSurface->setZTest(GFX_NO_ZTEST);
   pointArray->drawPoly(4, V, 0);
	if (gfxSurface->getCaps() & GFX_DEVCAP_SUPPORTS_CONST_ALPHA)
	   gfxSurface->setZTest(GFX_ZTEST_AND_WRITE);
   if(lensFlare) {
      TS::TransformedVertex vx;
      camera->transformProject(pos, &vx);
      bool vis = vx.fStatus & TS::TransformedVertex::Projected;
      lensFlare->setSunPos(vis, vx.fPoint, pos);
   }
}
void BrushAdjustHeightAction::process(Selection * sel, const Gui3DMouseEvent & event, bool, Type type)
{
   if(type == Process)
      return;

   TerrainBlock *terrBlock = mTerrainEditor->getActiveTerrain();
   if ( !terrBlock )
      return;

   if(type == Begin)
   {
      mTerrainEditor->lockSelection(true);
      mTerrainEditor->getRoot()->mouseLock(mTerrainEditor);

      // the way this works is:
      // construct a plane that goes through the collision point
      // with one axis up the terrain Z, and horizontally parallel to the
      // plane of projection

      // the cross of the camera ffdv and the terrain up vector produces
      // the cross plane vector.

      // all subsequent mouse actions are collided against the plane and the deltaZ
      // from the previous position is used to delta the selection up and down.
      Point3F cameraDir;

      EditTSCtrl::smCamMatrix.getColumn(1, &cameraDir);
      terrBlock->getTransform().getColumn(2, &mTerrainUpVector);

      // ok, get the cross vector for the plane:
      Point3F planeCross;
      mCross(cameraDir, mTerrainUpVector, &planeCross);

      planeCross.normalize();
      Point3F planeNormal;

      Point3F intersectPoint;
      mTerrainEditor->collide(event, intersectPoint);

      mCross(mTerrainUpVector, planeCross, &planeNormal);
      mIntersectionPlane.set(intersectPoint, planeNormal);

      // ok, we have the intersection point...
      // project the collision point onto the up vector of the terrain

      mPreviousZ = mDot(mTerrainUpVector, intersectPoint);

      // add to undo
      // and record the starting heights
      for(U32 i = 0; i < sel->size(); i++)
      {
         mTerrainEditor->getUndoSel()->add((*sel)[i]);
         (*sel)[i].mStartHeight = (*sel)[i].mHeight;
      }
   }
   else if(type == Update)
   {
      // ok, collide the ray from the event with the intersection plane:

      Point3F intersectPoint;
      Point3F start = event.pos;
      Point3F end = start + event.vec * 1000;

      F32 t = mIntersectionPlane.intersect(start, end);

      m_point3F_interpolate( start, end, t, intersectPoint);
      F32 currentZ = mDot(mTerrainUpVector, intersectPoint);

      F32 diff = currentZ - mPreviousZ;

      for(U32 i = 0; i < sel->size(); i++)
      {
         (*sel)[i].mHeight = (*sel)[i].mStartHeight + diff * (*sel)[i].mWeight;

         // clamp it
         if((*sel)[i].mHeight < 0.f)
            (*sel)[i].mHeight = 0.f;
         if((*sel)[i].mHeight > 2047.f)
            (*sel)[i].mHeight = 2047.f;

         mTerrainEditor->setGridInfoHeight((*sel)[i]);
      }
      mTerrainEditor->scheduleGridUpdate();
   }
   else if(type == End)
   {
      mTerrainEditor->getRoot()->mouseUnlock(mTerrainEditor);
   }
}
Beispiel #23
0
void DebugDrawer::drawPolyhedronDebugInfo( const AnyPolyhedron& polyhedron, const MatrixF& transform, const Point3F& scale )
{
   Point3F center = polyhedron.getCenterPoint();
   center.convolve( scale );
   transform.mulP( center );

   // Render plane indices and normals.

   const U32 numPlanes = polyhedron.getNumPlanes();
   for( U32 i = 0; i < numPlanes; ++ i )
   {
      const AnyPolyhedron::PlaneType& plane = polyhedron.getPlanes()[ i ];

      Point3F planePos = plane.getPosition();
      planePos.convolve( scale );
      transform.mulP( planePos );

      Point3F normal = plane.getNormal();
      transform.mulV( normal );

      drawText( planePos, String::ToString( i ), ColorI::BLACK );
      drawLine( planePos, planePos + normal, ColorI::GREEN );
   }

   // Render edge indices and direction indicators.

   const U32 numEdges = polyhedron.getNumEdges();
   for( U32 i = 0; i < numEdges; ++ i )
   {
      const AnyPolyhedron::EdgeType& edge = polyhedron.getEdges()[ i ];

      Point3F v1 = polyhedron.getPoints()[ edge.vertex[ 0 ] ];
      Point3F v2 = polyhedron.getPoints()[ edge.vertex[ 1 ] ];

      v1.convolve( scale );
      v2.convolve( scale );
      transform.mulP( v1 );
      transform.mulP( v2 );

      const Point3F midPoint = v1 + ( v2 - v1 ) / 2.f;

      drawText( midPoint, String::ToString( "%i (%i, %i)", i, edge.face[ 0 ], edge.face[ 1 ] ), ColorI::WHITE );

      // Push out the midpoint away from the center to place the direction indicator.

      Point3F pushDir = midPoint - center;
      pushDir.normalize();
      const Point3F dirPoint = midPoint + pushDir;
      const Point3F lineDir = ( v2 - v1 ) / 2.f;

      drawLine( dirPoint, dirPoint + lineDir, ColorI::RED );
   }

   // Render point indices and coordinates.

   const U32 numPoints = polyhedron.getNumPoints();
   for( U32 i = 0; i < numPoints; ++ i )
   {
      Point3F p = polyhedron.getPoints()[ i ];

      p.convolve( scale );
      transform.mulP( p );

      drawText( p, String::ToString( "%i: (%.2f, %.2f, %.2f)", i, p.x, p.y, p.z ), ColorF::WHITE );
   }
}
bool Frustum::bakeProjectionOffset()
{
   // Nothing to bake if ortho
   if( mIsOrtho )
      return false;

   // Nothing to bake if no offset
   if( mProjectionOffset.isZero() )
      return false;

   // Near plane points in camera space
   Point3F np[4];
   np[0].set( mNearLeft, mNearDist, mNearTop );       // NearTopLeft
   np[1].set( mNearRight, mNearDist, mNearTop );      // NearTopRight
   np[2].set( mNearLeft, mNearDist, mNearBottom );    // NearBottomLeft
   np[3].set( mNearRight, mNearDist, mNearBottom );   // NearBottomRight

   // Generate the near plane
   PlaneF nearPlane( np[0], np[1], np[3] );

   // Far plane points in camera space
   const F32 farOverNear = mFarDist / mNearDist;
   Point3F fp0( mNearLeft * farOverNear, mFarDist, mNearTop * farOverNear );     // FarTopLeft
   Point3F fp1( mNearRight * farOverNear, mFarDist, mNearTop * farOverNear );    // FarTopRight
   Point3F fp2( mNearLeft * farOverNear, mFarDist, mNearBottom * farOverNear );  // FarBottomLeft
   Point3F fp3( mNearRight * farOverNear, mFarDist, mNearBottom * farOverNear ); // FarBottomRight

   // Generate the far plane
   PlaneF farPlane( fp0, fp1, fp3 );

   // The offset camera point
   Point3F offsetCamera( mProjectionOffset.x, 0.0f, mProjectionOffset.y );

   // The near plane point we'll be using for our calculations below
   U32 nIndex = 0;
   if( mProjectionOffset.x < 0.0 )
   {
      // Offset to the left so we'll need to use the near plane point on the right
      nIndex = 1;
   }
   if( mProjectionOffset.y > 0.0 )
   {
      // Offset to the top so we'll need to use the near plane point at the bottom
      nIndex += 2;
   }

   // Begin by calculating the offset point on the far plane as it goes
   // from the offset camera to the edge of the near plane.
   Point3F farPoint;
   Point3F fdir = np[nIndex] - offsetCamera;
   fdir.normalize();
   if( farPlane.intersect(offsetCamera, fdir, &farPoint) )
   {
      // Calculate the new near plane edge from the non-offset camera position
      // to the far plane point from above.
      Point3F nearPoint;
      Point3F ndir = farPoint;
      ndir.normalize();
      if( nearPlane.intersect( Point3F::Zero, ndir, &nearPoint) )
      {
         // Handle a x offset
         if( mProjectionOffset.x < 0.0 )
         {
            // The new near plane right side
            mNearRight = nearPoint.x;
         }
         else if( mProjectionOffset.x > 0.0 )
         {
            // The new near plane left side
            mNearLeft = nearPoint.x;
         }

         // Handle a y offset
         if( mProjectionOffset.y < 0.0 )
         {
            // The new near plane top side
            mNearTop = nearPoint.y;
         }
         else if( mProjectionOffset.y > 0.0 )
         {
            // The new near plane bottom side
            mNearBottom = nearPoint.y;
         }
      }
   }

   mDirty = true;

   // Indicate that we've modified the frustum
   return true;
}
Beispiel #25
0
void Projectile::emitParticles(const Point3F& from, const Point3F& to, const Point3F& vel, const U32 ms)
{
   if ( mHasExploded )
      return;

   Point3F axis = -vel;

   if( axis.isZero() )
      axis.set( 0.0, 0.0, 1.0 );
   else
      axis.normalize();

   bool fromWater = pointInWater(from);
   bool toWater   = pointInWater(to);

   if (!fromWater && !toWater && bool(mParticleEmitter))                                        // not in water
      mParticleEmitter->emitParticles(from, to, axis, vel, ms);
   else if (fromWater && toWater && bool(mParticleWaterEmitter))                                // in water
      mParticleWaterEmitter->emitParticles(from, to, axis, vel, ms);
   else if (!fromWater && toWater && mDataBlock->splash)     // entering water
   {
      // cast the ray to get the surface point of the water
      RayInfo rInfo;
      if (gClientContainer.castRay(from, to, WaterObjectType, &rInfo))
      {
         MatrixF trans = getTransform();
         trans.setPosition(rInfo.point);

         Splash *splash = new Splash();
         splash->onNewDataBlock(mDataBlock->splash, false);
         splash->setTransform(trans);
         splash->setInitialState(trans.getPosition(), Point3F(0.0, 0.0, 1.0));
         if (!splash->registerObject())
         {
            delete splash;
            splash = NULL;
         }

         // create an emitter for the particles out of water and the particles in water
         if (mParticleEmitter)
            mParticleEmitter->emitParticles(from, rInfo.point, axis, vel, ms);

         if (mParticleWaterEmitter)
            mParticleWaterEmitter->emitParticles(rInfo.point, to, axis, vel, ms);
      }
   }
   else if (fromWater && !toWater && mDataBlock->splash)     // leaving water
   {
      // cast the ray in the opposite direction since that point is out of the water, otherwise
      //  we hit water immediately and wont get the appropriate surface point
      RayInfo rInfo;
      if (gClientContainer.castRay(to, from, WaterObjectType, &rInfo))
      {
         MatrixF trans = getTransform();
         trans.setPosition(rInfo.point);

         Splash *splash = new Splash();
         splash->onNewDataBlock(mDataBlock->splash,false);
         splash->setTransform(trans);
         splash->setInitialState(trans.getPosition(), Point3F(0.0, 0.0, 1.0));
         if (!splash->registerObject())
         {
            delete splash;
            splash = NULL;
         }

         // create an emitter for the particles out of water and the particles in water
         if (mParticleEmitter)
            mParticleEmitter->emitParticles(rInfo.point, to, axis, vel, ms);

         if (mParticleWaterEmitter)
            mParticleWaterEmitter->emitParticles(from, rInfo.point, axis, vel, ms);
      }
   }
}