예제 #1
0
/*!
	\param screen_position screen position
	\param position_ position
	\param direction_ direction
*/
void Storm3D_Scene::GetEyeVectors(const VC2I &screen_position, Vector &position_, Vector &direction_)
{
	static const float NEAR_Z = 2.f;

	D3DXMATRIX pProjection;
	D3DXMATRIX pView;

	VC3 camera_up = camera.GetUpVec();
	VC3 camera_position = camera.GetPosition();
	VC3 camera_target = camera.GetTarget();
	
	D3DXMatrixLookAtLH(pView, camera_position, camera_target, camera_up);

	//RECT windowSize = { 0 };
	//GetClientRect(Storm3D2->window_handle, &windowSize);
	igios_unimplemented();
	Storm3D_SurfaceInfo ss = Storm3D2->GetScreenSize();
	float aspect=(float) ss.width / (float) ss.height;

	float fov = camera.GetFieldOfView();
	float vis_range = camera.GetVisibilityRange();

	VC3 pV;
	D3DXMatrixPerspectiveFovLH(pProjection,fov,aspect,1.0f,vis_range);

	pV.x = 1.0f;
	pV.y = 1.0f;
	pV.z = 1.0f;
	//pV.x =  ( ( ( 2.0f * (float)screen_position.x ) / windowSize.right  ) - 1 ) / pProjection._11;
	//pV.y = -( ( ( 2.0f * (float)screen_position.y ) / windowSize.bottom ) - 1 ) / pProjection._22;
	//pV.z =  1.0f;

	D3DXMATRIX m;
	D3DXMatrixInverse(m, NULL, pView);

	VC3 vPickRayDir;
	VC3 vPickRayOrig;

	vPickRayDir.x  = pV.x*m._11 + pV.y*m._21 + pV.z*m._31;
	vPickRayDir.y  = pV.x*m._12 + pV.y*m._22 + pV.z*m._32;
	vPickRayDir.z  = pV.x*m._13 + pV.y*m._23 + pV.z*m._33;
	vPickRayDir = vPickRayDir.GetNormalized();
	vPickRayOrig.x = m._41;
	vPickRayOrig.y = m._42;
	vPickRayOrig.z = m._43;

	vPickRayOrig+=vPickRayDir*NEAR_Z;

	direction_.x = vPickRayDir.x;
	direction_.y = vPickRayDir.y;
	direction_.z = vPickRayDir.z;
	position_.x = vPickRayOrig.x;
	position_.y = vPickRayOrig.y;
	position_.z = vPickRayOrig.z;
}
예제 #2
0
void GravityPointParticleForce::calcForce(Vector& force, const Vector& pos, const Vector& vel) {
	VC3 diff = pos - m_point;
	VC3 diffNorm = diff.GetNormalized();
	float diffLenSq = diff.GetSquareLength();
	if (fabsf(diffLenSq) < 0.01f)
	{
		force.x = 0.0f;
		force.y = 0.0f;
		force.z = 0.0f;
	} else {
		// realistic gravity (bad)
		//force = -diffNorm * 0.001f * m_gravity / diffLenSq;
		// unrealisic gravity (better)
		float diffLen = sqrtf(diffLenSq);
		force = -diffNorm * 0.001f * m_gravity / diffLen;
	}
}
예제 #3
0
	bool LineAreaChecker::isPointInsideLineArea(const VC3 &point, 
		const VC3 &lineStart, const VC3 &lineEnd, float lineWidth)
	{
		VC3 projPos = lineEnd - lineStart;
		float projPosLenSq = projPos.GetSquareLength();
		VC3 projPosNorm = VC3(0,0,0);
		if (projPosLenSq > 0.00001f)
		{
			projPosNorm = projPos.GetNormalized();
		}

		VC3 chkpos = point - lineStart;
		float chkposLen = chkpos.GetLength();

		VC3 hitAndUnitDiff = chkpos - projPos;
		float hitAndUnitDiffLenSq = hitAndUnitDiff.GetSquareLength();

		float lineRadiusSq = (float)(lineWidth * lineWidth);

		if (hitAndUnitDiffLenSq < lineRadiusSq)
		{
			return true;
		}

		if (chkposLen * chkposLen < projPosLenSq)
		{
			VC3 pipedPos = projPosNorm * chkposLen;
			VC3 posdiff = chkpos - pipedPos;

			if (posdiff.GetSquareLength() < lineRadiusSq)
			{
				return true;
			}
		}

		return false;
	}
	// return true if position ok and decal should be added
	//        false, if position NOT ok and decal should NOT be added
	bool DecalPositionCalculator::calculateDecalPosition(
		game::GameScene *gameScene,
		const VC3 &origin, const VC3 &velocity, 
		DECAL_POSITIONING positioning, int positionRandom,
		VC3 *resultPosition, QUAT *resultRotation)
	{
		assert(positioning != DecalPositionCalculator::DECAL_POSITIONING_INVALID);

		game::GameMap *gameMap = gameScene->getGameMap();

		bool hitWall = false;

		*resultPosition = origin;
		*resultRotation = QUAT((-3.1415926f / 2.0f),0,0);

		// if velocity positioning...
		if (positioning == DecalPositionCalculator::DECAL_POSITIONING_VELOCITY)
		{
			VC3 velocityRandomized;
			if (positionRandom > 0)
			{
				velocityRandomized = velocity * GAME_TICKS_PER_SECOND;

	// TEMP
	//char buf[64];
	//sprintf(buf, "%f,%f,%f", velocity.x, velocity.y, velocity.z);
	//Logger::getInstance()->error(buf);

				// TODO: add positionRandom to velocity _angle_...
				// (or maybe just do a quick hack and add it to xz-coordinates?)
				velocityRandomized.x += float((SystemRandom::getInstance()->nextInt() % (positionRandom * 2 + 1)) - positionRandom) / 100.0f;
				velocityRandomized.z += float((SystemRandom::getInstance()->nextInt() % (positionRandom * 2 + 1)) - positionRandom) / 100.0f;
				
				// add to y too? maybe should add downward only? 
				// NOTE: biased downward
				velocityRandomized.y += float((SystemRandom::getInstance()->nextInt() % (positionRandom * 2 + 1)) - positionRandom) / 100.0f;
				velocityRandomized.y -= float(positionRandom) / 100.0f * 0.5f;

			} else {
				velocityRandomized = velocity;
			}

			velocityRandomized *= 2.0f;

			IStorm3D_Scene *scene = gameScene->getStormScene();

			VC3 dir = velocityRandomized.GetNormalized();			
			VC3 rayOrigin = origin;
			float rayLen = velocityRandomized.GetLength();

			Storm3D_CollisionInfo sceneColl;
			sceneColl.includeTerrainObjects = false;
			scene->RayTrace(rayOrigin, dir, rayLen, sceneColl, true);

			/*
			if (sceneColl.hit)
			{
				VC3 hitNormal = sceneColl.plane_normal;
				// make a "wall" hit if normal-y is not nearly 1
				//if (fabs(hitNormal.y) < 0.8f)
				{
					hitWall = true;

					VC3 x(rand() % 1000 / 999.f, 0, rand() % 1000 / 999.f);
					x.Normalize();
					x -= hitNormal * x.GetDotWith(hitNormal);
					VC3 y = -x.GetCrossWith(hitNormal);

					assert(fabsf(x.GetDotWith(y)) < 0.0001f);
					assert(fabsf(x.GetDotWith(hitNormal)) < 0.0001f);

					MAT tm;
					tm.Set(0, x.x);
					tm.Set(1, x.y);
					tm.Set(2, x.z);
					tm.Set(4, y.x);
					tm.Set(5, y.y);
					tm.Set(6, y.z);
					tm.Set(8, hitNormal.x);
					tm.Set(9, hitNormal.y);
					tm.Set(10, hitNormal.z);

					*resultRotation = tm.GetRotation();
				}
				*resultPosition = sceneColl.position;
			} else {
				*resultPosition += velocityRandomized;
			}
			*/

			// New version
			{
				VC3 hitNormal(0, 1.f, 0);
				if(sceneColl.hit)
				{
					hitNormal = sceneColl.plane_normal;
					*resultPosition = sceneColl.position;
				}
				else
				{
					*resultPosition += velocityRandomized;
					VC2 p2(resultPosition->x, resultPosition->z);
					hitNormal = gameScene->getTerrain()->getFaceNormal(p2);
				}

				{
					if(sceneColl.hit)
						hitWall = true;

		/*
		VC3 y = dir;
		VC3 z = hitNormal;
		y -= hitNormal * y.GetDotWith(hitNormal);
		VC3 x = z.GetCrossWith(y);
		*/

		VC3 x = dir;
		x.y = 0.f;
		x.Normalize();
		x -= hitNormal * x.GetDotWith(hitNormal);
		VC3 y = -x.GetCrossWith(hitNormal);
		VC3 z = hitNormal;

		MAT tm;
		tm.Set(0, x.x);
		tm.Set(1, x.y);
		tm.Set(2, x.z);
		tm.Set(4, y.x);
		tm.Set(5, y.y);
		tm.Set(6, y.z);
		tm.Set(8, z.x);
		tm.Set(9, z.y);
		tm.Set(10, z.z);

		resultRotation->MakeFromAngles(0.f, 0.f, -PI*0.5f);
		*resultRotation = (*resultRotation) * tm.GetRotation();

					/*
					VC3 x(rand() % 1000 / 999.f, 0, rand() % 1000 / 999.f);
					x.Normalize();
					x -= hitNormal * x.GetDotWith(hitNormal);
					VC3 y = -x.GetCrossWith(hitNormal);

					assert(fabsf(x.GetDotWith(y)) < 0.0001f);
					assert(fabsf(x.GetDotWith(hitNormal)) < 0.0001f);

					MAT tm;
					tm.Set(0, x.x);
					tm.Set(1, x.y);
					tm.Set(2, x.z);
					tm.Set(4, y.x);
					tm.Set(5, y.y);
					tm.Set(6, y.z);
					tm.Set(8, hitNormal.x);
					tm.Set(9, hitNormal.y);
					tm.Set(10, hitNormal.z);

					*resultRotation = tm.GetRotation();
					*/
				}
			}


			// TODO: some kind of terrain raytrace maybe...?
			// should collide to walls, etc.
		}

		// if downward positioning...
		if (positioning == DecalPositionCalculator::DECAL_POSITIONING_DOWNWARD)
		{
			if (positionRandom > 0)
			{
				// TODO: add a random xz-offset to result position
				//*resultPosition += randomizedOffset;
				resultPosition->x += float((SystemRandom::getInstance()->nextInt() % (positionRandom * 2 + 1)) - positionRandom) / 100.0f;
				resultPosition->z += float((SystemRandom::getInstance()->nextInt() % (positionRandom * 2 + 1)) - positionRandom) / 100.0f;
			}			

			/*
			// psd
			{
				VC2 p2(resultPosition->x, resultPosition->z);
				VC3 hitNormal = gameScene->getTerrain()->getFaceNormal(p2);

				VC3 x(rand() % 1000 / 999.f, 0, rand() % 1000 / 999.f);
				x.Normalize();
				x -= hitNormal * x.GetDotWith(hitNormal);
				VC3 y = -x.GetCrossWith(hitNormal);

				assert(fabsf(x.GetDotWith(y)) < 0.0001f);
				assert(fabsf(x.GetDotWith(hitNormal)) < 0.0001f);

				MAT tm;
				tm.Set(0, x.x);
				tm.Set(1, x.y);
				tm.Set(2, x.z);
				tm.Set(4, y.x);
				tm.Set(5, y.y);
				tm.Set(6, y.z);
				tm.Set(8, hitNormal.x);
				tm.Set(9, hitNormal.y);
				tm.Set(10, hitNormal.z);

				*resultRotation = tm.GetRotation();
			}
			*/
			VC3 fooNormal;
			calculateDecalRotation(gameScene, *resultPosition, *resultRotation, 0.f, fooNormal);
		}

		// now check that we're still inside map boundaries
		if (!gameMap->isWellInScaledBoundaries(resultPosition->x, resultPosition->z))
		{
			// out of map.
			return false;
		}

		// then fix decal height to ground height
		if (positioning == DecalPositionCalculator::DECAL_POSITIONING_DOWNWARD
			|| positioning == DecalPositionCalculator::DECAL_POSITIONING_VELOCITY)
		{
			if (!hitWall)
			{
				resultPosition->y = gameMap->getScaledHeightAt(resultPosition->x, resultPosition->z);
			}
		}

		// check that not on top of metal grid area...
		if (game::MaterialManager::isMaterialUnderPosition(gameMap, 
			*resultPosition, MATERIAL_METAL_GRATE))
		{
			// on top of grid, no decal here.
			return false;
		}

		// TODO: check that not inside a wall, terrainobject, etc.
		// if so, return false

		return true;
	}