Example #1
0
void Spring::updateForce(RigidBody* body, real duration)
{
    // Calculate the two ends in world space
    Vector3 lws = body->getPointInWorldSpace(connectionPoint);
    Vector3 ows = other->getPointInWorldSpace(otherConnectionPoint);

    // Calculate the vector of the spring
    Vector3 force = lws - ows;

    // Calculate the magnitude of the force
    real magnitude = force.magnitude(); // @TODO: ask massimo if this is correct
    //magnitude = real_abs(magnitude - restLength);
	magnitude = magnitude - restLength;
    magnitude *= springConstant;

    // Calculate the final force and apply it
    force.normalise();
    force *= -magnitude;
    body->addForceAtPoint(force, lws);
}
Example #2
0
float TerUtil::GetAngleAt(Terrain* terrain, float x, float z, float s)
{
	//float* hf = terrain ? terrain->getHeightData() : sc->td.hfHeight;
	//Real t = sc->td.fTriangleSize * 2.f;
	//Vector3 vx(t, hf[a+1] - hf[a-1], 0);  // x+1 - x-1
	//Vector3 vz(0, hf[a+wx] - hf[a-wx], t);	// z+1 - z-1
	//Vector3 norm = -vx.crossProduct(vz);  norm.normalise();
	//Real ang = Math::ACos(norm.y).valueDegrees();

	Real y0=0;
	Vector3 vx(x-s, y0, z), vz(x, y0, z-s);
	Vector3 vX(x+s, y0, z), vZ(x, y0, z+s);
	vx.y = terrain->getHeightAtWorldPosition(vx);  vX.y = terrain->getHeightAtWorldPosition(vX);
	vz.y = terrain->getHeightAtWorldPosition(vz);  vZ.y = terrain->getHeightAtWorldPosition(vZ);
	Vector3 v_x = vx-vX;  //v_x.normalise();
	Vector3 v_z = vz-vZ;  //v_z.normalise();
	Vector3 n = -v_x.crossProduct(v_z);  n.normalise();
	Real a = Math::ACos(n.y).valueDegrees();
	return a;
}
Example #3
0
void Pod::update(float elapsed)
{
    if (glowNode)
    {
        glowNode->setOrientation(head->_getDerivedOrientation());
    }
    if (indicatorNode)
    {
        indicatorNode->roll(Degree(elapsed));;
    }
    if (moveSpeed != 0.0)
    {
        Vector3 dist = dest - entirePod->getPosition();
    
        Vector3 norm = dist;
        norm.normalise();
        Vector3 delta = dist * moveSpeed * elapsed;
        
        //	if (delta.length() > dist.length())
        if (delta.x * delta.x + delta.y * delta.y + delta.z * delta.z >
            dist.x * dist.x + dist.y * dist.y + dist.z * dist.z)
            delta = dist;
    
        move(delta);
    }
    if (rotateSpeed != Vector3::ZERO)
    {
        head->yaw(Degree(rotateSpeed.x));
        head->pitch(Degree(rotateSpeed.y));
        head->roll(Degree(rotateSpeed.z));
    }
    
    if( bPFXNode ) {
        bPFX->getEmitter(0)->setParameter("width",Util::toStringFloat(bPFXwidth));
        bPFX->getEmitter(0)->setColour(ColourValue(bPFXcolor,1.0f,1.0f));
        if( bPFXwidth+0.75f < 4.0f ) bPFXwidth += 0.75f;
        else bPFXwidth = 4.0f;
        if( bPFXcolor-0.05f > 0.0f ) bPFXcolor -= 0.05f;
        else bPFXcolor = 0.0f;
    }
}
Example #4
0
bool CollisionTools::collidesWithEntity(const Vector3& fromPoint, const Vector3& toPoint, const float collisionRadius, const float rayHeightLevel, const uint32 queryMask)
{
	Vector3 fromPointAdj(fromPoint.x, fromPoint.y + rayHeightLevel, fromPoint.z);
	Vector3 toPointAdj(toPoint.x, toPoint.y + rayHeightLevel, toPoint.z);	
	Vector3 normal = toPointAdj - fromPointAdj;
	float distToDest = normal.normalise();

	Vector3 myResult(0, 0, 0);
	Ogre::Entity* myObject = NULL;
	float distToColl = 0.0f;

	if (raycastFromPoint(fromPointAdj, normal, myResult, (unsigned long&)myObject, distToColl, queryMask))
	{
		distToColl -= collisionRadius; 
		return (distToColl <= distToDest);
	}
	else
	{
		return false;
	}
}
	//-----------------------------------------------------------------------
	void AlignAffector::_affect(ParticleTechnique* particleTechnique, Particle* particle, Real timeElapsed)
	{
		if (particle->particleType == Particle::PT_VISUAL)
		{
			// Set the orientation towards the previous particle, but rotation is undetermined.
			VisualParticle* visualParticle = static_cast<VisualParticle*>(particle);

			// Get difference
			Vector3 diff = (mPreviousParticle->position - particle->position);
			if (mResize)
			{
				visualParticle->setOwnDimensions (visualParticle->width, diff.length(), visualParticle->depth);
			}
			diff.normalise();
			visualParticle->orientation.x = diff.x;
			visualParticle->orientation.y = diff.y;
			visualParticle->orientation.z = diff.z;
		}

		mPreviousParticle = particle;
	}
Example #6
0
	void CArrayGraphics::setTransform(){
		
		
		//en un futuro simplemente se orientara la entidad en el 3ds o similar. 

		// Obtengo la camara para posicionarla en esta posicion pero algo modificada
		Graphics::CCamera* camera = Graphics::CServer::getSingletonPtr()->getActiveScene()->getCamera();
		Vector3 direction = /*camera->getTargetCameraPosition() -*/ camera->getCameraPosition();
		
		direction.normalise();
		//Vector3 posicionModificada = camera->getCameraPosition() - Vector3(0,2.5,0) + ((8.0f) * direction);
		Vector3 posicionModificada = camera->getCameraPosition() + ((8.0f) * direction);
		
		//Aqui establezco la rotacion (En un futuro se rotara el modelo)
		Quaternion yaw,pitch,roll;
		Math::rotate(Vector3::UNIT_Y,Ogre::Radian(_graphicsEntities[_currentWeapon].yaw),yaw);
		Math::rotate(Vector3::UNIT_X,Ogre::Radian(_graphicsEntities[_currentWeapon].pitch),pitch);
		Math::rotate(Vector3::UNIT_Z,Ogre::Radian(_graphicsEntities[_currentWeapon].roll),roll);
		_graphicsEntities[_currentWeapon]._graphicsEntity->setTransform(posicionModificada,yaw*pitch*roll);

	}// setTransform
Example #7
0
	Vector4* SnowTerrain::convertNormalsToFloats(PixelBox* terrainNormals, bool compressed)
	{
		const size_t srcPixelSize = PixelUtil::getNumElemBytes(terrainNormals->format);
		const size_t dstPixelSize = PixelUtil::getNumElemBytes(PF_FLOAT32_RGBA);
		size_t w,h,d;
		w = terrainNormals->getWidth();
		h = terrainNormals->getHeight();
		d = terrainNormals->getDepth();

		assert(terrainNormals->getWidth() == mTerrainSize);
		size_t terrainNormalSize = terrainNormals->getWidth()*terrainNormals->getHeight();
		Vector4* terrainNormalDataCorrected = OGRE_ALLOC_T(Vector4, terrainNormalSize, MEMCATEGORY_GENERAL);

		size_t i = 0; size_t j = 0;
		uint8* pixelsBuffer = static_cast<uint8*>(terrainNormals->data);
		for(; i < terrainNormalSize * srcPixelSize && j < terrainNormalSize * sizeof(Vector4); i+=srcPixelSize)
		{
			uint8 r,g,b,a;
			PixelUtil::unpackColour(&r,&g,&b,&a, terrainNormals->format, static_cast<void*>(&pixelsBuffer[i]));
			float fr,fg,fb;
			if(compressed)
			{			
				//(signed) float packed/compressed into uint8, unpack
				fr = ((float)(r))/(0.5f * 255.0f) - 1.0f;
				fg = ((float)(g))/(0.5f * 255.0f) - 1.0f;
				fb = ((float)(b))/(0.5f * 255.0f) - 1.0f;
			}
			else
			{
				fr = ((float)(r))/255.0f;
				fg = ((float)(g))/255.0f;
				fb = ((float)(b))/255.0f;
			}
			Vector3 v = Vector3(fr, fg, fb);
			v.normalise();
			terrainNormalDataCorrected[j++] = Vector4(v);
		}

		return terrainNormalDataCorrected;
	}
