void CBeamLaser::Update(void)
{
	if(targetType!=Target_None){
		weaponPos=owner->pos+owner->frontdir*relWeaponPos.z+owner->updir*relWeaponPos.y+owner->rightdir*relWeaponPos.x;
		if(!onlyForward){
			wantedDir=targetPos-weaponPos;
			wantedDir.Normalize();
		}
		predict=salvoSize/2;
	}
	CWeapon::Update();

	if(lastFireFrame > gs->frameNum - 18 && lastFireFrame != gs->frameNum  && weaponDef->sweepFire)
	{
		if (gs->Team(owner->team)->metal>=metalFireCost && gs->Team(owner->team)->energy>=energyFireCost)
		{
			owner->UseEnergy(energyFireCost / salvoSize);
			owner->UseMetal(metalFireCost / salvoSize);

			std::vector<int> args;
			args.push_back(0);
			owner->cob->Call(COBFN_QueryPrimary+weaponNum,args);
			CMatrix44f weaponMat = owner->localmodel->GetPieceMatrix(args[0]);

			float3 relWeaponPos = weaponMat.GetPos();
			weaponPos=owner->pos+owner->frontdir*-relWeaponPos.z+owner->updir*relWeaponPos.y+owner->rightdir*-relWeaponPos.x;

			float3 dir = owner->frontdir * weaponMat[10] + owner->updir * weaponMat[6] + -owner->rightdir * weaponMat[2];
			FireInternal(dir, true);
		}
	}
}
float3 LocalS3DOModel::GetRawPiecePos(int piecenum) const
{
	CMatrix44f mat;
	pieces[piecenum].GetPiecePosIter(&mat);

	// stupid fix for valkyres
	const S3DO* p3do = pieces[piecenum].original3do;
	if (p3do && (p3do->vertices.size() == 2)) {
		const std::vector<S3DOVertex>& pv = p3do->vertices;
		if (pv[0].pos.y > pv[1].pos.y) {
			mat.Translate(pv[0].pos.x, pv[0].pos.y, -pv[0].pos.z);
		} else {
			mat.Translate(pv[1].pos.x, pv[1].pos.y, -pv[1].pos.z);
		}
	}

/*
	logOutput.Print("%f %f %f %f",mat[0],mat[4],mat[8],mat[12]);
	logOutput.Print("%f %f %f %f",mat[1],mat[5],mat[9],mat[13]);
	logOutput.Print("%f %f %f %f",mat[2],mat[6],mat[10],mat[14]);
	logOutput.Print("%f %f %f %f",mat[3],mat[7],mat[11],mat[15]);/**/
	float3 pos = mat.GetPos();
	pos.z *= -1.0f;
	pos.x *= -1.0f;

	return pos;
}
Example #3
0
void CBeamLaser::UpdatePosAndMuzzlePos()
{
	if (sweepFireState.IsSweepFiring()) {
		const int weaponPiece = owner->script->QueryWeapon(weaponNum);
		const CMatrix44f weaponMat = owner->script->GetPieceMatrix(weaponPiece);

		const float3 relWeaponPos = weaponMat.GetPos();
		const float3 newWeaponDir = owner->GetObjectSpaceVec(float3(weaponMat[2], weaponMat[6], weaponMat[10]));

		relWeaponMuzzlePos = owner->script->GetPiecePos(weaponPiece);

		weaponPos = owner->GetObjectSpacePos(relWeaponPos * float3(-1.0f, 1.0f, -1.0f)); // ??
		weaponMuzzlePos = owner->GetObjectSpacePos(relWeaponMuzzlePos);

		sweepFireState.SetSweepTempDir(newWeaponDir);
	} else {
		weaponPos = owner->GetObjectSpacePos(relWeaponPos);
		weaponMuzzlePos = owner->GetObjectSpacePos(relWeaponMuzzlePos);

		if (weaponDef->sweepFire) {
			// needed for first call to GetFireDir() when new sweep starts after inactivity
			sweepFireState.SetSweepTempDir((weaponMuzzlePos - weaponPos).SafeNormalize());
		}
	}
}
Example #4
0
static void DrawUnitDebugPieceTree(const LocalModelPiece* p, const LocalModelPiece* lap, int lapf, CMatrix44f mat)
{
	mat.Translate(p->pos.x, p->pos.y, p->pos.z);
	mat.RotateY(-p->rot[1]);
	mat.RotateX(-p->rot[0]);
	mat.RotateZ(-p->rot[2]);

	glPushMatrix();
		glMultMatrixf(mat.m);

		if (p->visible && !p->GetCollisionVolume()->IsDisabled()) {
			if ((p == lap) && (lapf > 0 && ((gs->frameNum - lapf) < 150))) {
				glColor3f((1.0f - ((gs->frameNum - lapf) / 150.0f)), 0.0f, 0.0f);
			}

			DrawCollisionVolume(p->GetCollisionVolume());

			if ((p == lap) && (lapf > 0 && ((gs->frameNum - lapf) < 150))) {
				glColorf3(defaultColVolColor);
			}
		}
	glPopMatrix();

	for (unsigned int i = 0; i < p->childs.size(); i++) {
		DrawUnitDebugPieceTree(p->childs[i], lap, lapf, mat);
	}
}
Example #5
0
bool CCollisionHandler::Collision(const CUnit* u, const float3& p)
{
	const CollisionVolume* v = u->collisionVolume;

	if (((u->midPos + v->GetOffsets()) - p).SqLength() > v->GetBoundingRadiusSq()) {
		return false;
	}

	switch (u->collisionVolume->GetVolumeType()) {
		case CollisionVolume::COLVOL_TYPE_SPHERE: {
			return true;
		}
		case CollisionVolume::COLVOL_TYPE_FOOTPRINT: {
			return CCollisionHandler::CollisionFootprint(u, p);
		}
		default: {
			// NOTE: we have to translate by relMidPos to get to midPos
			// (which is where the collision volume gets drawn) because
			// GetTransformMatrix() only uses pos
			CMatrix44f m = u->GetTransformMatrix(true);
			m.Translate(u->relMidPos * float3(-1.0f, 1.0f, 1.0f));
			m.Translate(v->GetOffsets());

			return CCollisionHandler::Collision(v, m, p);
		}
	}
}
// test if ray from <p0> to <p1> (in world-coors) intersects
// the volume whose transformation matrix is given by <m>
bool CCollisionHandler::Intersect(const CollisionVolume* v, const CMatrix44f& m, const float3& p0, const float3& p1, CollisionQuery* q)
{
	CMatrix44f mInv = m.Invert();
	const float3 pi0 = mInv.Mul(p0);
	const float3 pi1 = mInv.Mul(p1);
	bool intersect = false;

	// minimum and maximum (x, y, z) coordinates of transformed ray
	const float rminx = MIN(pi0.x, pi1.x), rminy = MIN(pi0.y, pi1.y), rminz = MIN(pi0.z, pi1.z);
	const float rmaxx = MAX(pi0.x, pi1.x), rmaxy = MAX(pi0.y, pi1.y), rmaxz = MAX(pi0.z, pi1.z);

	// minimum and maximum (x, y, z) coordinates of (bounding box around) volume
	const float vminx = -v->axisHScales.x, vminy = -v->axisHScales.y, vminz = -v->axisHScales.z;
	const float vmaxx =  v->axisHScales.x, vmaxy =  v->axisHScales.y, vmaxz =  v->axisHScales.z;

	// check if ray segment misses (bounding box around) volume
	// (if so, then no further intersection tests are necessary)
	if (rmaxx < vminx || rminx > vmaxx) { return false; }
	if (rmaxy < vminy || rminy > vmaxy) { return false; }
	if (rmaxz < vminz || rminz > vmaxz) { return false; }

	switch (v->volumeType) {
		case COLVOL_TYPE_ELLIPSOID: {
			intersect = CCollisionHandler::IntersectEllipsoid(v, pi0, pi1, q);
		} break;
		case COLVOL_TYPE_CYLINDER: {
			intersect = CCollisionHandler::IntersectCylinder(v, pi0, pi1, q);
		} break;
		case COLVOL_TYPE_BOX: {
			intersect = CCollisionHandler::IntersectBox(v, pi0, pi1, q);
		} break;
	}

	return intersect;
}
Example #7
0
bool CCollisionHandler::IntersectPieceTree(const CUnit* u, const float3& p0, const float3& p1, CollisionQuery* q)
{
	std::list<CollisionQuery> hits;
	std::list<CollisionQuery>::const_iterator hitsIt;

	// this probably needs an early-out test
	CMatrix44f mat = u->GetTransformMatrix(true);
	mat.Translate(u->relMidPos * float3(-1.0f, 0.0f, 1.0f));

	IntersectPieceTreeHelper(u->localmodel->GetRoot(), mat, p0, p1, &hits);

	float dstNearSq = 1e30f;

	// save the closest intersection
	for (hitsIt = hits.begin(); hitsIt != hits.end(); ++hitsIt) {
		const CollisionQuery& qTmp = *hitsIt;
		const float dstSq = (qTmp.p0 - p0).SqLength();

		if (q != NULL && dstSq < dstNearSq) {
			dstNearSq = dstSq;

			q->b0 = qTmp.b0; q->t0 = qTmp.t0; q->p0 = qTmp.p0;
			q->b1 = qTmp.b1; q->t1 = qTmp.t1; q->p1 = qTmp.p1;

			q->lmp = qTmp.lmp;
		}
	}

	return (!hits.empty());
}
float3 LocalS3DOModel::GetPiecePos(int piecenum)
{
	if(piecenum>=numpieces || piecenum<0)
		return ZeroVector;

	int p=scritoa[piecenum];

	if(p==-1)
		return ZeroVector;

	CMatrix44f mat;
	pieces[p].GetPiecePosIter(&mat);
	if(pieces[p].original3do && pieces[p].original3do->vertices.size()==2){		//stupid fix for valkyres
		if(pieces[p].original3do->vertices[0].pos.y > pieces[p].original3do->vertices[1].pos.y)
			mat.Translate(pieces[p].original3do->vertices[0].pos.x, pieces[p].original3do->vertices[0].pos.y, -pieces[p].original3do->vertices[0].pos.z);
		else
			mat.Translate(pieces[p].original3do->vertices[1].pos.x, pieces[p].original3do->vertices[1].pos.y, -pieces[p].original3do->vertices[1].pos.z);
	}

/*
	logOutput.Print("%f %f %f %f",mat[0],mat[4],mat[8],mat[12]);
	logOutput.Print("%f %f %f %f",mat[1],mat[5],mat[9],mat[13]);
	logOutput.Print("%f %f %f %f",mat[2],mat[6],mat[10],mat[14]);
	logOutput.Print("%f %f %f %f",mat[3],mat[7],mat[11],mat[15]);/**/
	float3 pos=mat.GetPos();
	pos.z*=-1;
	pos.x*=-1;

	return pos;
	//return UpVector;
}
Example #9
0
static void DrawUnitDebugPieceTree(const LocalModelPiece* p, const LocalModelPiece* lap, int lapf, CMatrix44f mat)
{
	const float3& rot = p->GetRotation();
	mat.Translate(p->GetPosition());
	mat.RotateY(-rot[1]);
	mat.RotateX(-rot[0]);
	mat.RotateZ(-rot[2]);

	glPushMatrix();
		glMultMatrixf(mat.m);

		if (p->scriptSetVisible && !p->GetCollisionVolume()->IgnoreHits()) {
			if ((p == lap) && (lapf > 0 && ((gs->frameNum - lapf) < 150))) {
				glColor3f((1.0f - ((gs->frameNum - lapf) / 150.0f)), 0.0f, 0.0f);
			}

			DrawCollisionVolume(p->GetCollisionVolume());

			if ((p == lap) && (lapf > 0 && ((gs->frameNum - lapf) < 150))) {
				glColorf3(DEFAULT_VOLUME_COLOR);
			}
		}
	glPopMatrix();

	for (unsigned int i = 0; i < p->children.size(); i++) {
		DrawUnitDebugPieceTree(p->children[i], lap, lapf, mat);
	}
}
Example #10
0
//! generalized inverse for non-orthonormal 4x4 matrices
//! A^-1 = (1 / det(A)) (C^T)_{ij} = (1 / det(A)) C_{ji}
CMatrix44f CMatrix44f::Invert(bool* status) const
{
	CMatrix44f mat;
	CMatrix44f& cofac = mat;

	for (int i = 0; i < 4; i++) {
		for (int j = 0; j < 4; j++) {
			cofac.md[i][j] = CalculateCofactor(md, i, j);
		}
	}

	const float det =
		(md[0][0] * cofac.md[0][0]) +
		(md[0][1] * cofac.md[0][1]) +
		(md[0][2] * cofac.md[0][2]) +
		(md[0][3] * cofac.md[0][3]);

	if (det == 0.0f) {
		//! singular matrix, set to identity?
		mat.LoadIdentity();
		if (status) *status = false;
		return mat;
	}

	mat *= 1.f / det;
	mat.Transpose();

	if (status) *status = true;
	return mat;
}
Example #11
0
bool CCollisionHandler::MouseHit(const CUnit* u, const float3& p0, const float3& p1, const CollisionVolume* v, CollisionQuery* q)
{
	// note: use the piece tree?
	CMatrix44f m = u->GetTransformMatrix(false, true);
	m.Translate(u->relMidPos + v->GetOffsets());

	return CCollisionHandler::Intersect(v, m, p0, p1, q);
}
Example #12
0
inline bool CCollisionHandler::Intersect(const CollisionVolume* v, const CSolidObject* o, const float3 p0, const float3 p1, CollisionQuery* cq)
{
	CMatrix44f m = o->GetTransformMatrix(true);
	m.Translate(o->relMidPos * WORLD_TO_OBJECT_SPACE);
	m.Translate(v->GetOffsets());

	return (CCollisionHandler::Intersect(v, m, p0, p1, cq));
}
Example #13
0
bool CCollisionHandler::Collision(const CollisionVolume* v, const CMatrix44f& m, const float3& p)
{
	numDiscTests += 1;

	// get the inverse volume transformation matrix and
	// apply it to the projectile's position, then test
	// if the transformed position lies within the axis-
	// aligned collision volume
	CMatrix44f mInv = m.Invert();
	float3 pi = mInv.Mul(p);

	bool hit = false;

	switch (v->GetVolumeType()) {
		case CollisionVolume::COLVOL_TYPE_SPHERE: {
			// normally, this code is never executed, because the higher level
			// Collision(CFeature*) and Collision(CUnit*) already optimize via
			// early-out tests
			hit = (pi.dot(pi) <= v->GetHSqScales().x);

			// test for arbitrary ellipsoids (no longer supported)
			// const float f1 = (pi.x * pi.x) / v->GetHSqScales().x;
			// const float f2 = (pi.y * pi.y) / v->GetHSqScales().y;
			// const float f3 = (pi.z * pi.z) / v->GetHSqScales().z;
			// hit = ((f1 + f2 + f3) <= 1.0f);
		} break;
		case CollisionVolume::COLVOL_TYPE_CYLINDER: {
			switch (v->GetPrimaryAxis()) {
				case CollisionVolume::COLVOL_AXIS_X: {
					const bool xPass = (math::fabs(pi.x) < v->GetHScales().x);
					const float yRat = (pi.y * pi.y) / v->GetHSqScales().y;
					const float zRat = (pi.z * pi.z) / v->GetHSqScales().z;
					hit = (xPass && (yRat + zRat <= 1.0f));
				} break;
				case CollisionVolume::COLVOL_AXIS_Y: {
					const bool yPass = (math::fabs(pi.y) < v->GetHScales().y);
					const float xRat = (pi.x * pi.x) / v->GetHSqScales().x;
					const float zRat = (pi.z * pi.z) / v->GetHSqScales().z;
					hit = (yPass && (xRat + zRat <= 1.0f));
				} break;
				case CollisionVolume::COLVOL_AXIS_Z: {
					const bool zPass = (math::fabs(pi.z) < v->GetHScales().z);
					const float xRat = (pi.x * pi.x) / v->GetHSqScales().x;
					const float yRat = (pi.y * pi.y) / v->GetHSqScales().y;
					hit = (zPass && (xRat + yRat <= 1.0f));
				} break;
			}
		} break;
		case CollisionVolume::COLVOL_TYPE_BOX: {
			const bool b1 = (math::fabs(pi.x) < v->GetHScales().x);
			const bool b2 = (math::fabs(pi.y) < v->GetHScales().y);
			const bool b3 = (math::fabs(pi.z) < v->GetHScales().z);
			hit = (b1 && b2 && b3);
		} break;
	}

	return hit;
}
Example #14
0
float CollisionVolume::GetPointSurfaceDistance(const CFeature* f, const LocalModelPiece* /*lmp*/, const float3& p) const {
	CMatrix44f mat = f->GetTransformMatrixRef();

	mat.Translate(f->relMidPos * WORLD_TO_OBJECT_SPACE);
	mat.Translate(GetOffsets());
	mat.InvertAffineInPlace();

	return (GetPointSurfaceDistance(mat, p));
}
void CBeamLaser::Update(void)
{
	if (targetType != Target_None) {
		weaponPos =
			owner->pos +
			owner->frontdir * relWeaponPos.z +
			owner->updir    * relWeaponPos.y +
			owner->rightdir * relWeaponPos.x;
		weaponMuzzlePos =
			owner->pos +
			owner->frontdir * relWeaponMuzzlePos.z +
			owner->updir    * relWeaponMuzzlePos.y +
			owner->rightdir * relWeaponMuzzlePos.x;

		if (!onlyForward) {
			wantedDir = targetPos - weaponPos;
			wantedDir.ANormalize();
		}

		if (!weaponDef->beamburst) {
			predict = salvoSize / 2;
		} else {
 			// beamburst tracks the target during the burst so there's no need to lead
			predict = 0;
		}
	}
	CWeapon::Update();

	if (lastFireFrame > gs->frameNum - 18 && lastFireFrame != gs->frameNum  && weaponDef->sweepFire) {
		if (teamHandler->Team(owner->team)->metal >= metalFireCost &&
			teamHandler->Team(owner->team)->energy >= energyFireCost) {

			owner->UseEnergy(energyFireCost / salvoSize);
			owner->UseMetal(metalFireCost / salvoSize);

			std::vector<int> args;
			args.push_back(0);
			owner->cob->Call(COBFN_QueryPrimary + weaponNum, args);
			CMatrix44f weaponMat = owner->cob->GetPieceMatrix(args[0]);

			const float3 relWeaponPos = weaponMat.GetPos();
			const float3 dir =
				owner->frontdir *  weaponMat[10] +
				owner->updir    *  weaponMat[ 6] +
				owner->rightdir * -weaponMat[ 2];

			weaponPos =
				owner->pos +
				owner->frontdir * -relWeaponPos.z +
				owner->updir    *  relWeaponPos.y +
				owner->rightdir * -relWeaponPos.x;

			FireInternal(dir, true);
		}
	}
}
Example #16
0
void CCamera::Pitch(float rad)
{
    CMatrix44f rotate;
    rotate.Rotate(rad, right);
    forward = rotate.Mul(forward);
    forward.Normalize();
    rot.y = atan2(forward.x,forward.z);
    rot.x = asin(forward.y);
    UpdateForward();
}
Example #17
0
bool CCollisionHandler::Intersect(const CUnit* u, const float3& p0, const float3& p1, CollisionQuery* q)
{
	const CollisionVolume* v = u->collisionVolume;

	CMatrix44f m = u->GetTransformMatrix(true);
	m.Translate(u->relMidPos * float3(-1.0f, 1.0f, 1.0f));
	m.Translate(v->GetOffsets());

	return CCollisionHandler::Intersect(v, m, p0, p1, q);
}
Example #18
0
bool CCollisionHandler::Collision(const CollisionVolume* v, const CMatrix44f& m, const float3& p)
{
	// get the inverse volume transformation matrix and
	// apply it to the projectile's position, then test
	// if the transformed position lies within the axis-
	// aligned collision volume
	CMatrix44f mInv = m.Invert();
	float3 pi = mInv.Mul(p);
	bool hit = false;

	switch (v->GetVolumeType()) {
		case CollisionVolume::COLVOL_TYPE_SPHERE: {
			// normally, this code is never executed, because the higher level
			// Collision(CFeature*) and Collision(CUnit*) already optimize
			// for volumeType == CollisionVolume::COLVOL_TYPE_SPHERE.
			hit = (pi.dot(pi) <= v->GetHScalesSq().x);
		} break;
		case CollisionVolume::COLVOL_TYPE_ELLIPSOID: {
			const float f1 = (pi.x * pi.x) / v->GetHScalesSq().x;
			const float f2 = (pi.y * pi.y) / v->GetHScalesSq().y;
			const float f3 = (pi.z * pi.z) / v->GetHScalesSq().z;
			hit = ((f1 + f2 + f3) <= 1.0f);
		} break;
		case CollisionVolume::COLVOL_TYPE_CYLINDER: {
			switch (v->GetPrimaryAxis()) {
				case CollisionVolume::COLVOL_AXIS_X: {
					const bool xPass = (pi.x > -v->GetHScales().x  &&  pi.x < v->GetHScales().x);
					const float yRat = (pi.y * pi.y) / v->GetHScalesSq().y;
					const float zRat = (pi.z * pi.z) / v->GetHScalesSq().z;
					hit = (xPass && (yRat + zRat <= 1.0f));
				} break;
				case CollisionVolume::COLVOL_AXIS_Y: {
					const bool yPass = (pi.y > -v->GetHScales().y  &&  pi.y < v->GetHScales().y);
					const float xRat = (pi.x * pi.x) / v->GetHScalesSq().x;
					const float zRat = (pi.z * pi.z) / v->GetHScalesSq().z;
					hit = (yPass && (xRat + zRat <= 1.0f));
				} break;
				case CollisionVolume::COLVOL_AXIS_Z: {
					const bool zPass = (pi.z > -v->GetHScales().z  &&  pi.z < v->GetHScales().z);
					const float xRat = (pi.x * pi.x) / v->GetHScalesSq().x;
					const float yRat = (pi.y * pi.y) / v->GetHScalesSq().y;
					hit = (zPass && (xRat + yRat <= 1.0f));
				} break;
			}
		} break;
		case CollisionVolume::COLVOL_TYPE_BOX: {
			const bool b1 = (pi.x > -v->GetHScales().x  &&  pi.x < v->GetHScales().x);
			const bool b2 = (pi.y > -v->GetHScales().y  &&  pi.y < v->GetHScales().y);
			const bool b3 = (pi.z > -v->GetHScales().z  &&  pi.z < v->GetHScales().z);
			hit = (b1 && b2 && b3);
		} break;
	}

	return hit;
}
bool CCollisionHandler::Intersect(const CUnit* u, const float3& p0, const float3& p1, CollisionQuery* q)
{
	const CollisionVolume* v = u->collisionVolume;

	CMatrix44f m;
	u->GetTransformMatrix(m, true);
	m.Translate(u->relMidPos.x, u->relMidPos.y, u->relMidPos.z);
	m.Translate(v->axisOffsets.x, v->axisOffsets.y, v->axisOffsets.z);

	return CCollisionHandler::Intersect(v, m, p0, p1, q);
}
// test if point <p> (in world-coors) lies inside the
// volume whose transformation matrix is given by <m>
bool CCollisionHandler::Collision(const CollisionVolume* v, const CMatrix44f& m, const float3& p)
{
	// get the inverse volume transformation matrix and
	// apply it to the projectile's position, then test
	// if the transformed position lies within the axis-
	// aligned collision volume
	CMatrix44f mInv = m.Invert();
	float3 pi = mInv.Mul(p);
	bool hit = false;

	switch (v->volumeType) {
		case COLVOL_TYPE_ELLIPSOID: {
			if (v->spherical) {
				hit = (pi.dot(pi) <= v->axisHScalesSq.x);
			} else {
				const float f1 = (pi.x * pi.x) / v->axisHScalesSq.x;
				const float f2 = (pi.y * pi.y) / v->axisHScalesSq.y;
				const float f3 = (pi.z * pi.z) / v->axisHScalesSq.z;
				hit = ((f1 + f2 + f3) <= 1.0f);
			}
		} break;
		case COLVOL_TYPE_CYLINDER: {
			switch (v->primaryAxis) {
				case COLVOL_AXIS_X: {
					const bool xPass = (pi.x > -v->axisHScales.x  &&  pi.x < v->axisHScales.x);
					const float yRat = (pi.y * pi.y) / v->axisHScalesSq.y;
					const float zRat = (pi.z * pi.z) / v->axisHScalesSq.z;
					hit = (xPass && (yRat + zRat <= 1.0f));
				} break;
				case COLVOL_AXIS_Y: {
					const bool yPass = (pi.y > -v->axisHScales.y  &&  pi.y < v->axisHScales.y);
					const float xRat = (pi.x * pi.x) / v->axisHScalesSq.x;
					const float zRat = (pi.z * pi.z) / v->axisHScalesSq.z;
					hit = (yPass && (xRat + zRat <= 1.0f));
				} break;
				case COLVOL_AXIS_Z: {
					const bool zPass = (pi.z > -v->axisHScales.z  &&  pi.z < v->axisHScales.z);
					const float xRat = (pi.x * pi.x) / v->axisHScalesSq.x;
					const float yRat = (pi.y * pi.y) / v->axisHScalesSq.y;
					hit = (zPass && (xRat + yRat <= 1.0f));
				} break;
			}
		} break;
		case COLVOL_TYPE_BOX: {
			const bool b1 = (pi.x > -v->axisHScales.x  &&  pi.x < v->axisHScales.x);
			const bool b2 = (pi.y > -v->axisHScales.y  &&  pi.y < v->axisHScales.y);
			const bool b3 = (pi.z > -v->axisHScales.z  &&  pi.z < v->axisHScales.z);
			hit = (b1 && b2 && b3);
		} break;
	}

	return hit;
}
Example #21
0
float3 LocalModelPiece::GetAbsolutePos() const
{
	CMatrix44f mat;
	GetPiecePosIter(&mat);

	mat.Translate(original->GetPosOffset());

	//! we use a 'right' vector, and the positive x axis points to the left
	float3 pos = mat.GetPos();
	pos.x = -pos.x;
	return pos;
}
void CShadowHandler::SetShadowMatrix(CCamera* playerCam, CCamera* shadowCam)
{
	const CMatrix44f lightMatrix = std::move(ComposeLightMatrix(sky->GetLight()));
	const CMatrix44f scaleMatrix = std::move(ComposeScaleMatrix(GetShadowProjectionScales(playerCam, -lightMatrix.GetZ())));

	// convert xy-diameter to radius
	shadowCam->SetFrustumScales(shadowProjScales * float4(0.5f, 0.5f, 1.0f, 1.0f));

	#if 0
	// reshape frustum (to maximize SM resolution); for culling we want
	// the scales-matrix applied to projMatrix instead of to viewMatrix
	// ((V*S) * P = V * (S*P); note that S * P is a pre-multiplication
	// so we express it as P * S in code)
	projMatrix[SHADOWMAT_TYPE_CULLING] = projMatrix[SHADOWMAT_TYPE_DRAWING];
	projMatrix[SHADOWMAT_TYPE_CULLING] *= scaleMatrix;

	// frustum-culling needs this form
	viewMatrix[SHADOWMAT_TYPE_CULLING].LoadIdentity();
	viewMatrix[SHADOWMAT_TYPE_CULLING].SetX(std::move(lightMatrix.GetX()));
	viewMatrix[SHADOWMAT_TYPE_CULLING].SetY(std::move(lightMatrix.GetY()));
	viewMatrix[SHADOWMAT_TYPE_CULLING].SetZ(std::move(lightMatrix.GetZ()));
	viewMatrix[SHADOWMAT_TYPE_CULLING].Transpose(); // invert rotation (R^T == R^{-1})
	viewMatrix[SHADOWMAT_TYPE_CULLING].Translate(-projMidPos[2]); // same as SetPos(mat * -pos)
	#else
	// KISS; define only the world-to-light transform (P[CULLING] is unused anyway)
	//
	// we have two options: either place the camera such that it *looks at* projMidPos
	// (along lightMatrix.GetZ()) or such that it is *at or behind* projMidPos looking
	// in the inverse direction (the latter is chosen here)
	viewMatrix[SHADOWMAT_TYPE_CULLING].LoadIdentity();
	viewMatrix[SHADOWMAT_TYPE_CULLING].SetX(-std::move(lightMatrix.GetX()));
	viewMatrix[SHADOWMAT_TYPE_CULLING].SetY( std::move(lightMatrix.GetY()));
	viewMatrix[SHADOWMAT_TYPE_CULLING].SetZ(-std::move(lightMatrix.GetZ()));
	viewMatrix[SHADOWMAT_TYPE_CULLING].SetPos(projMidPos[2]);
	#endif

	// shaders need this form, projection into SM-space is done by shadow2DProj()
	// note: ShadowGenVertProg is a special case because it does not use uniforms
	viewMatrix[SHADOWMAT_TYPE_DRAWING].LoadIdentity();
	viewMatrix[SHADOWMAT_TYPE_DRAWING].SetX(std::move(lightMatrix.GetX()));
	viewMatrix[SHADOWMAT_TYPE_DRAWING].SetY(std::move(lightMatrix.GetY()));
	viewMatrix[SHADOWMAT_TYPE_DRAWING].SetZ(std::move(lightMatrix.GetZ()));
	viewMatrix[SHADOWMAT_TYPE_DRAWING].Scale(float3(scaleMatrix[0], scaleMatrix[5], scaleMatrix[10])); // extract (X.x, Y.y, Z.z)
	viewMatrix[SHADOWMAT_TYPE_DRAWING].Transpose();
	viewMatrix[SHADOWMAT_TYPE_DRAWING].SetPos(viewMatrix[SHADOWMAT_TYPE_DRAWING] * -projMidPos[2]);
	viewMatrix[SHADOWMAT_TYPE_DRAWING].SetPos(viewMatrix[SHADOWMAT_TYPE_DRAWING].GetPos() + (FwdVector * 0.5f)); // add z-bias

	#if 0
	// holds true in the non-KISS case, but needs an epsilon-tolerance equality test
	assert((viewMatrix[0] * projMatrix[0]) == (viewMatrix[1] * projMatrix[1]));
	#endif
}
Example #23
0
bool CCollisionHandler::Intersect(const CollisionVolume* v, const CMatrix44f& m, const float3& p0, const float3& p1, CollisionQuery* q)
{
	if (q) {
		// reset the query
		q->b0 = false; q->t0 = 0.0f; q->p0 = ZVEC;
		q->b1 = false; q->t1 = 0.0f; q->p1 = ZVEC;
	}

	CMatrix44f mInv = m.Invert();
	const float3 pi0 = mInv.Mul(p0);
	const float3 pi1 = mInv.Mul(p1);
	bool intersect = false;

	// minimum and maximum (x, y, z) coordinates of transformed ray
	const float rminx = std::min(pi0.x, pi1.x), rminy = std::min(pi0.y, pi1.y), rminz = std::min(pi0.z, pi1.z);
	const float rmaxx = std::max(pi0.x, pi1.x), rmaxy = std::max(pi0.y, pi1.y), rmaxz = std::max(pi0.z, pi1.z);

	// minimum and maximum (x, y, z) coordinates of (bounding box around) volume
	const float vminx = -v->GetHScales().x, vminy = -v->GetHScales().y, vminz = -v->GetHScales().z;
	const float vmaxx =  v->GetHScales().x, vmaxy =  v->GetHScales().y, vmaxz =  v->GetHScales().z;

	// check if ray segment misses (bounding box around) volume
	// (if so, then no further intersection tests are necessary)
	if (rmaxx < vminx || rminx > vmaxx) { return false; }
	if (rmaxy < vminy || rminy > vmaxy) { return false; }
	if (rmaxz < vminz || rminz > vmaxz) { return false; }

	switch (v->GetVolumeType()) {
		case CollisionVolume::COLVOL_TYPE_FOOTPRINT:
			// fall through, intersection with footprint collision volume
			// is not supported yet, so only test against sphere/ellipsoid
		case CollisionVolume::COLVOL_TYPE_SPHERE:
			// fall through, sphere is special case of ellipsoid
		case CollisionVolume::COLVOL_TYPE_ELLIPSOID: {
			intersect = CCollisionHandler::IntersectEllipsoid(v, pi0, pi1, q);
		} break;
		case CollisionVolume::COLVOL_TYPE_CYLINDER: {
			intersect = CCollisionHandler::IntersectCylinder(v, pi0, pi1, q);
		} break;
		case CollisionVolume::COLVOL_TYPE_BOX: {
			intersect = CCollisionHandler::IntersectBox(v, pi0, pi1, q);
		} break;
	}

	if (q) {
		// transform the intersection points
		if (q->b0) { q->p0 = m.Mul(q->p0); }
		if (q->b1) { q->p1 = m.Mul(q->p1); }
	}

	return intersect;
}
Example #24
0
static inline std::array<float2, 4> GetEdgePoinsOfDecal(const CDecalsDrawerGL4::Decal& d)
{
	CMatrix44f m;
	m.RotateY(d.rot);
	auto f3tof2 = [](float3 f3) { return float2(f3.x, f3.z); };

	return {
		f3tof2(d.pos + m * float3(-d.size.x, 0.f, -d.size.y)),
		f3tof2(d.pos + m * float3(-d.size.x, 0.f,  d.size.y)),
		f3tof2(d.pos + m * float3( d.size.x, 0.f,  d.size.y)),
		f3tof2(d.pos + m * float3( d.size.x, 0.f, -d.size.y))
	};
}
void CPieceProjectile::Update()
{
	if (flags & PP_Fall)
		speed.y += gs->gravity;
/*	speed.x *= 0.994f;
	speed.z *= 0.994f;
	if(speed.y > 0)
		speed.y *= 0.998f;*/
	speed*=0.997f;
	pos += speed;
	spinPos+=spinSpeed;

	*numCallback=0;
	if ((flags & PP_Fire && HasVertices() )/* && (gs->frameNum & 1)*/) {
		ENTER_MIXED;
		OldInfo* tempOldInfo=oldInfos[7];
		for(int a=6;a>=0;--a){
			oldInfos[a+1]=oldInfos[a];
		}
		CMatrix44f m;
		m.Translate(pos.x,pos.y,pos.z);
		m.Rotate(spinPos*PI/180,spinVec);
		float3 pos=RandomVertexPos();
		m.Translate(pos.x,pos.y,pos.z);

		oldInfos[0]=tempOldInfo;
		oldInfos[0]->pos=m.GetPos();
		oldInfos[0]->size=gu->usRandFloat()*1+1;
		ENTER_SYNCED;
	}

	age++;
	if(!(age & 7) && (flags & PP_Smoke)){
		float3 dir=speed;
		dir.Normalize();
		if(curCallback)
			curCallback->drawCallbacker=0;
		curCallback=SAFE_NEW CSmokeTrailProjectile(pos,oldSmoke,dir,oldSmokeDir,owner,age==8,false,14,Smoke_Time,0.5f,drawTrail,this);
		useAirLos=curCallback->useAirLos;
		oldSmoke=pos;
		oldSmokeDir=dir;
		if(!drawTrail){
			float3 camDir=(pos-camera->pos).Normalize();
			if(camera->pos.distance(pos)+(1-fabs(camDir.dot(dir)))*3000 > 300)
				drawTrail=true;
		}
	}
	if(age>10)
		checkCol=true;
}
Example #26
0
bool CCollisionHandler::Intersect(const CollisionVolume* v, const CMatrix44f& m, const float3& p0, const float3& p1, CollisionQuery* q)
{
	numContTests += 1;

	CMatrix44f mInv = m.Invert();
	const float3 pi0 = mInv.Mul(p0);
	const float3 pi1 = mInv.Mul(p1);
	bool intersect = false;

	// minimum and maximum (x, y, z) coordinates of transformed ray
	const float rminx = std::min(pi0.x, pi1.x), rminy = std::min(pi0.y, pi1.y), rminz = std::min(pi0.z, pi1.z);
	const float rmaxx = std::max(pi0.x, pi1.x), rmaxy = std::max(pi0.y, pi1.y), rmaxz = std::max(pi0.z, pi1.z);

	// minimum and maximum (x, y, z) coordinates of (bounding box around) volume
	const float vminx = -v->GetHScales().x, vminy = -v->GetHScales().y, vminz = -v->GetHScales().z;
	const float vmaxx =  v->GetHScales().x, vmaxy =  v->GetHScales().y, vmaxz =  v->GetHScales().z;

	// check if ray segment misses (bounding box around) volume
	// (if so, then no further intersection tests are necessary)
	if (rmaxx < vminx || rminx > vmaxx) { return false; }
	if (rmaxy < vminy || rminy > vmaxy) { return false; }
	if (rmaxz < vminz || rminz > vmaxz) { return false; }

	switch (v->GetVolumeType()) {
		case CollisionVolume::COLVOL_TYPE_SPHERE: {
			// sphere is special case of ellipsoid, reuse code
			intersect = CCollisionHandler::IntersectEllipsoid(v, pi0, pi1, q);
		} break;
		case CollisionVolume::COLVOL_TYPE_CYLINDER: {
			intersect = CCollisionHandler::IntersectCylinder(v, pi0, pi1, q);
		} break;
		case CollisionVolume::COLVOL_TYPE_BOX: {
			// also covers footprints, but without taking the blocking-map into account
			// TODO: this would require stepping ray across non-blocking yardmap squares?
			//
			// intersect = CCollisionHandler::IntersectFootPrint(v, pi0, pi1, q);
			intersect = CCollisionHandler::IntersectBox(v, pi0, pi1, q);
		} break;
	}

	if (q != NULL) {
		// transform intersection points (iff not a special
		// case, otherwise calling code should not use them)
		if (q->b0 == CQ_POINT_ON_RAY) { q->p0 = m.Mul(q->p0); }
		if (q->b1 == CQ_POINT_ON_RAY) { q->p1 = m.Mul(q->p1); }
	}

	return intersect;
}
Example #27
0
bool CCollisionHandler::IntersectPiecesHelper(
	const CUnit* u,
	const float3& p0,
	const float3& p1,
	CollisionQuery* cq
) {
	CMatrix44f unitMat = u->GetTransformMatrix(true);
	CMatrix44f volMat;

	CollisionQuery cqt;

	if (cq == NULL)
		cq = &cqt;

	float minDistSq = std::numeric_limits<float>::max();
	float curDistSq = std::numeric_limits<float>::max();

	for (unsigned int n = 0; n < u->localModel->pieces.size(); n++) {
		const LocalModelPiece* lmp = u->localModel->GetPiece(n);
		const CollisionVolume* lmpVol = lmp->GetCollisionVolume();

		if (!lmp->scriptSetVisible || lmpVol->IgnoreHits())
			continue;

		volMat = unitMat * lmp->GetModelSpaceMatrix();
		volMat.Translate(lmpVol->GetOffsets());

		if (!CCollisionHandler::Intersect(lmpVol, volMat, p0, p1, cq))
			continue;
		// skip if neither an ingress nor an egress hit
		if (cq->GetHitPos() == ZeroVector)
			continue;

		cq->SetHitPiece(const_cast<LocalModelPiece*>(lmp));

		// save the closest intersection (others are not needed)
		if ((curDistSq = (cq->GetHitPos() - p0).SqLength()) >= minDistSq)
			continue;

		minDistSq = curDistSq;
	}

	// true iff at least one piece was intersected
	// (query must have been reset by calling code)
	return (cq->GetHitPiece() != NULL);
}
Example #28
0
// Iterate over the model and calculate its overall dimensions
void CAssParser::CalculateModelDimensions(S3DModel* model, S3DModelPiece* piece)
{
	CMatrix44f scaleRotMat;
	piece->ComposeTransform(scaleRotMat, ZeroVector, ZeroVector, piece->scales);

	// cannot set this until parent relations are known, so either here or in BuildPieceHierarchy()
	piece->goffset = scaleRotMat.Mul(piece->offset) + ((piece->parent != NULL)? piece->parent->goffset: ZeroVector);

	// update model min/max extents
	model->mins = float3::min(piece->goffset + piece->mins, model->mins);
	model->maxs = float3::max(piece->goffset + piece->maxs, model->maxs);

	piece->SetCollisionVolume(new CollisionVolume("box", piece->maxs - piece->mins, (piece->maxs + piece->mins) * 0.5f));

	// Repeat with children
	for (unsigned int i = 0; i < piece->children.size(); i++) {
		CalculateModelDimensions(model, piece->children[i]);
	}
}
Example #29
0
bool CCollisionHandler::MouseHit(const CUnit* u, const float3& p0, const float3& p1, const CollisionVolume* v, CollisionQuery* cq)
{
	if (!u->IsInVoid()) {
		if (v->DefaultToPieceTree()) {
			return (CCollisionHandler::IntersectPieceTree(u, p0, p1, cq));
		}
		if (!v->IgnoreHits()) {
			// note: should mouse-rays care about
			// IgnoreHits if unit is not in void?
			CMatrix44f m = u->GetTransformMatrix(false, true);
			m.Translate(u->relMidPos * WORLD_TO_OBJECT_SPACE);
			m.Translate(v->GetOffsets());

			return (CCollisionHandler::Intersect(v, m, p0, p1, cq));
		}
	}

	return false;
}
Example #30
0
static void DRAW_DECAL(CVertexArray* va, const CDecalsDrawerGL4::Decal* d)
{
	CMatrix44f m;
	m.Translate(d->pos.x, d->pos.z, 0.0f);
	m.RotateZ(d->rot * fastmath::DEG_TO_RAD);
	float2 dsize = d->size;
	// make sure it is at least 1x1 pixels!
	dsize.x = std::max(dsize.x, std::ceil( float(mapDims.mapx * SQUARE_SIZE) / CDecalsDrawerGL4::OVERLAP_TEST_TEXTURE_SIZE ));
	dsize.y = std::max(dsize.y, std::ceil( float(mapDims.mapy * SQUARE_SIZE) / CDecalsDrawerGL4::OVERLAP_TEST_TEXTURE_SIZE ));
	const float3 ds1 = float3(dsize.x,  dsize.y, 0.0f);
	const float3 ds2 = float3(dsize.x, -dsize.y, 0.0f);
	auto f3tof2 = [](float3 f3) { return *(float2*)&f3; };
	const float4 tc = d->texOffsets;

	va->EnlargeArrays(4, 0, VA_SIZE_2DT);
	va->AddVertexQ2dT(f3tof2(m * (-ds1)), float2(tc[0], tc[1]));
	va->AddVertexQ2dT(f3tof2(m * ( ds2)), float2(tc[2], tc[1]));
	va->AddVertexQ2dT(f3tof2(m * ( ds1)), float2(tc[2], tc[3]));
	va->AddVertexQ2dT(f3tof2(m * (-ds2)), float2(tc[0], tc[3]));
}