Example #8
0
void 
utils3D::rotateVecByQuat(Vector3& vec, const Vector3& axis, const float angle)
{
   float mag = vec.magnitude();
   vec.normalise();

   Quaternion vq(0, vec.x, vec.y, vec.z);
   Quaternion q;

	// HAUKAP - put this in quaternion class as another constructor
   Quaternion rot( cos(angle/2), axis.x * sin(angle/2), axis.y * sin(angle/2), axis.z * sin(angle/2) );
   q = rot * q;
   q.normalise();

   Quaternion qp(q.r, -q.x, -q.y, -q.z);
   Quaternion vp = qp * vq * q;

   vec.x = vp.x * mag;
   vec.y = vp.y * mag;
   vec.z = vp.z * mag;
   return;
}
void GameInputHandler::handleMouse(float timeSinceLastFrame)
{
	const OIS::MouseState &ms = inputManager->mouseState;

	static float delay = 0.0f;
	delay -= timeSinceLastFrame;
	
	if (game.getSubState() != SUBST_EDITOR)
	{
		windowManager.showCursor(game.getSubState() == SUBST_GAMESTART);
		return;
	}

	if (!inputManager->isMouseDown(OIS::MB_Middle))
	{
		windowManager.showCursor(true);

		// Edit geometry with left and right clicks
		CEGUI::TabControl* tabWindow = (CEGUI::TabControl*)CEGUI::WindowManager::getSingleton().getWindow("EditorTabControl");
		if (inputManager->processMouse && (tabWindow->getSelectedTabIndex() == 1) && (delay <= 0) && (inputManager->isMouseDown(OIS::MB_Left) || inputManager->isMouseDown(OIS::MB_Right)))
		{
			Ray r = camera->getCameraToViewportRay(CEGUI::MouseCursor::getSingleton().getPosition().d_x / settings.resolution_Width,
														 CEGUI::MouseCursor::getSingleton().getPosition().d_y / settings.resolution_Height);
			Vector3 pos = camera->getDerivedPosition();
			Vector3 dir = r.getDirection();
			dir.normalise();

			game.editLevel(inputManager->isMouseDown(OIS::MB_Left), pos, dir);
			delay = 0.12f;
		}
	}
	else
	{
		windowManager.showCursor(false);

		rotX = Degree(-ms.X.rel * settings.mouseSensitivity);
		rotY = Degree(-ms.Y.rel * settings.mouseSensitivity);
	}
}
void ObjectControl::update()
{
	using namespace Ogre;

	if( widget && node )
	{
		Vector3 objPos = node->_getWorldAABB().getCenter();
		mSceneMgr->getRootSceneNode()->removeChild( widget );
		mSceneMgr->getRootSceneNode()->addChild( widget );

		Vector3 raytoCam = objPos-mCamera->getRealPosition();
		raytoCam.normalise();
		raytoCam *= 20;

		widget->setPosition( mCamera->getRealPosition()+raytoCam );
		widget->setVisible( true );

		planeXNode->setPosition( objPos );
		planeYNode->setPosition( objPos );
		planeZNode->setPosition( objPos );
	}
}
// Draw objects to help visually debug the engine (collision points, normals, etc...)
void RenderingDemo::drawPhysicsDebugObjects()
{
	std::vector<PhysicsEngine::Collision> *collisionList = physicsEngine.getCollisionList();

	for (unsigned int collisionIndex = 0; collisionIndex < collisionList->size(); collisionIndex++)
	{
		// Render the collision position
		Vector3 collisionPosition = (*collisionList)[collisionIndex].contactPoint;
		Rendering::drawSphere(collisionPosition, Vector3(1.0f, 1.0f, 0.0f), 0.3);	

		// Now render the collision normal
		Vector3 collisionNormal = (*collisionList)[collisionIndex].contactNormal;
		collisionNormal.normalise();
		Vector3 rotationAxis = collisionNormal.vectorProduct(Vector3(1.0f, 0.0f, 0.0f));
		float rotationAngle = acosf(collisionNormal.scalarProduct(Vector3(1.0f, 0.0f, 0.0f)));
		collisionPosition = collisionPosition + (collisionNormal * .3f);

		// Create a transformation matrix corresponding to the collision normal's rotation and position
		Quaternion collisionRotation(cosf(rotationAngle / 2.0f), rotationAxis[0] * sinf(rotationAngle / 2.0f), rotationAxis[1] * sinf(rotationAngle / 2.0f), rotationAxis[2] * sinf(rotationAngle / 2.0f));
		Matrix4 transformationMatrix;
		PhysicsEngine::RigidBody::_calculateTransformMatrix(transformationMatrix, collisionPosition, collisionRotation);
		GLfloat mat[16];
		transformationMatrix.fillGLArray(mat);
		
		Rendering::drawBox(mat, Vector3(1.0f, 1.0f, 1.0f), Vector3(0.5f, 0.05f, 0.05f));

		// Print out the collision info to the console
		std::cout << "Collision Position:" << std::endl;
		std::cout << collisionPosition[0] << " " << collisionPosition[1] << " " << collisionPosition[2] << std::endl;
		// Print out the collision normals to the console
		std::cout << "Collision Normal:" << std::endl;
		std::cout << collisionNormal[0] << " " << collisionNormal[1] << " " << collisionNormal[2] << std::endl;
		std::cout << "Rotation axis:" << std::endl;
		std::cout << rotationAxis[0] << " " << rotationAxis[1] << " " << rotationAxis[2] << std::endl;
		std::cout << "Rotation angle:" << std::endl;
		std::cout << rotationAngle << std::endl;
	}
}
Example #12
0
void Water::ShowWave(Vector3 refpos)
{
    if (!m_waterplane_vert_buf_local)
        return;

    float xScaled = m_map_size.x * m_waterplane_mesh_scale;
    float zScaled = m_map_size.z * m_waterplane_mesh_scale;

    for (int pz = 0; pz < WAVEREZ + 1; pz++)
    {
        for (int px = 0; px < WAVEREZ + 1; px++)
        {
            m_waterplane_vert_buf_local[(pz * (WAVEREZ + 1) + px) * 8 + 1] = CalcWavesHeight(refpos + Vector3(xScaled * 0.5 - (float)px * xScaled / WAVEREZ, 0, (float)pz * zScaled / WAVEREZ - zScaled * 0.5)) - m_water_height;
        }
    }

    //normals
    for (int pz = 0; pz < WAVEREZ + 1; pz++)
    {
        for (int px = 0; px < WAVEREZ + 1; px++)
        {
            int left = std::max(0, px - 1);
            int right = std::min(px + 1, WAVEREZ);
            int up = std::max(0, pz - 1);
            int down = std::min(pz + 1, WAVEREZ);

            Vector3 normal = (Vector3(m_waterplane_vert_buf_local + ((pz * (WAVEREZ + 1) + left) * 8)) - Vector3(m_waterplane_vert_buf_local + ((pz * (WAVEREZ + 1) + right) * 8))).crossProduct(Vector3(m_waterplane_vert_buf_local + ((up * (WAVEREZ + 1) + px) * 8)) - Vector3(m_waterplane_vert_buf_local + ((down * (WAVEREZ + 1) + px) * 8)));
            normal.normalise();

            m_waterplane_vert_buf_local[(pz * (WAVEREZ + 1) + px) * 8 + 3] = normal.x;
            m_waterplane_vert_buf_local[(pz * (WAVEREZ + 1) + px) * 8 + 4] = normal.y;
            m_waterplane_vert_buf_local[(pz * (WAVEREZ + 1) + px) * 8 + 5] = normal.z;
        }
    }

    m_waterplane_vert_buf->writeData(0, (WAVEREZ + 1) * (WAVEREZ + 1) * 32, m_waterplane_vert_buf_local, true);
}
Example #13
0
Missile* Player::fireMissile()
{
	// 총알 생성 //
	Missile *missile = new Missile(mSceneMgr);

	// 총알의 발사 방향 //
	Vector3 direction = getDirection();
	direction.normalise();
	btVector3 velocity = btVector3(direction.x, direction.y, direction.z) * 5000;

	// 총알의 생성 위치 //
	Vector3 Rotation = mPlayerNode->getPosition() - Vector3(0, 3, 0);

	missile->makeMissile( Rotation );
	missile->setVelocity( velocity );

	mPhysicsWorld->addObject( missile->getMissilePhysics() );

	// 불빛 // 
	mFireFlash->create( mWeaponNode, mWeaponNode->getPosition() + Vector3(5, -14, 38));

	mMissileTimer.reset();
	return missile;
}	
Example #14
0
  Vector3 TerrainInfo::getNormalAt(float x, float z) const
  {
    int flip = 1;
    Vector3 here (x, getHeightAt(x, z), z);
    Vector3 left (x-1, getHeightAt(x-1, z), z);
    Vector3 down (x, getHeightAt(x, z+1), z+1);
    if (left.x < 0.0)
    {
      flip *= -1;
      left = Vector3(x+1, getHeightAt(x+1, z), z);
    }
    if (down.z >= mOffset.z + mScale.z*(mHeight-1))
    {
      flip *= -1;
      down = Vector3(x, getHeightAt(x, z-1), z-1);
    }
    left -= here;
    down -= here;

    Vector3 norm = flip * left.crossProduct(down);
    norm.normalise();

    return norm;
  }
Matrix4 Matrix4::buildViewMatrix(const Vector3 &from, const Vector3 &lookingAt, const Vector3 up) {
    Matrix4 r;
    r.setPositionVector(Vector3(-from.x, -from.y, -from.z));
    Matrix4 m;
    Vector3 f = (lookingAt - from);
    f.normalise();

    Vector3 s = Vector3::cross(f, up);
    Vector3 u = Vector3::cross(s, f);

    m.values[0] = s.x;
    m.values[4] = s.y;
    m.values[8] = s.z;

    m.values[1] = u.x;
    m.values[5] = u.y;
    m.values[9] = u.z;

    m.values[2] = -f.x;
    m.values[6] = -f.y;
    m.values[10] = -f.z;

    return m * r;
}
Example #16
0
void Water::showWave(Vector3 refpos)
{
	if (!wbuffer) return;

	float xScaled = mapSize.x * mScale;
	float zScaled = mapSize.z * mScale;

	for (int pz=0; pz<WAVEREZ+1; pz++)
	{
		for (int px=0; px<WAVEREZ+1; px++)
		{
			wbuffer[(pz*(WAVEREZ+1)+px)*8+1] = getHeightWaves(refpos + Vector3(xScaled*0.5-(float)px * xScaled / WAVEREZ, 0, (float)pz * zScaled / WAVEREZ - zScaled * 0.5)) - wHeight;
		}
	}

	//normals
	for (int pz=0; pz<WAVEREZ+1; pz++)
	{
		for (int px=0; px<WAVEREZ+1; px++)
		{
			int left  = std::max(0, px-1);
			int right = std::min(px+1, WAVEREZ);
			int up    = std::max(0, pz-1);
			int down  = std::min(pz+1, WAVEREZ);

			Vector3 normal = (Vector3(wbuffer+((pz*(WAVEREZ+1)+left)*8))-Vector3(wbuffer+((pz*(WAVEREZ+1)+right)*8))).crossProduct(Vector3(wbuffer+((up*(WAVEREZ+1)+px)*8))-Vector3(wbuffer+((down*(WAVEREZ+1)+px)*8)));
			normal.normalise();

			wbuffer[(pz*(WAVEREZ+1)+px)*8+3] = normal.x;
			wbuffer[(pz*(WAVEREZ+1)+px)*8+4] = normal.y;
			wbuffer[(pz*(WAVEREZ+1)+px)*8+5] = normal.z;
		}
	}

	wbuf->writeData(0, (WAVEREZ+1)*(WAVEREZ+1)*32, wbuffer, true);
}
unsigned CollisionDetector::boxAndBox(
    const CollisionBox &one,
    const CollisionBox &two,
    CollisionData *data
    )
{
    //if (!IntersectionTests::boxAndBox(one, two)) return 0;

    // Find the vector between the two centres
    Vector3 toCentre = two.getAxis(3) - one.getAxis(3);

    // We start assuming there is no contact
    real pen = REAL_MAX;
    unsigned best = 0xffffff;

    // Now we check each axes, returning if it gives us
    // a separating axis, and keeping track of the axis with
    // the smallest penetration otherwise.
    CHECK_OVERLAP(one.getAxis(0), 0);
    CHECK_OVERLAP(one.getAxis(1), 1);
    CHECK_OVERLAP(one.getAxis(2), 2);

    CHECK_OVERLAP(two.getAxis(0), 3);
    CHECK_OVERLAP(two.getAxis(1), 4);
    CHECK_OVERLAP(two.getAxis(2), 5);

    // Store the best axis-major, in case we run into almost
    // parallel edge collisions later
    unsigned bestSingleAxis = best;

    CHECK_OVERLAP(one.getAxis(0) % two.getAxis(0), 6);
    CHECK_OVERLAP(one.getAxis(0) % two.getAxis(1), 7);
    CHECK_OVERLAP(one.getAxis(0) % two.getAxis(2), 8);
    CHECK_OVERLAP(one.getAxis(1) % two.getAxis(0), 9);
    CHECK_OVERLAP(one.getAxis(1) % two.getAxis(1), 10);
    CHECK_OVERLAP(one.getAxis(1) % two.getAxis(2), 11);
    CHECK_OVERLAP(one.getAxis(2) % two.getAxis(0), 12);
    CHECK_OVERLAP(one.getAxis(2) % two.getAxis(1), 13);
    CHECK_OVERLAP(one.getAxis(2) % two.getAxis(2), 14);

    // Make sure we've got a result.
    assert(best != 0xffffff);

    // We now know there's a collision, and we know which
    // of the axes gave the smallest penetration. We now
    // can deal with it in different ways depending on
    // the case.
    if (best < 3)
    {
        // We've got a vertex of box two on a face of box one.
        fillPointFaceBoxBox(one, two, toCentre, data, best, pen);
        data->addContacts(1);
        return 1;
    }
    else if (best < 6)
    {
        // We've got a vertex of box one on a face of box two.
        // We use the same algorithm as above, but swap around
        // one and two (and therefore also the vector between their
        // centres).
        fillPointFaceBoxBox(two, one, toCentre*-1.0f, data, best-3, pen);
        data->addContacts(1);
        return 1;
    }
    else
    {
        // We've got an edge-edge contact. Find out which axes
        best -= 6;
        unsigned oneAxisIndex = best / 3;
        unsigned twoAxisIndex = best % 3;
        Vector3 oneAxis = one.getAxis(oneAxisIndex);
        Vector3 twoAxis = two.getAxis(twoAxisIndex);
        Vector3 axis = oneAxis % twoAxis;
        axis.normalise();

        // The axis should point from box one to box two.
        if (axis * toCentre > 0) axis = axis * -1.0f;

        // We have the axes, but not the edges: each axis has 4 edges parallel
        // to it, we need to find which of the 4 for each object. We do
        // that by finding the point in the centre of the edge. We know
        // its component in the direction of the box's collision axis is zero
        // (its a mid-point) and we determine which of the extremes in each
        // of the other axes is closest.
        Vector3 ptOnOneEdge = one.halfSize;
        Vector3 ptOnTwoEdge = two.halfSize;
        for (unsigned i = 0; i < 3; i++)
        {
            if (i == oneAxisIndex) ptOnOneEdge[i] = 0;
            else if (one.getAxis(i) * axis > 0) ptOnOneEdge[i] = -ptOnOneEdge[i];

            if (i == twoAxisIndex) ptOnTwoEdge[i] = 0;
            else if (two.getAxis(i) * axis < 0) ptOnTwoEdge[i] = -ptOnTwoEdge[i];
        }

        // Move them into world coordinates (they are already oriented
        // correctly, since they have been derived from the axes).
        ptOnOneEdge = one.transform * ptOnOneEdge;
        ptOnTwoEdge = two.transform * ptOnTwoEdge;

        // So we have a point and a direction for the colliding edges.
        // We need to find out point of closest approach of the two
        // line-segments.
        Vector3 vertex = contactPoint(
            ptOnOneEdge, oneAxis, one.halfSize[oneAxisIndex],
            ptOnTwoEdge, twoAxis, two.halfSize[twoAxisIndex],
            bestSingleAxis > 2
            );

        // We can fill the contact.
        Contact* contact = data->contacts;

        contact->penetration = pen;
        contact->contactNormal = axis;
        contact->contactPoint = vertex;
        contact->setBodyData(one.body, two.body,
            data->friction, data->restitution);
        data->addContacts(1);
        return 1;
    }
    return 0;
}
    /// Implements the plane optimal shadow camera setup algorithm
    void PlaneOptimalShadowCameraSetup::getShadowCamera (const SceneManager *sm, const Camera *cam,
        const Viewport *vp, const Light *light, Camera *texCam, size_t iteration) const
    {
        // get the plane transformed by the parent node(s)
        // Also, make sure the plane is normalized
        Plane worldPlane = mPlane->_getDerivedPlane();
        worldPlane.normalise();

        // get camera's projection matrix
        Matrix4 camProjection = cam->getProjectionMatrix() * cam->getViewMatrix();

        // get the world points to constrain
        vector<Vector4>::type vhull;
        cam->forwardIntersect(worldPlane, &vhull);
        if (vhull.size() < 4)
            return;

        // make sure the last point is a finite point (not point at infinity)
        if (vhull[3].w == 0.0)
        {
            int finiteIndex = -1;
            for (uint loopIndex = 0; loopIndex < vhull.size(); loopIndex++)
            {
                if (vhull[loopIndex].w != 0.0)
                {
                    finiteIndex = loopIndex;
                    break;
                }
            }
            if (finiteIndex == -1)
            {
                // there are no finite points, which means camera doesn't see plane of interest.
                // so we don't care what the shadow map matrix is
                // We'll map points off the shadow map so they aren't even stored
                Matrix4 crazyMat(0.0, 0.0, 0.0, 5.0,
                                 0.0, 0.0, 0.0, 5.0,
                                 0.0, 0.0, 0.0, 5.0,
                                 0.0, 0.0, 0.0, 1.0);
                texCam->setCustomViewMatrix(true, Matrix4::IDENTITY);
                texCam->setCustomProjectionMatrix(true, crazyMat);
                return;
            }
            // swap finite point to last point
            std::swap(vhull[3], vhull[finiteIndex]);
        }
        vhull.resize(4);

        // get the post-projective coordinate constraints
        vector<Vector2>::type constraint;
        for (int i=0; i<4; i++)
        {
            Vector4 postProjPt = camProjection * vhull[i];
            postProjPt *= 1.0 / postProjPt.w;
            constraint.push_back(Vector2(postProjPt.x, postProjPt.y));
        }

        // perturb one point so we don't have coplanarity
        const Vector4& pinhole = light->getAs4DVector();
        const Vector4& oldPt = vhull.back();
        Vector4 newPt;
        if (pinhole.w == 0)
        {
            // It's directional light
            static const Real NEAR_SCALE = 100.0;
            newPt = oldPt + (pinhole * (cam->getNearClipDistance() * NEAR_SCALE));
        }
        else
        {
            // It's point or spotlight
            Vector4 displacement = oldPt - pinhole;
            Vector3 displace3    = Vector3(displacement.x, displacement.y, displacement.z);
            Real dotProd = fabs(displace3.dotProduct(worldPlane.normal));
            static const Real NEAR_FACTOR = 0.05;
            newPt = pinhole + (displacement * (cam->getNearClipDistance() * NEAR_FACTOR / dotProd));
        }
        vhull.back() = newPt;

        // solve for the matrix that stabilizes the plane
        Matrix4 customMatrix = computeConstrainedProjection(pinhole, vhull, constraint);

        if (pinhole.w == 0)
        {
            // TODO: factor into view and projection pieces.
            // Note: In fact, it's unnecessary to factor into view and projection pieces,
            // but if we do, we will more according with academic requirement :)
            texCam->setCustomViewMatrix(true, Matrix4::IDENTITY);
            texCam->setCustomProjectionMatrix(true, customMatrix);
            return;
        }

        Vector3 tempPos = Vector3(pinhole.x, pinhole.y, pinhole.z);

        // factor into view and projection pieces
        Matrix4    translation(1.0, 0.0, 0.0,  tempPos.x,
            0.0, 1.0, 0.0,  tempPos.y,
            0.0, 0.0, 1.0,  tempPos.z,
            0.0, 0.0, 0.0,  1.0);
        Matrix4 invTranslation(1.0, 0.0, 0.0, -tempPos.x,
            0.0, 1.0, 0.0, -tempPos.y,
            0.0, 0.0, 1.0, -tempPos.z,
            0.0, 0.0, 0.0,  1.0);
        Matrix4 tempMatrix = customMatrix * translation;
        Vector3 zRow(-tempMatrix[3][0], -tempMatrix[3][1], -tempMatrix[3][2]);
        zRow.normalise();
        Vector3 up;
        if (zRow.y == 1.0)
            up = Vector3(1,0,0);
        else
            up = Vector3(0,1,0);
        Vector3 xDir = up.crossProduct(zRow);
        xDir.normalise();
        up = zRow.crossProduct(xDir);
        Matrix4 rotation(xDir.x, up.x, zRow.x, 0.0,
            xDir.y, up.y, zRow.y, 0.0,
            xDir.z, up.z, zRow.z, 0.0,
            0.0,  0.0,    0.0, 1.0 );
        Matrix4 customProj = tempMatrix * rotation;
        Matrix4 customView = rotation.transpose() * invTranslation;
        // note: now customProj * (0,0,0,1)^t = (0, 0, k, 0)^t for k some constant
        // note: also customProj's 4th row is (0, 0, c, 0) for some negative c.


        // set the shadow map camera
        texCam->setCustomViewMatrix(true, customView);
        texCam->setCustomProjectionMatrix(true, customProj);
    }
void AIInConeAttackStrategy::Step(unsigned timeMs)
{        
    IScenable *scen = Parent->GetScenable();
	
	if (TargetID<0)
	{		
		return;
	}
	if (TargetID==0)
	{
		if (Owner)
		{
			TargetID = Owner->SelectTargetID();			
		}
		if (TargetID<=0)
		{
			TargetID=-1;
			IEquipped *eq = Parent->GetEquipped();
			eq->SetTargetPosition(Ogre::Vector3::ZERO);
			eq->SetShooting(false);
			return;
		}
	}
		
	IAAObject *obj = CommonDeclarations::GetIDObject(TargetID);
	if (NULL==obj)
	{		
		TargetID=0;
		return;
	}
		
	IScenable* Target;	
	Target = obj->GetScenable();
	if (NULL==Target/* || phys->IsCollided()*/)
		return;
	
	if(RotationUnit.mRotating)
	{
		RotationUnit.Step();
		if(RotationUnit.mRotating)                                // Process timed rotation
		{				
			Ogre::Quaternion delta = RotationUnit.Slerp();	
			scen->SetOrientation(delta);
		}
	}// else
	{	
		int actual_rotation_speed = RotationSpeed;
		IPhysical *phys = Parent->GetPhysical();
        AICommander *commander = Owner->GetCommander();
        Ogre::Vector3 src = Ogre::Vector3::ZERO;
        if (commander)
        {
            IAAObject *obj = commander->GetParent();
            if (obj)
            {
                IScenable *scen = obj->GetScenable();
                if (scen)
                {
                    src = scen->GetOrientation()*Ogre::Vector3::NEGATIVE_UNIT_Z;
                }
            }
        } else
        {
            src = -phys->GetForwardDirection(); //OurOrientation * Ogre::Vector3::NEGATIVE_UNIT_Z;
        }
		
		Ogre::Vector3 direction = Target->GetPosition()-scen->GetPosition();
        direction.normalise();

        Ogre::Real cs = src.dotProduct(direction);
        if (src.isZeroLength() || cs>=AngleCosinusModule)
        {
			actual_rotation_speed = actual_rotation_speed/2;
			/*char log[100];
			sprintf(log,"in cone %f %f %f\n",direction.x, direction.y, direction.z);
			Debugging::Log("icas",log);*/			
        } else
		{			
			direction = src;
			/*char log[100];
			sprintf(log,"not in cone %f %f %f\n",direction.x, direction.y, direction.z);
			Debugging::Log("icas",log);*/
		}

        Ogre::Vector3 up =CommonDeclarations::GetUpVector();

		Ogre::Quaternion OurOrientation = scen->GetOrientation();
		Vector3 xVec = up.crossProduct(direction);
		xVec.normalise();
		Vector3 yVec = direction.crossProduct(xVec);
		yVec.normalise();
		Quaternion unitZToTarget = Quaternion(xVec, yVec, direction);

		Quaternion targetOrientation = Quaternion(-unitZToTarget.y, -unitZToTarget.z, unitZToTarget.w, unitZToTarget.x);

		RotationUnit.StartRotation(OurOrientation, targetOrientation, actual_rotation_speed);
	}

	std::pair<bool, Ogre::Real> intersection_res;
		
	IEquipped *eq = Parent->GetEquipped();
	Ogre::Ray pl_ray = eq->GetSightRay();

	intersection_res = pl_ray.intersects(Target->GetBoundingBox(true));
	if (intersection_res.first)
	{
        eq->SetTargetPosition(Target->GetPosition(), intersection_res.second);
		eq->SetShooting(true);
	} else
    {
        eq->SetTargetPosition(Ogre::Vector3::ZERO);
        eq->SetShooting(false);
    }
		
}
Example #20
0
void FollowCamera::update(Real time, const PosInfo& posIn, PosInfo* posOut, COLLISION_WORLD* world, bool bounce)
{
    if (!ca || !posOut)  return;

    ///  input from car posInfoIn
    Vector3 posGoal = posIn.pos;
    Quaternion orientGoal = posIn.rot;
    ///  output saved back to car posInfoOut
    Quaternion camRotFinal;

    const static Quaternion
    qO = Quaternion(Degree(180),Vector3::UNIT_Z) * Quaternion(Degree(-90),Vector3::UNIT_Y),
    qR = Quaternion(Degree(90),Vector3(0,1,0));

    Quaternion  orient = orientGoal * qO;
    Vector3  ofs = orient * ca->mOffset,  goalLook = posGoal + ofs;

    first = iFirst < 2;  ///par few first frames after reset
    if (iFirst < 10)  // after reset
    {
        ++iFirst;
        mDistReduce = 0.f;
        mATilt = 0.f;
    }

    ///  Camera Tilt from terrain/road slope under car
    //-------------------------------------------------------------------------------------------
    const float			//  params  . . .
    Rdist = 1.f,     // dist from car to ray (front or back)
    HupCar = 1.5f,	  // car up dir dist - for pipes - so pos stays inside pipe
    Habove = 1.5f,    // up axis dist, above car - for very high terrain angles
    HMaxDepth = 12.f;  // how far down can the ray goes
    const static Radian r0(0.f),
          angMin = Degree(10.f),   // below this angle, tilt has no effect - terrain bumps
          maxDiff = Degree(1.4f);  // max diff of tilt - no sudden jumps
    const float smoothSpeed = 14.f;  // how fast to apply tilt change

    bool bUseTilt = ca->mType == CAM_ExtAng || ca->mType == CAM_Follow;
    Radian tilt(0.f);
    if (pSet->cam_tilt && bUseTilt)
    {
        //  car pos
        Vector3 carUp = posIn.pos - HupCar * posIn.carY;
        MATHVECTOR<float,3> pos(carUp.x, -carUp.z, carUp.y + Habove);  // to vdr/blt
        const static MATHVECTOR<float,3> dir(0,0,-1);  // cast rays down

        //  car rot, yaw angle
        Quaternion q = posIn.rot * Quaternion(Degree(90),Vector3(0,1,0));
        float angCarY = q.getYaw().valueRadians() + PI_d/2.f;
        float ax = cosf(angCarY)*Rdist, ay = sinf(angCarY)*Rdist;
        //LogO("pos: "+fToStr(pos[0],2,4)+" "+fToStr(pos[1],2,4)+"  a: "+fToStr(angCarY,2,4)+"  dir: "+fToStr(ax,2,4)+" "+fToStr(ay,2,4));

        //  cast 2 rays - 2 times, average 2 angles
        COLLISION_CONTACT ct0,ct1,ct20,ct21;
        MATHVECTOR<float,3> ofs(ax*0.5f,ay*0.5f,0),ofs2(ax,ay,0);
        world->CastRay(pos+ofs, dir, HMaxDepth,chassis, ct0,  0,0, true, true);
        world->CastRay(pos-ofs, dir, HMaxDepth,chassis, ct1,  0,0, true, true);
        world->CastRay(pos+ofs2,dir, HMaxDepth,chassis, ct20, 0,0, true, true);
        world->CastRay(pos-ofs2,dir, HMaxDepth,chassis, ct21, 0,0, true, true);

#ifdef CAM_TILT_DBG
        MATHVECTOR<float,3> v;
        v = pos+ofs;
        posHit[0] = Vector3(v[0],v[2]- ct0.GetDepth(), -v[1]);
        v = pos-ofs;
        posHit[1] = Vector3(v[0],v[2]- ct1.GetDepth(), -v[1]);
        v = pos+ofs2;
        posHit[2] = Vector3(v[0],v[2]- ct20.GetDepth(),-v[1]);
        v = pos-ofs2;
        posHit[3] = Vector3(v[0],v[2]- ct21.GetDepth(),-v[1]);
#endif

        if (ct0.GetColObj() && ct1.GetColObj() && ct20.GetColObj() && ct21.GetColObj() )
            tilt = (GetAngle(Rdist, ct1.GetDepth() - ct0.GetDepth()) +
                    GetAngle(2.f*Rdist, ct21.GetDepth() - ct20.GetDepth())) * 0.5f;
        //else  LogO(String("no hit: ")+(ct0.col?"1":"0")+(ct1.col?" 1":" 0"));

        //if (tilt < angMin && tilt > -angMin)  tilt = 0.f;
        if (tilt < r0 && tilt >-angMin) {
            Radian d = tilt-angMin;
            tilt = std::min(r0, tilt + d*d*5.f);
        }
        if (tilt > r0 && tilt < angMin) {
            Radian d =-angMin-tilt;
            tilt = std::max(r0, tilt - d*d*5.f);
        }

        //LogO("a "+fToStr(angCarY,3,5)+" d  "+fToStr(ct0.GetDepth(),3,5)+" "+fToStr(ct1.GetDepth(),3,5)+"  t "+fToStr(tilt.valueDegrees(),3,5));
    }
    //  smooth tilt angle
    mATilt += std::min(maxDiff, std::max(-maxDiff, tilt - mATilt)) * time * smoothSpeed;


    //-------------------------------------------------------------------------------------------
    if (ca->mType == CAM_Car)	/* 3 Car - car pos & rot full */
    {
        camPosFinal = goalLook;
        camRotFinal = orient;

        posOut->camPos = camPosFinal;  // save result in out posInfo
        posOut->camRot = camRotFinal;
        return;
    }

    if (ca->mType == CAM_Follow)  ofs = ca->mOffset;

    Vector3  pos,goalPos;
    pos     = camPosFinal - ofs;
    goalPos = posGoal;

    Vector3  xyz;
    if (ca->mType != CAM_Arena)
    {
        Real x,y,z,xz;   // pitch & yaw to direction vector
        Real ap = bUseTilt ? (ca->mPitch.valueRadians() + mATilt.valueRadians()) : ca->mPitch.valueRadians(),
             ay = ca->mYaw.valueRadians();
        y = sin(ap), xz = cos(ap);
        x = sin(ay) * xz, z = cos(ay) * xz;
        xyz = Vector3(x,y,z);
        xyz *= ca->mDist;
    }

    bool manualOrient = false;
    switch (ca->mType)
    {
    case CAM_Arena:		/* 2 Arena - free pos & rot */
        goalPos = ca->mOffset - ofs;
        break;

    case CAM_Free:		/* 1 Free - free rot, pos from car */
        goalPos += xyz;
        break;

    case CAM_Follow:	/* 0 Follow - car rotY & pos from behind car, smooth */
    {   Quaternion  orient = orientGoal * qR;
        orient.FromAngleAxis(orient.getYaw(), Vector3::UNIT_Y);
        goalPos += orient * xyz;
    }
    break;

    case CAM_ExtAng:    /* 4 Extended Angle - car in center, angle smooth */
    {   Quaternion  orient = orientGoal * qR;
        Quaternion  ory;
        ory.FromAngleAxis(orient.getYaw(), Vector3::UNIT_Y);

        if (first)  {
            qq = ory;
        }
        else  qq = orient.Slerp(ca->mSpeed * time, qq, ory, true);

        //  smooth dist from vel
#if 0
        {
            if (first)  {
                mPosNodeOld = posGoal;
            }
            Real vel = (posGoal - mPosNodeOld).length() / std::max(0.002f, std::min(0.1f, time));
            mPosNodeOld = posGoal;
            if (first)  mVel = 0.f;
            else
                mVel += (vel - mVel) * time * 8.f;  //par-  vel smooth speed
            if (!first)
                xyz *= 1.f + std::min(100.f, mVel) * 0.01f;  //par-  vel dist factor
        }
#endif

        Quaternion  qy = Quaternion(ca->mYaw,Vector3(0,1,0));
        goalPos += qq * (xyz + ca->mOffset);

        camPosFinal = goalPos;
        camRotFinal = qq * qy * Quaternion(Degree(-ca->mPitch - mATilt), Vector3(1,0,0));
        manualOrient = true;
    }
    break;
    }

    if (!manualOrient)  // if !CAM_ExtAng
    {
        float dtmul = ca->mSpeed == 0 ? 1.0f : ca->mSpeed * time;

        if (ca->mType ==  CAM_Arena)
        {
            Vector3  Pos(0,0,0), goalPos = ca->mOffset;
            Pos = camPosFinal;  //read last state (smooth)
            Pos += (goalPos - Pos) * dtmul;

            mAPitch += (ca->mPitch - mAPitch) * dtmul;
            mAYaw += (ca->mYaw - mAYaw) * dtmul;

            if (first)  {
                Pos = goalPos;
                mAPitch = ca->mPitch;
                mAYaw = ca->mYaw;
            }
            camPosFinal = Pos;
            camRotFinal = Quaternion(Degree(mAYaw),Vector3(0,1,0)) * Quaternion(Degree(mAPitch),Vector3(1,0,0));
            manualOrient = true;
        }
        else
        {
            if (first)  pos = goalPos;
            Vector3  addPos,addLook;
            addPos = (goalPos - pos).normalisedCopy() * (goalPos - pos).length() * dtmul;
            if (addPos.squaredLength() > (goalPos - pos).squaredLength())  addPos = goalPos - pos;
            pos += addPos;
            camPosFinal = pos + ofs;

            goalLook = posGoal + ofs;
            if (first)	{
                mLook = goalLook;
            }

            addLook = (goalLook - mLook) * dtmul;//Rot;
            mLook += addLook;
        }
    }

    //camLookFinal = mLook;
    if (!manualOrient)  // CAM_Free or CAM_Follow
    {
        Vector3 zdir = camPosFinal - mLook;
        zdir.normalise();
        Vector3 xVec = Vector3::UNIT_Y.crossProduct(zdir);
        xVec.normalise();
        Vector3 yVec = zdir.crossProduct(xVec);
        yVec.normalise();
        Quaternion q;
        q.FromAxes(xVec, yVec, zdir);
        camRotFinal = q;
    }

    //  cast ray from car to camera, reduce dist if hit
    //-------------------------------------------------------------------------------------------
    Vector3 pp = camPosFinal;
    if (bounce)
        pp += posIn.camOfs * ca->mOfsMul
              * gPar.camBncScale * pSet->cam_bnc_mul;

    Vector3 p = posGoal;
    p.y += 1.f;  //up
    //Vector3 d = camRotFinal * Vector3::UNIT_Z;  d.normalise();
    Vector3 d = pp - p;
    d.normalise();

    if (!first && ca->mType != CAM_Arena)
    {
        MATHVECTOR<float,3> pos1(p.x,-p.z,p.y), dir(d.x,-d.z,d.y);  //dir = dir.Normalize();
        COLLISION_CONTACT ct;
        float maxLen = (p - pp).length();  //cam near
        world->CastRay(pos1, dir, maxLen,chassis, ct,  0,0, true, true, true/*+*/);
        //dbgLen = -maxLen;

        if (ct.GetColObj())
        {
            float len = ct.GetDepth();  //dbgLen = len;
            len -= 0.2f + ct.GetNormal()[2];  ///par  normal up, flat terrain, move closer
            if (len < maxLen)
            {
                Real dist = maxLen - len;
                if (dist > mDistReduce)
                    mDistReduce = dist;
            }
        }
    }

    //  save result in out posInfo
    posOut->camPos = mDistReduce > 0.0001f ? (pp - d * mDistReduce) : pp;
    posOut->camRot = camRotFinal;

    //  smooth, back to normal dist
    if (mDistReduce > 0.f)
        mDistReduce -= time * 10.f;
}
Example #21
0
    //-----------------------------------------------------------------------
    void PatchSurface::interpolateVertexData(void* lockedBuffer, size_t leftIdx, size_t rightIdx, size_t destIdx)
    {
        size_t vertexSize = mDeclaration->getVertexSize(0);
        const VertexElement* elemPos = mDeclaration->findElementBySemantic(VES_POSITION);
        const VertexElement* elemNorm = mDeclaration->findElementBySemantic(VES_NORMAL);
        const VertexElement* elemDiffuse = mDeclaration->findElementBySemantic(VES_DIFFUSE);
        const VertexElement* elemTex0 = mDeclaration->findElementBySemantic(VES_TEXTURE_COORDINATES, 0);
        const VertexElement* elemTex1 = mDeclaration->findElementBySemantic(VES_TEXTURE_COORDINATES, 1);

        float *pDestReal, *pLeftReal, *pRightReal;
        unsigned char *pDestChar, *pLeftChar, *pRightChar;
        unsigned char *pDest, *pLeft, *pRight;

        // Set up pointers & interpolate
        pDest = static_cast<unsigned char*>(lockedBuffer) + (vertexSize * destIdx);
        pLeft = static_cast<unsigned char*>(lockedBuffer) + (vertexSize * leftIdx);
        pRight = static_cast<unsigned char*>(lockedBuffer) + (vertexSize * rightIdx);

        // Position
        elemPos->baseVertexPointerToElement(pDest, &pDestReal);
        elemPos->baseVertexPointerToElement(pLeft, &pLeftReal);
        elemPos->baseVertexPointerToElement(pRight, &pRightReal);

        *pDestReal++ = (*pLeftReal++ + *pRightReal++) * 0.5f;
        *pDestReal++ = (*pLeftReal++ + *pRightReal++) * 0.5f;
        *pDestReal++ = (*pLeftReal++ + *pRightReal++) * 0.5f;

        if (elemNorm)
        {
            elemNorm->baseVertexPointerToElement(pDest, &pDestReal);
            elemNorm->baseVertexPointerToElement(pLeft, &pLeftReal);
            elemNorm->baseVertexPointerToElement(pRight, &pRightReal);
            Vector3 norm;
            norm.x = (*pLeftReal++ + *pRightReal++) * 0.5f;
            norm.y = (*pLeftReal++ + *pRightReal++) * 0.5f;
            norm.z = (*pLeftReal++ + *pRightReal++) * 0.5f;
            norm.normalise();

            *pDestReal++ = norm.x;
            *pDestReal++ = norm.y;
            *pDestReal++ = norm.z;
        }
        if (elemDiffuse)
        {
            // Blend each byte individually
            elemDiffuse->baseVertexPointerToElement(pDest, &pDestChar);
            elemDiffuse->baseVertexPointerToElement(pLeft, &pLeftChar);
            elemDiffuse->baseVertexPointerToElement(pRight, &pRightChar);
            // 4 bytes to RGBA
            *pDestChar++ = static_cast<unsigned char>(((*pLeftChar++) + (*pRightChar++)) * 0.5);
            *pDestChar++ = static_cast<unsigned char>(((*pLeftChar++) + (*pRightChar++)) * 0.5);
            *pDestChar++ = static_cast<unsigned char>(((*pLeftChar++) + (*pRightChar++)) * 0.5);
            *pDestChar++ = static_cast<unsigned char>(((*pLeftChar++) + (*pRightChar++)) * 0.5);
        }
        if (elemTex0)
        {
            elemTex0->baseVertexPointerToElement(pDest, &pDestReal);
            elemTex0->baseVertexPointerToElement(pLeft, &pLeftReal);
            elemTex0->baseVertexPointerToElement(pRight, &pRightReal);

            for (size_t dim = 0; dim < VertexElement::getTypeCount(elemTex0->getType()); ++dim)
                *pDestReal++ = ((*pLeftReal++) + (*pRightReal++)) * 0.5f;
        }
        if (elemTex1)
        {
            elemTex1->baseVertexPointerToElement(pDest, &pDestReal);
            elemTex1->baseVertexPointerToElement(pLeft, &pLeftReal);
            elemTex1->baseVertexPointerToElement(pRight, &pRightReal);

            for (size_t dim = 0; dim < VertexElement::getTypeCount(elemTex1->getType()); ++dim)
                *pDestReal++ = ((*pLeftReal++) + (*pRightReal++)) * 0.5f;
        }
    }
	//-----------------------------------------------------------------------
	void FocusedShadowCameraSetup::calculateShadowMappingMatrix(const SceneManager& sm,
		const Camera& cam, const Light& light, Matrix4 *out_view, Matrix4 *out_proj, 
		Camera *out_cam) const
	{
		// get the shadow frustum's far distance
		Real shadowDist = light.getShadowFarDistance();
		if (!shadowDist)
		{
			// need a shadow distance, make one up
			shadowDist = cam.getNearClipDistance() * 3000;
		}
		Real shadowOffset = shadowDist * sm.getShadowDirLightTextureOffset();


		if (light.getType() == Light::LT_DIRECTIONAL)
		{
			// generate view matrix if requested
			if (out_view != NULL)
			{
				Vector3 pos;
				if (sm.getCameraRelativeRendering())
				{
					pos = Vector3::ZERO;
				}
				else
				{
					pos = cam.getDerivedPosition();
				}
				*out_view = buildViewMatrix(pos, 
					light.getDerivedDirection(), 
					cam.getDerivedUp());
			}

			// generate projection matrix if requested
			if (out_proj != NULL)
			{
				*out_proj = Matrix4::getScale(1, 1, -1);
				//*out_proj = Matrix4::IDENTITY;
			}

			// set up camera if requested
			if (out_cam != NULL)
			{
				out_cam->setProjectionType(PT_ORTHOGRAPHIC);
				out_cam->setDirection(light.getDerivedDirection());
				out_cam->setPosition(cam.getDerivedPosition());
				out_cam->setFOVy(Degree(90));
				out_cam->setNearClipDistance(shadowOffset);
			}
		}
		else if (light.getType() == Light::LT_POINT)
		{
			// target analogue to the default shadow textures
			// Calculate look at position
			// We want to look at a spot shadowOffset away from near plane
			// 0.5 is a little too close for angles
			Vector3 target = cam.getDerivedPosition() + 
				(cam.getDerivedDirection() * shadowOffset);
			Vector3 lightDir = target - light.getDerivedPosition();
			lightDir.normalise();

			// generate view matrix if requested
			if (out_view != NULL)
			{
				*out_view = buildViewMatrix(light.getDerivedPosition(), 
					lightDir, 
					cam.getDerivedUp());
			}

			// generate projection matrix if requested
			if (out_proj != NULL)
			{
				// set FOV to 120 degrees
				mTempFrustum->setFOVy(Degree(120));

				mTempFrustum->setNearClipDistance(light._deriveShadowNearClipDistance(&cam));
				mTempFrustum->setFarClipDistance(light._deriveShadowFarClipDistance(&cam));

				*out_proj = mTempFrustum->getProjectionMatrix();
			}

			// set up camera if requested
			if (out_cam != NULL)
			{
				out_cam->setProjectionType(PT_PERSPECTIVE);
				out_cam->setDirection(lightDir);
				out_cam->setPosition(light.getDerivedPosition());
				out_cam->setFOVy(Degree(120));
				out_cam->setNearClipDistance(light._deriveShadowNearClipDistance(&cam));
				out_cam->setFarClipDistance(light._deriveShadowFarClipDistance(&cam));
			}
		}
		else if (light.getType() == Light::LT_SPOTLIGHT)
		{
			// generate view matrix if requested
			if (out_view != NULL)
			{
				*out_view = buildViewMatrix(light.getDerivedPosition(), 
					light.getDerivedDirection(), 
					cam.getDerivedUp());
			}

			// generate projection matrix if requested
			if (out_proj != NULL)
			{
				// set FOV slightly larger than spotlight range
				mTempFrustum->setFOVy(Ogre::Math::Clamp<Radian>(light.getSpotlightOuterAngle() * 1.2, Radian(0), Radian(Math::PI/2.0f)));

				mTempFrustum->setNearClipDistance(light._deriveShadowNearClipDistance(&cam));
				mTempFrustum->setFarClipDistance(light._deriveShadowFarClipDistance(&cam));

				*out_proj = mTempFrustum->getProjectionMatrix();
			}

			// set up camera if requested
			if (out_cam != NULL)
			{
				out_cam->setProjectionType(PT_PERSPECTIVE);
				out_cam->setDirection(light.getDerivedDirection());
				out_cam->setPosition(light.getDerivedPosition());
				out_cam->setFOVy(Ogre::Math::Clamp<Radian>(light.getSpotlightOuterAngle() * 1.2, Radian(0), Radian(Math::PI/2.0f)));
				out_cam->setNearClipDistance(light._deriveShadowNearClipDistance(&cam));
				out_cam->setFarClipDistance(light._deriveShadowFarClipDistance(&cam));
			}
		}
	}
    //-----------------------------------------------------------------------
    void SceneNode::setDirection(const Vector3& vec, TransformSpace relativeTo, 
        const Vector3& localDirectionVector)
    {
        // Do nothing if given a zero vector
        if (vec == Vector3::ZERO) return;

        // The direction we want the local direction point to
        Vector3 targetDir = vec.normalisedCopy();

        // Transform target direction to world space
        switch (relativeTo)
        {
        case TS_PARENT:
            if (mInheritOrientation)
            {
                if (mParent)
                {
                    targetDir = mParent->_getDerivedOrientation() * targetDir;
                }
            }
            break;
        case TS_LOCAL:
            targetDir = _getDerivedOrientation() * targetDir;
            break;
        case TS_WORLD:
            // default orientation
            break;
        }

        // Calculate target orientation relative to world space
        Quaternion targetOrientation;
        if( mYawFixed )
        {
            // Calculate the quaternion for rotate local Z to target direction
            Vector3 xVec = mYawFixedAxis.crossProduct(targetDir);
            xVec.normalise();
            Vector3 yVec = targetDir.crossProduct(xVec);
            yVec.normalise();
            Quaternion unitZToTarget = Quaternion(xVec, yVec, targetDir);

            if (localDirectionVector == Vector3::NEGATIVE_UNIT_Z)
            {
                // Specail case for avoid calculate 180 degree turn
                targetOrientation =
                    Quaternion(-unitZToTarget.y, -unitZToTarget.z, unitZToTarget.w, unitZToTarget.x);
            }
            else
            {
                // Calculate the quaternion for rotate local direction to target direction
                Quaternion localToUnitZ = localDirectionVector.getRotationTo(Vector3::UNIT_Z);
                targetOrientation = unitZToTarget * localToUnitZ;
            }
        }
        else
        {
            const Quaternion& currentOrient = _getDerivedOrientation();

            // Get current local direction relative to world space
            Vector3 currentDir = currentOrient * localDirectionVector;

            if ((currentDir+targetDir).squaredLength() < 0.00005f)
            {
                // Oops, a 180 degree turn (infinite possible rotation axes)
                // Default to yaw i.e. use current UP
                targetOrientation =
                    Quaternion(-currentOrient.y, -currentOrient.z, currentOrient.w, currentOrient.x);
            }
            else
            {
                // Derive shortest arc to new direction
                Quaternion rotQuat = currentDir.getRotationTo(targetDir);
                targetOrientation = rotQuat * currentOrient;
            }
        }

        // Set target orientation, transformed to parent space
        if (mParent && mInheritOrientation)
            setOrientation(mParent->_getDerivedOrientation().UnitInverse() * targetOrientation);
        else
            setOrientation(targetOrientation);
    }
Example #24
0
    //-----------------------------------------------------------------------
    const PlaneBoundedVolumeList& Light::_getFrustumClipVolumes(const Camera* const cam) const
    {

        // Homogenous light position
        Vector4 lightPos = getAs4DVector();
        // 3D version (not the same as _getDerivedPosition, is -direction for
        // directional lights)
        Vector3 lightPos3 = Vector3(lightPos.x, lightPos.y, lightPos.z);

        const Vector3 *clockwiseVerts[4];

        // Get worldspace frustum corners
        const Vector3* corners = cam->getWorldSpaceCorners();
        int winding = cam->isReflected() ? +1 : -1;

        bool infiniteViewDistance = (cam->getFarClipDistance() == 0);

        mFrustumClipVolumes.clear();
        for (unsigned short n = 0; n < 6; ++n)
        {
            // Skip far plane if infinite view frustum
            if (infiniteViewDistance && n == FRUSTUM_PLANE_FAR)
                continue;

            const Plane& plane = cam->getFrustumPlane(n);
            Vector4 planeVec(plane.normal.x, plane.normal.y, plane.normal.z, plane.d);
            // planes face inwards, we need to know if light is on negative side
            Real d = planeVec.dotProduct(lightPos);
            if (d < -1e-06)
            {
                // Ok, this is a valid one
                // clockwise verts mean we can cross-product and always get normals
                // facing into the volume we create

                mFrustumClipVolumes.push_back(PlaneBoundedVolume());
                PlaneBoundedVolume& vol = mFrustumClipVolumes.back();
                switch(n)
                {
                case(FRUSTUM_PLANE_NEAR):
                    clockwiseVerts[0] = corners + 3;
                    clockwiseVerts[1] = corners + 2;
                    clockwiseVerts[2] = corners + 1;
                    clockwiseVerts[3] = corners + 0;
                    break;
                case(FRUSTUM_PLANE_FAR):
                    clockwiseVerts[0] = corners + 7;
                    clockwiseVerts[1] = corners + 6;
                    clockwiseVerts[2] = corners + 5;
                    clockwiseVerts[3] = corners + 4;
                    break;
                case(FRUSTUM_PLANE_LEFT):
                    clockwiseVerts[0] = corners + 2;
                    clockwiseVerts[1] = corners + 6;
                    clockwiseVerts[2] = corners + 5;
                    clockwiseVerts[3] = corners + 1;
                    break;
                case(FRUSTUM_PLANE_RIGHT):
                    clockwiseVerts[0] = corners + 7;
                    clockwiseVerts[1] = corners + 3;
                    clockwiseVerts[2] = corners + 0;
                    clockwiseVerts[3] = corners + 4;
                    break;
                case(FRUSTUM_PLANE_TOP):
                    clockwiseVerts[0] = corners + 0;
                    clockwiseVerts[1] = corners + 1;
                    clockwiseVerts[2] = corners + 5;
                    clockwiseVerts[3] = corners + 4;
                    break;
                case(FRUSTUM_PLANE_BOTTOM):
                    clockwiseVerts[0] = corners + 7;
                    clockwiseVerts[1] = corners + 6;
                    clockwiseVerts[2] = corners + 2;
                    clockwiseVerts[3] = corners + 3;
                    break;
                };

                // Build a volume
                // Iterate over world points and form side planes
                Vector3 normal;
                Vector3 lightDir;
                for (unsigned int i = 0; i < 4; ++i)
                {
                    // Figure out light dir
                    lightDir = lightPos3 - (*(clockwiseVerts[i]) * lightPos.w);
                    Vector3 edgeDir = *(clockwiseVerts[i]) - *(clockwiseVerts[(i+winding)%4]);
                    // Cross with anticlockwise corner, therefore normal points in
                    normal = edgeDir.crossProduct(lightDir);
                    normal.normalise();
                    vol.planes.push_back(Plane(normal, *(clockwiseVerts[i])));
                }

                // Now do the near plane (this is the plane of the side we're 
                // talking about, with the normal inverted (d is already interpreted as -ve)
                vol.planes.push_back( Plane(-plane.normal, plane.d) );

                // Finally, for a point/spot light we can add a sixth plane
                // This prevents false positives from behind the light
                if (mLightType != LT_DIRECTIONAL)
                {
                    // re-use our own plane normal
                    vol.planes.push_back(Plane(plane.normal, lightPos3));
                }
            }
        }

        return mFrustumClipVolumes;
    }
Example #25
0
bool App::frameStart(Real time)
{
	PROFILER.beginBlock(" frameSt");
	fLastFrameDT = time;


	//  input
	for (int i=0; i<4; ++i)
	{
		boost::lock_guard<boost::mutex> lock(input->mPlayerInputStateMutex);
		for (int a = 0; a < NumPlayerActions; ++a)
			input->mPlayerInputState[i][a] = mInputCtrlPlayer[i]->getChannel(a)->getValue();
	}

	if (imgBack && pGame)  // show/hide background image
	{
		bool backImgVis = !bLoading && pGame->cars.empty();
		imgBack->setVisible(backImgVis);
	}


	//  multi thread
	if (pSet->multi_thr == 1 && pGame && !bLoading)
	{
		updatePoses(time);
	}

	///  graphs update  -._/\_-.
	if (pSet->show_graphs && graphs.size() > 0)
	{
		GraphsNewVals();
		UpdateGraphs();
	}

	//...................................................................
	///* tire edit */
	if (pSet->graphs_type == Gh_TireEdit && carModels.size() > 0)
	{
		int k = (isKey(SDL_SCANCODE_1) || isKey(SDL_SCANCODE_KP_DIVIDE)  ? -1 : 0)
			  + (isKey(SDL_SCANCODE_2) || isKey(SDL_SCANCODE_KP_MULTIPLY) ? 1 : 0);
		if (k)
		{
			double mul = shift ? 0.2 : (ctrl ? 4.0 : 1.0);
			mul *= 0.005;  // par

			CARDYNAMICS& cd = carModels[0]->pCar->dynamics;
			CARTIRE* tire = cd.GetTire(FRONT_LEFT);
			if (iEdTire == 1)  // longit |
			{
				Dbl& val = tire->longitudinal[iCurLong];  // modify 1st
				val += mul*k * (1 + abs(val));
				for (int i=1; i<4; ++i)
					cd.GetTire(WHEEL_POSITION(i))->longitudinal[iCurLong] = val;  // copy for rest
			}
			else if (iEdTire == 0)  // lateral --
			{
				Dbl& val = tire->lateral[iCurLat];
				val += mul*k * (1 + abs(val));
				for (int i=1; i<4; ++i)
					cd.GetTire(WHEEL_POSITION(i))->lateral[iCurLat] = val;
			}
			else  // align o
			{
				Dbl& val = tire->aligning[iCurAlign];
				val += mul*k * (1 + abs(val));
				for (int i=1; i<4; ++i)
					cd.GetTire(WHEEL_POSITION(i))->aligning[iCurAlign] = val;
			}

			//  update hat, 1st
			tire->CalculateSigmaHatAlphaHat();
			for (int i=1; i<4; ++i)  // copy for rest
			{	cd.GetTire(WHEEL_POSITION(i))->sigma_hat = tire->sigma_hat;
				cd.GetTire(WHEEL_POSITION(i))->alpha_hat = tire->alpha_hat;
			}
			iUpdTireGr = 1;
		}
	}
	//...................................................................


	///  gui
	gui->GuiUpdate();

	
	if (bWindowResized)
	{	bWindowResized = false;

		gcom->ResizeOptWnd();
		gcom->SizeGUI();
		gcom->updTrkListDim();
		gui->updChampListDim();  // resize lists
		bRecreateHUD = true;
		
		if (mSplitMgr)  //  reassign car cameras from new viewports
		{	std::list<Camera*>::iterator it = mSplitMgr->mCameras.begin();
			for (int i=0; i < carModels.size(); ++i)
				if (carModels[i]->fCam && it != mSplitMgr->mCameras.end())
				{	carModels[i]->fCam->mCamera = *it;  ++it;  }
		}
		if (!mSplitMgr->mCameras.empty())
		{
			Camera* cam1 = *mSplitMgr->mCameras.begin();
			scn->mWaterRTT->setViewerCamera(cam1);
			if (scn->grass)  scn->grass->setCamera(cam1);
			if (scn->trees)  scn->trees->setCamera(cam1);
		}
	}

	//  hud update sizes, after res change
	if (bRecreateHUD)
	{	bRecreateHUD = false;
		
		hud->Destroy();  hud->Create();
	}
	if (bSizeHUD)
	{	bSizeHUD = false;

		hud->Size();
	}


	if (bLoading)
	{
		NewGameDoLoad();
		PROFILER.endBlock(" frameSt");
		return true;
	}
	else 
	{
		///  loading end  ------
		const int iFr = 3;
		if (iLoad1stFrames >= 0)
		{	++iLoad1stFrames;
			if (iLoad1stFrames == iFr)
			{
				LoadingOff();  // hide loading overlay
				mSplitMgr->mGuiViewport->setClearEveryFrame(true, FBT_DEPTH);
				gui->Ch_LoadEnd();
				bLoadingEnd = true;
				iLoad1stFrames = -1;  // for refl
			}
		}else if (iLoad1stFrames >= -1)
		{
			--iLoad1stFrames;  // -2 end

			imgLoad->setVisible(false);  // hide back imgs
			if (imgBack)
				imgBack->setVisible(false);
		}

		
		//  input
		if (isFocGui && pSet->inMenu == MNU_Options && !pSet->isMain &&
			mWndTabsOpts->getIndexSelected() == TABo_Input)
			gui->UpdateInputBars();
		
		
		//  keys up/dn, for lists
		static float dirU = 0.f,dirD = 0.f;
		if (isFocGui && !pSet->isMain && !isTweak())
		{
			if (isKey(SDL_SCANCODE_UP)  ||isKey(SDL_SCANCODE_KP_8))	dirD += time;  else
			if (isKey(SDL_SCANCODE_DOWN)||isKey(SDL_SCANCODE_KP_2))	dirU += time;  else
			{	dirU = 0.f;  dirD = 0.f;  }
			int d = ctrl ? 4 : 1;
			if (dirU > 0.0f) {  gui->LNext( d);  dirU = -0.2f;  }
			if (dirD > 0.0f) {  gui->LNext(-d);  dirD = -0.2f;  }
		}
		
		///  Gui updates from Networking
		gui->UpdGuiNetw();


		//  replay forward,backward keys
		if (bRplPlay)
		{
			isFocRpl = ctrl;
			bool le = isKey(SDL_SCANCODE_LEFTBRACKET), ri = isKey(SDL_SCANCODE_RIGHTBRACKET), ctrlN = ctrl && (le || ri);
			int ta = ((le || gui->bRplBack) ? -2 : 0) + ((ri || gui->bRplFwd) ? 2 : 0);
			if (ta)
			{	double tadd = ta;
				tadd *= (shift ? 0.2 : 1) * (ctrlN ? 4 : 1) * (alt ? 8 : 1);  // multipliers
				if (!bRplPause)  tadd -= 1;  // play compensate
				double t = pGame->timer.GetReplayTime(0), len = replay.GetTimeLength();
				t += tadd * time;  // add
				if (t < 0.0)  t += len;  // cycle
				if (t > len)  t -= len;
				pGame->timer.SetReplayTime(0, t);
			}
		}

		if (!pGame)
		{
			PROFILER.endBlock(" frameSt");
			return false;
		}


		if (pSet->multi_thr == 0)
			DoNetworking();


		//  single thread, sim on draw
		bool ret = true;
		if (pSet->multi_thr == 0)
		{
			ret = pGame->OneLoop(time);
			if (!ret)  mShutDown = true;
			updatePoses(time);
		}
		
		// align checkpoint arrow
		// move in front of camera
		if (pSet->check_arrow && hud->arrow.node && !bRplPlay && !carModels.empty())
		{
			FollowCamera* cam = carModels[0]->fCam;
		
			Vector3 pos = cam->mCamera->getPosition();
			Vector3 dir = cam->mCamera->getDirection();  dir.normalise();
			Vector3 up = cam->mCamera->getUp();  up.normalise();
			Vector3 arrowPos = pos + 10.0f * dir + 3.5f*up;
			hud->arrow.node->setPosition(arrowPos);
			
			// animate
			bool bFirstFrame = carModels.front()->bGetStPos;
			if (bFirstFrame) // 1st frame: dont animate
				hud->arrow.qCur = hud->arrow.qEnd;
			else
				hud->arrow.qCur = Quaternion::Slerp(time*5, hud->arrow.qStart, hud->arrow.qEnd, true);
			hud->arrow.nodeRot->setOrientation(hud->arrow.qCur);
			
			// look down -y a bit so we can see the arrow better
			hud->arrow.nodeRot->pitch(Degree(-20), SceneNode::TS_LOCAL); 
		}

		//  cam info text
		if (pSet->show_cam && !carModels.empty() && hud->txCamInfo)
		{	FollowCamera* cam = carModels[0]->fCam;
			if (cam)
			{	bool vis = cam->updInfo(time) && !isFocGui;
				if (vis)
					hud->txCamInfo->setCaption(String(cam->ss));
				hud->txCamInfo->setVisible(vis);
		}	}
		

		//  update all cube maps
		PROFILER.beginBlock("g.refl");
		for (std::vector<CarModel*>::iterator it=carModels.begin(); it!=carModels.end(); it++)
		if (!(*it)->isGhost() && (*it)->pReflect)
			(*it)->pReflect->Update(iLoad1stFrames == -1);
		PROFILER.endBlock("g.refl");


		//  trees
		PROFILER.beginBlock("g.veget");
		if (scn->road) {
			if (scn->grass)  scn->grass->update();
			if (scn->trees)  scn->trees->update();  }
		PROFILER.endBlock("g.veget");


		//  road upd lods
		if (scn->road)
		{
			//PROFILER.beginBlock("g.road");  // below 0.0 ms

			//  more than 1: in pre viewport, each frame
			if (mSplitMgr->mNumViewports == 1)
			{
				roadUpdTm += time;
				if (roadUpdTm > 0.1f)  // interval [sec]
				{
					roadUpdTm = 0.f;
					scn->road->UpdLodVis(pSet->road_dist);
				}
			}
			//PROFILER.endBlock("g.road");
		}

		//**  bullet bebug draw
		if (dbgdraw)  {							// DBG_DrawWireframe
			dbgdraw->setDebugMode(pSet->bltDebug ? 1 /*+(1<<13) 255*/ : 0);
			dbgdraw->step();  }


		///  terrain mtr from blend maps
		// now in CarModel::Update
		//UpdWhTerMtr(pCar);
		
		// stop rain/snow when paused
		if (scn->pr && scn->pr2 && pGame)
		{
			if (pGame->pause)
				{	 scn->pr->setSpeedFactor(0.f);  scn->pr2->setSpeedFactor(0.f);  }
			else{	 scn->pr->setSpeedFactor(1.f);  scn->pr2->setSpeedFactor(1.f);  }
		}

		
		//  update shader time
		mTimer += time;
		mFactory->setSharedParameter("windTimer",  sh::makeProperty <sh::FloatValue>(new sh::FloatValue(mTimer)));
		mFactory->setSharedParameter("waterTimer", sh::makeProperty <sh::FloatValue>(new sh::FloatValue(mTimer)));


		///()  grass sphere pos
		if (!carModels.empty())
		{
			Real r = 1.7;  r *= r;  //par
			const Vector3* p = &carModels[0]->posSph[0];
			mFactory->setSharedParameter("posSph0", sh::makeProperty <sh::Vector4>(new sh::Vector4(p->x,p->y,p->z,r)));
			p = &carModels[0]->posSph[1];
			mFactory->setSharedParameter("posSph1", sh::makeProperty <sh::Vector4>(new sh::Vector4(p->x,p->y,p->z,r)));
		}else
		{	mFactory->setSharedParameter("posSph0", sh::makeProperty <sh::Vector4>(new sh::Vector4(0,0,500,-1)));
			mFactory->setSharedParameter("posSph1", sh::makeProperty <sh::Vector4>(new sh::Vector4(0,0,500,-1)));
		}


		//  Signal loading finished to the peers
		if (mClient && bLoadingEnd)
		{
			bLoadingEnd = false;
			mClient->loadingFinished();
		}
		
		PROFILER.endBlock(" frameSt");

		return ret;
	}
	PROFILER.endBlock(" frameSt");
}
Example #26
0
    //-----------------------------------------------------------------------
    const PlaneBoundedVolume& Light::_getNearClipVolume(const Camera* const cam) const
    {
        // First check if the light is close to the near plane, since
        // in this case we have to build a degenerate clip volume
        mNearClipVolume.planes.clear();
        mNearClipVolume.outside = Plane::NEGATIVE_SIDE;

        Real n = cam->getNearClipDistance();
        // Homogenous position
        Vector4 lightPos = getAs4DVector();
        // 3D version (not the same as _getDerivedPosition, is -direction for
        // directional lights)
        Vector3 lightPos3 = Vector3(lightPos.x, lightPos.y, lightPos.z);

        // Get eye-space light position
        // use 4D vector so directional lights still work
        Vector4 eyeSpaceLight = cam->getViewMatrix() * lightPos;
        // Find distance to light, project onto -Z axis
        Real d = eyeSpaceLight.dotProduct(
            Vector4(0, 0, -1, -n) );
        #define THRESHOLD 1e-6
        if (d > THRESHOLD || d < -THRESHOLD)
        {
            // light is not too close to the near plane
            // First find the worldspace positions of the corners of the viewport
            const Vector3 *corner = cam->getWorldSpaceCorners();
            int winding = (d < 0) ^ cam->isReflected() ? +1 : -1;
            // Iterate over world points and form side planes
            Vector3 normal;
            Vector3 lightDir;
            for (unsigned int i = 0; i < 4; ++i)
            {
                // Figure out light dir
                lightDir = lightPos3 - (corner[i] * lightPos.w);
                // Cross with anticlockwise corner, therefore normal points in
                normal = (corner[i] - corner[(i+winding)%4])
                    .crossProduct(lightDir);
                normal.normalise();
                mNearClipVolume.planes.push_back(Plane(normal, corner[i]));
            }

            // Now do the near plane plane
            normal = cam->getFrustumPlane(FRUSTUM_PLANE_NEAR).normal;
            if (d < 0)
            {
                // Behind near plane
                normal = -normal;
            }
            const Vector3& cameraPos = cam->getDerivedPosition();
            mNearClipVolume.planes.push_back(Plane(normal, cameraPos));

            // Finally, for a point/spot light we can add a sixth plane
            // This prevents false positives from behind the light
            if (mLightType != LT_DIRECTIONAL)
            {
                // Direction from light perpendicular to near plane
                mNearClipVolume.planes.push_back(Plane(-normal, lightPos3));
            }
        }
        else
        {
            // light is close to being on the near plane
            // degenerate volume including the entire scene 
            // we will always require light / dark caps
            mNearClipVolume.planes.push_back(Plane(Vector3::UNIT_Z, -n));
            mNearClipVolume.planes.push_back(Plane(-Vector3::UNIT_Z, n));
        }

        return mNearClipVolume;
    }
Example #27
0
	//---------------------------------------------------------------------()
	void Camera::getCameraToViewportBoxVolume(Real screenLeft, 
		Real screenTop, Real screenRight, Real screenBottom, 
		PlaneBoundedVolume* outVolume, bool includeFarPlane)
	{
		outVolume->planes.clear();

		if (mProjType == PT_PERSPECTIVE)
		{

			// Use the corner rays to generate planes
			Ray ul = getCameraToViewportRay(screenLeft, screenTop);
			Ray ur = getCameraToViewportRay(screenRight, screenTop);
			Ray bl = getCameraToViewportRay(screenLeft, screenBottom);
			Ray br = getCameraToViewportRay(screenRight, screenBottom);


			Vector3 normal;
			// top plane
			normal = ul.getDirection().crossProduct(ur.getDirection());
			normal.normalise();
			outVolume->planes.push_back(
				Plane(normal, getDerivedPosition()));

			// right plane
			normal = ur.getDirection().crossProduct(br.getDirection());
			normal.normalise();
			outVolume->planes.push_back(
				Plane(normal, getDerivedPosition()));

			// bottom plane
			normal = br.getDirection().crossProduct(bl.getDirection());
			normal.normalise();
			outVolume->planes.push_back(
				Plane(normal, getDerivedPosition()));

			// left plane
			normal = bl.getDirection().crossProduct(ul.getDirection());
			normal.normalise();
			outVolume->planes.push_back(
				Plane(normal, getDerivedPosition()));

		}
		else
		{
			// ortho planes are parallel to frustum planes

			Ray ul = getCameraToViewportRay(screenLeft, screenTop);
			Ray br = getCameraToViewportRay(screenRight, screenBottom);

			updateFrustumPlanes();
			outVolume->planes.push_back(
				Plane(mFrustumPlanes[FRUSTUM_PLANE_TOP].normal, ul.getOrigin()));
			outVolume->planes.push_back(
				Plane(mFrustumPlanes[FRUSTUM_PLANE_RIGHT].normal, br.getOrigin()));
			outVolume->planes.push_back(
				Plane(mFrustumPlanes[FRUSTUM_PLANE_BOTTOM].normal, br.getOrigin()));
			outVolume->planes.push_back(
				Plane(mFrustumPlanes[FRUSTUM_PLANE_LEFT].normal, ul.getOrigin()));
			

		}

		// near & far plane applicable to both projection types
		outVolume->planes.push_back(getFrustumPlane(FRUSTUM_PLANE_NEAR));
		if (includeFarPlane)
			outVolume->planes.push_back(getFrustumPlane(FRUSTUM_PLANE_FAR));
	}
Example #28
0
    //-----------------------------------------------------------------------
    void Camera::setDirection(const Vector3& vec)
    {
        // Do nothing if given a zero vector
        // (Replaced assert since this could happen with auto tracking camera and
        //  camera passes through the lookAt point)
        if (vec == Vector3::ZERO) return;

        // Remember, camera points down -Z of local axes!
        // Therefore reverse direction of direction vector before determining local Z
        Vector3 zAdjustVec = -vec;
        zAdjustVec.normalise();

		Quaternion targetWorldOrientation;


        if( mYawFixed )
        {
            Vector3 xVec = mYawFixedAxis.crossProduct( zAdjustVec );
            xVec.normalise();

            Vector3 yVec = zAdjustVec.crossProduct( xVec );
            yVec.normalise();

            targetWorldOrientation.FromAxes( xVec, yVec, zAdjustVec );
        }
        else
        {

            // Get axes from current quaternion
            Vector3 axes[3];
            updateView();
            mRealOrientation.ToAxes(axes);
            Quaternion rotQuat;
            if ( (axes[2]+zAdjustVec).squaredLength() <  0.00005f) 
            {
                // Oops, a 180 degree turn (infinite possible rotation axes)
                // Default to yaw i.e. use current UP
                rotQuat.FromAngleAxis(Radian(Math::PI), axes[1]);
            }
            else
            {
                // Derive shortest arc to new direction
                rotQuat = axes[2].getRotationTo(zAdjustVec);

            }
            targetWorldOrientation = rotQuat * mRealOrientation;
        }

        // transform to parent space
        if (mParentNode)
        {
            mOrientation =
                mParentNode->_getDerivedOrientation().Inverse() * targetWorldOrientation;
        }
		else
		{
			mOrientation = targetWorldOrientation;
		}

        // TODO If we have a fixed yaw axis, we mustn't break it by using the
        // shortest arc because this will sometimes cause a relative yaw
        // which will tip the camera

        invalidateView();

    }
 //-----------------------------------------------------------------------
 Vector3 Math::calculateBasicFaceNormal(const Vector3& v1, const Vector3& v2, const Vector3& v3)
 {
     Vector3 normal = (v2 - v1).crossProduct(v3 - v1);
     normal.normalise();
     return normal;
 }
    //---------------------------------------------------------------------
    Real ProgressiveMesh::computeEdgeCollapseCost(PMVertex *src, PMVertex *dest)
    {
        // if we collapse edge uv by moving src to dest then how 
        // much different will the model change, i.e. how much "error".
        // The method of determining cost was designed in order 
        // to exploit small and coplanar regions for
        // effective polygon reduction.
        Vector3 edgeVector = src->position - dest->position;

        Real cost;
		Real curvature = 0.001f;

        // find the "sides" triangles that are on the edge uv
        PMVertex::FaceList sides;
        PMVertex::FaceList::iterator srcface, srcfaceEnd;
        srcfaceEnd = src->face.end();
        // Iterate over src's faces and find 'sides' of the shared edge which is being collapsed
        for(srcface = src->face.begin(); srcface != srcfaceEnd; ++srcface)
        {
            // Check if this tri also has dest in it (shared edge)
            if( (*srcface)->hasCommonVertex(dest) )
            {
                sides.insert(*srcface);
            }
        }

		// Special cases
		// If we're looking at a border vertex
        if(src->isBorder())
        {
			if (sides.size() > 1) 
			{
				// src is on a border, but the src-dest edge has more than one tri on it
				// So it must be collapsing inwards
				// Mark as very high-value cost
				// curvature = 1.0f;
				cost = 1.0f;
			}
			else
			{
				// Collapsing ALONG a border
				// We can't use curvature to measure the effect on the model
				// Instead, see what effect it has on 'pulling' the other border edges
				// The more colinear, the less effect it will have
				// So measure the 'kinkiness' (for want of a better term)
				// Normally there can be at most 1 other border edge attached to this
				// However in weird cases there may be more, so find the worst
				Vector3 collapseEdge, otherBorderEdge;
				Real kinkiness, maxKinkiness;
				PMVertex::NeighborList::iterator n, nend;
				nend = src->neighbor.end();
				maxKinkiness = 0.0f;
				edgeVector.normalise();
				collapseEdge = edgeVector;
				for (n = src->neighbor.begin(); n != nend; ++n)
				{
					if (*n != dest && (*n)->isManifoldEdgeWith(src))
					{
						otherBorderEdge = src->position - (*n)->position;
						otherBorderEdge.normalise();
						// This time, the nearer the dot is to -1, the better, because that means
						// the edges are opposite each other, therefore less kinkiness
						// Scale into [0..1]
						kinkiness = (otherBorderEdge.dotProduct(collapseEdge) + 1.002f) * 0.5f;
						maxKinkiness = std::max(kinkiness, maxKinkiness);

					}
				}

				cost = maxKinkiness; 

			}
        } 
		else // not a border
		{

			// Standard inner vertex
			// Calculate curvature
			// use the triangle facing most away from the sides 
			// to determine our curvature term
			// Iterate over src's faces again
			for(srcface = src->face.begin(); srcface != srcfaceEnd; ++srcface) 
			{
				Real mincurv = 1.0f; // curve for face i and closer side to it
				// Iterate over the sides
				PMVertex::FaceList::iterator sidesFace, sidesFaceEnd;
				sidesFaceEnd = sides.end();
				for(sidesFace = sides.begin(); sidesFace != sidesFaceEnd; ++sidesFace) 
				{
					// Dot product of face normal gives a good delta angle
					Real dotprod = (*srcface)->normal.dotProduct( (*sidesFace)->normal );
					// NB we do (1-..) to invert curvature where 1 is high curvature [0..1]
					// Whilst dot product is high when angle difference is low
					mincurv =  std::min(mincurv,(1.002f - dotprod) * 0.5f);
				}
				curvature = std::max(curvature, mincurv);
			}
			cost = curvature;
		}

        // check for texture seam ripping
		if (src->seam && !dest->seam)
		{
			cost = 1.0f;
		}

        // Check for singular triangle destruction
        // If src and dest both only have 1 triangle (and it must be a shared one)
        // then this would destroy the shape, so don't do this
        if (src->face.size() == 1 && dest->face.size() == 1)
        {
            cost = NEVER_COLLAPSE_COST;
        }


		// Degenerate case check
		// Are we going to invert a face normal of one of the neighbouring faces?
		// Can occur when we have a very small remaining edge and collapse crosses it
		// Look for a face normal changing by > 90 degrees
		for(srcface = src->face.begin(); srcface != srcfaceEnd; ++srcface) 
		{
			// Ignore the deleted faces (those including src & dest)
			if( !(*srcface)->hasCommonVertex(dest) )
			{
				// Test the new face normal
				PMVertex *v0, *v1, *v2;
				// Replace src with dest wherever it is
				v0 = ( (*srcface)->vertex[0]->commonVertex == src) ? dest : (*srcface)->vertex[0]->commonVertex;
				v1 = ( (*srcface)->vertex[1]->commonVertex == src) ? dest : (*srcface)->vertex[1]->commonVertex;
				v2 = ( (*srcface)->vertex[2]->commonVertex == src) ? dest : (*srcface)->vertex[2]->commonVertex;

				// Cross-product 2 edges
				Vector3 e1 = v1->position - v0->position; 
				Vector3 e2 = v2->position - v1->position;

				Vector3 newNormal = e1.crossProduct(e2);
				newNormal.normalise();

				// Dot old and new face normal
				// If < 0 then more than 90 degree difference
				if (newNormal.dotProduct( (*srcface)->normal ) < 0.0f )
				{
					// Don't do it!
					cost = NEVER_COLLAPSE_COST;
					break; // No point continuing
				}


			}
		}
		

		assert (cost >= 0);
		return cost;
    }