コード例 #1
0
ファイル: SimpleWindow.cpp プロジェクト: Yetta1/OpenTechBFG
void idSimpleWindow::SetupTransforms( float x, float y )
{
	static idMat3 trans;
	static idVec3 org;
	
	trans.Identity();
	org.Set( origin.x + x, origin.y + y, 0 );
	if( rotate )
	{
		static idRotation rot;
		static idVec3 vec( 0, 0, 1 );
		rot.Set( org, vec, rotate );
		trans = rot.ToMat3();
	}
	
	static idMat3 smat;
	smat.Identity();
	if( shear.x() || shear.y() )
	{
		smat[0][1] = shear.x();
		smat[1][0] = shear.y();
		trans *= smat;
	}
	
	if( !trans.IsIdentity() )
	{
		dc->SetTransformInfo( org, trans );
	}
}
コード例 #2
0
ファイル: Push.cpp プロジェクト: albertz/iodoom3
/*
============
idPush::ClipPush

  Try to push other entities by moving the given entity.
============
*/
float idPush::ClipPush( trace_t &results, idEntity *pusher, const int flags,
								const idVec3 &oldOrigin, const idMat3 &oldAxis,
									idVec3 &newOrigin, idMat3 &newAxis ) {
	idVec3 translation;
	idRotation rotation;
	float mass;

    mass = 0.0f;

	results.fraction = 1.0f;
	results.endpos = newOrigin;
	results.endAxis = newAxis;
	memset( &results.c, 0, sizeof( results.c ) );

	// translational push
	translation = newOrigin - oldOrigin;

	// if the pusher translates
	if ( translation != vec3_origin ) {

		mass += ClipTranslationalPush( results, pusher, flags, newOrigin, translation );
		if ( results.fraction < 1.0f ) {
			newOrigin = oldOrigin;
			newAxis = oldAxis;
			return mass;
		}
	} else {
		newOrigin = oldOrigin;
	}

	// rotational push
	rotation = ( oldAxis.Transpose() * newAxis ).ToRotation();
	rotation.SetOrigin( newOrigin );
	rotation.Normalize180();
	rotation.ReCalculateMatrix();		// recalculate the rotation matrix to avoid accumulating rounding errors

	// if the pusher rotates
	if ( rotation.GetAngle() != 0.0f ) {

		// recalculate new axis to avoid floating point rounding problems
		newAxis = oldAxis * rotation.ToMat3();
		newAxis.OrthoNormalizeSelf();
		newAxis.FixDenormals();
		newAxis.FixDegeneracies();

		pusher->GetPhysics()->GetClipModel()->SetPosition( newOrigin, oldAxis );

		mass += ClipRotationalPush( results, pusher, flags, newAxis, rotation );
		if ( results.fraction < 1.0f ) {
			newOrigin = oldOrigin;
			newAxis = oldAxis;
			return mass;
		}
	} else {
		newAxis = oldAxis;
	}

	return mass;
}
コード例 #3
0
/*
================
sdPhysics_GeneralMover::SetInitialPosition
================
*/
void sdPhysics_GeneralMover::SetInitialPosition( const idVec3& org, const idMat3& axes ) {
	move.startPos		= org;
	move.endPos			= org;

	move.startAngles	= axes.ToAngles();
	move.endAngles		= axes.ToAngles();

	SetCurrentPos( 1.f, true );
	rate				= 0.f;

	UpdateClipModel();
}
コード例 #4
0
ファイル: Brush.cpp プロジェクト: Yetta1/OpenTechBFG
/*
============
idBrush::Transform
============
*/
void idBrush::Transform( const idVec3& origin, const idMat3& axis )
{
	int i;
	bool transformed = false;
	
	if( axis.IsRotated() )
	{
		for( i = 0; i < sides.Num(); i++ )
		{
			sides[i]->plane.RotateSelf( vec3_origin, axis );
		}
		transformed = true;
	}
	if( origin != vec3_origin )
	{
		for( i = 0; i < sides.Num(); i++ )
		{
			sides[i]->plane.TranslateSelf( origin );
		}
		transformed = true;
	}
	if( transformed )
	{
		CreateWindings();
	}
}
コード例 #5
0
/*
 =======================================================================================================================
 =======================================================================================================================
 */
bool GetMatrixForKey(entity_t *ent, const char *key, idMat3 &mat)
{
    const char	*k;
    k = ValueForKey(ent, key);
    if (k && strlen(k) > 0)
    {
        sscanf
        (
            k,
            "%f %f %f %f %f %f %f %f %f ",
            &mat[0][0],
            &mat[0][1],
            &mat[0][2],
            &mat[1][0],
            &mat[1][1],
            &mat[1][2],
            &mat[2][0],
            &mat[2][1],
            &mat[2][2]
        );
        return true;
    }
    else
    {
        mat.Identity();
    }

    return false;
}
コード例 #6
0
/*
================
idPhysics_Parametric::SetAxis
================
*/
void idPhysics_Parametric::SetAxis( const idMat3 &newAxis, int id ) {
	idVec3 masterOrigin;
	idMat3 masterAxis;

	current.localAngles = newAxis.ToAngles();

	current.angularExtrapolation.SetStartValue( current.localAngles );
	current.angularInterpolation.SetStartValue( current.localAngles );

	current.localAngles = current.angularExtrapolation.GetCurrentValue( current.time );
	if ( hasMaster && isOrientated ) {
		self->GetMasterPosition( masterOrigin, masterAxis );
		current.axis = current.localAngles.ToMat3() * masterAxis;
		current.angles = current.axis.ToAngles();
	}
	else {
		current.axis = current.localAngles.ToMat3();
		current.angles = current.localAngles;
	}
	if ( clipModel ) {
// RAVEN BEGIN
// ddynerman: multiple clip worlds
		clipModel->Link( self, 0, current.origin, current.axis );
// RAVEN END
	}
	Activate();
}
コード例 #7
0
ファイル: Clip.cpp プロジェクト: AndreiBarsan/doom3.gpl
/*
============
idClip::Contents
============
*/
int idClip::Contents( const idVec3 &start, const idClipModel *mdl, const idMat3 &trmAxis, int contentMask, const idEntity *passEntity ) {
	int i, num, contents;
	idClipModel *touch, *clipModelList[MAX_GENTITIES];
	idBounds traceBounds;
	const idTraceModel *trm;

	trm = TraceModelForClipModel( mdl );

	if ( !passEntity || passEntity->entityNumber != ENTITYNUM_WORLD ) {
		// test world
		idClip::numContents++;
		contents = collisionModelManager->Contents( start, trm, trmAxis, contentMask, 0, vec3_origin, mat3_default );
	} else {
		contents = 0;
	}

	if ( !trm ) {
		traceBounds[0] = start;
		traceBounds[1] = start;
	} else if ( trmAxis.IsRotated() ) {
		traceBounds.FromTransformedBounds( trm->bounds, start, trmAxis );
	} else {
		traceBounds[0] = trm->bounds[0] + start;
		traceBounds[1] = trm->bounds[1] + start;
	}

	num = GetTraceClipModels( traceBounds, -1, passEntity, clipModelList );

	for ( i = 0; i < num; i++ ) {
		touch = clipModelList[i];

		if ( !touch ) {
			continue;
		}

		// no contents test with render models
		if ( touch->renderModelHandle != -1 ) {
			continue;
		}

		// if the entity does not have any contents we are looking for
		if ( ( touch->contents & contentMask ) == 0 ) {
			continue;
		}

		// if the entity has no new contents flags
		if ( ( touch->contents & contents ) == touch->contents ) {
			continue;
		}

		idClip::numContents++;
		if ( collisionModelManager->Contents( start, trm, trmAxis, contentMask, touch->Handle(), touch->origin, touch->axis ) ) {
			contents |= ( touch->contents & contentMask );
		}
	}

	return contents;
}
コード例 #8
0
/*
=====================
sdWalker::SetAxis
=====================
*/
void sdWalker::SetAxis( const idMat3& axis ) {
	viewAxis = axis;

	if ( vehicleControl ) {
		idAngles angles = axis.ToAngles();
		vehicleControl->OnYawChanged( angles.yaw );
	}

	UpdateVisuals();
}
コード例 #9
0
/*
================
idCollisionModelManagerLocal::DrawEdge
================
*/
void idCollisionModelManagerLocal::DrawEdge( cm_model_t* model, int edgeNum, const idVec3& origin, const idMat3& axis )
{
	int side;
	cm_edge_t* edge;
	idVec3 start, end, mid;
	bool isRotated;
	
	isRotated = axis.IsRotated();
	
	edge = model->edges + abs( edgeNum );
	side = edgeNum < 0;
	
	start = model->vertices[edge->vertexNum[side]].p;
	end = model->vertices[edge->vertexNum[!side]].p;
	if( isRotated )
	{
		start *= axis;
		end *= axis;
	}
	start += origin;
	end += origin;
	
	if( edge->internal )
	{
		if( cm_drawInternal.GetBool() )
		{
			common->RW()->DebugArrow( colorGreen, start, end, 1 );
		}
	}
	else
	{
		if( edge->numUsers > 2 )
		{
			common->RW()->DebugArrow( colorBlue, start, end, 1 );
		}
		else
		{
			common->RW()->DebugArrow( cm_color, start, end, 1 );
		}
	}
	
	if( cm_drawNormals.GetBool() )
	{
		mid = ( start + end ) * 0.5f;
		if( isRotated )
		{
			end = mid + 5 * ( axis * edge->normal );
		}
		else
		{
			end = mid + 5 * edge->normal;
		}
		common->RW()->DebugArrow( colorCyan, mid, end, 1 );
	}
}
コード例 #10
0
/*
=====================
sdClientProjectile::Launch
=====================
*/
void sdClientProjectile::Launch( idEntity* owner, const idVec3& tracerMuzzleOrigin, const idMat3& tracerMuzzleAxis ) {
	idAngles tracerMuzzleAngles = tracerMuzzleAxis.ToAngles();
	idVec3 anglesVec( tracerMuzzleAngles.pitch, tracerMuzzleAngles.yaw, tracerMuzzleAngles.roll );

	AddOwner( owner );

	sdScriptHelper helper;
	helper.Push( tracerMuzzleOrigin );
	helper.Push( anglesVec );
	CallNonBlockingScriptEvent( scriptObject->GetFunction( "OnLaunch" ), helper );
}
コード例 #11
0
ファイル: Dict.cpp プロジェクト: revelator/Revelation
/*
================
idDict::GetMatrix
================
*/
bool idDict::GetMatrix( const char *key, const char *defaultString, idMat3 &out ) const {
	const char	*s;
	bool		found;
	if( !defaultString ) {
		defaultString = "1 0 0 0 1 0 0 0 1";
	}
	found = GetString( key, defaultString, &s );
	out.Identity();		// sccanf has a bug in it on Mac OS 9.  Sigh.
	sscanf( s, "%f %f %f %f %f %f %f %f %f", &out[0].x, &out[0].y, &out[0].z, &out[1].x, &out[1].y, &out[1].z, &out[2].x, &out[2].y, &out[2].z );
	return found;
}
コード例 #12
0
/*
=====================
sdClientAnimated::GetJointWorldTransform
=====================
*/
bool sdClientAnimated::GetJointWorldTransform( jointHandle_t jointHandle, int currentTime, idVec3 &offset, idMat3 &axis ) {
	if ( !animator.GetJointTransform( jointHandle, currentTime, offset, axis ) ) {
		offset.Zero();
		axis.Identity();
		return false;
	}

	offset = renderEntity.origin + offset * renderEntity.axis;
	axis *= renderEntity.axis;
	return true;
}
コード例 #13
0
/*
================
idCollisionModelManagerLocal::DrawPolygon
================
*/
void idCollisionModelManagerLocal::DrawPolygon( cm_model_t *model, cm_polygon_t *p, const idVec3 &origin, const idMat3 &axis, const idVec3 &viewOrigin ) {
	int i, edgeNum;
	cm_edge_t *edge;
	idVec3 center, end, dir;

	if ( cm_backFaceCull.GetBool() ) {
		edgeNum = p->edges[0];
		edge = model->edges + abs(edgeNum);
		dir = model->vertices[edge->vertexNum[0]].p - viewOrigin;
		if ( dir * p->plane.Normal() > 0.0f ) {
			return;
		}
	}

	if ( cm_drawNormals.GetBool() ) {
		center = vec3_origin;
		for ( i = 0; i < p->numEdges; i++ ) {
			edgeNum = p->edges[i];
			edge = model->edges + abs(edgeNum);
			center += model->vertices[edge->vertexNum[edgeNum < 0]].p;
		}
		center *= (1.0f / p->numEdges);
		if ( axis.IsRotated() ) {
			center = center * axis + origin;
			end = center + 5 * (axis * p->plane.Normal());
		} else {
			center += origin;
			end = center + 5 * p->plane.Normal();
		}
		session->rw->DebugArrow( colorMagenta, center, end, 1 );
	}

	if ( cm_drawFilled.GetBool() ) {
		idFixedWinding winding;
		for ( i = p->numEdges - 1; i >= 0; i-- ) {
			edgeNum = p->edges[i];
			edge = model->edges + abs(edgeNum);
			winding += origin + model->vertices[edge->vertexNum[INTSIGNBITSET(edgeNum)]].p * axis;
		}
		session->rw->DebugPolygon( cm_color, winding );
	} else {
		for ( i = 0; i < p->numEdges; i++ ) {
			edgeNum = p->edges[i];
			edge = model->edges + abs(edgeNum);
			if ( edge->checkcount == checkCount ) {
				continue;
			}
			edge->checkcount = checkCount;
			DrawEdge( model, edgeNum, origin, axis );
		}
	}
}
コード例 #14
0
/*
================
hhCameraInterpolator::DetermineIdealRotation
================
*/
idQuat hhCameraInterpolator::DetermineIdealRotation( const idVec3& idealUpVector, const idVec3& viewDir, const idMat3& untransformedViewAxis ) {
	idMat3 mat;
	idVec3 newViewVector( viewDir );

	newViewVector.ProjectOntoPlane( idealUpVector );
	if( newViewVector.LengthSqr() < VECTOR_EPSILON ) {
		newViewVector = -Sign( newViewVector * idealUpVector );
	}

	newViewVector.Normalize();
	mat[0] = newViewVector;
	mat[1] = idealUpVector.Cross( newViewVector );
	mat[2] = idealUpVector;

	mat = untransformedViewAxis.Transpose() * mat;
	return mat.ToQuat();
}
コード例 #15
0
ファイル: Bounds.cpp プロジェクト: mrwonko/preymotionmod
/*
============
idBounds::FromBoundsTranslation

  Most tight bounds for the translational movement of the given bounds.
============
*/
void idBounds::FromBoundsTranslation( const idBounds &bounds, const idVec3 &origin, const idMat3 &axis, const idVec3 &translation ) {
	int i;

	if ( axis.IsRotated() ) {
		FromTransformedBounds( bounds, origin, axis );
	}
	else {
		b[0] = bounds[0] + origin;
		b[1] = bounds[1] + origin;
	}
	for ( i = 0; i < 3; i++ ) {
		if ( translation[i] < 0.0f ) {
			b[0][i] += translation[i];
		}
		else {
			b[1][i] += translation[i];
		}
	}
}
コード例 #16
0
/*
================
idCollisionModelManagerLocal::DrawModel
================
*/
void idCollisionModelManagerLocal::DrawModel( cmHandle_t handle, const idVec3 &modelOrigin, const idMat3 &modelAxis,
					const idVec3 &viewOrigin, const float radius ) {

	cm_model_t *model;
	idVec3 viewPos;

	if ( handle < 0 && handle >= numModels ) {
		return;
	}

	if ( cm_drawColor.IsModified() ) {
		sscanf( cm_drawColor.GetString(), "%f %f %f %f", &cm_color.x, &cm_color.y, &cm_color.z, &cm_color.w );
		cm_drawColor.ClearModified();
	}

	model = models[ handle ];
	viewPos = (viewOrigin - modelOrigin) * modelAxis.Transpose();
	checkCount++;
	DrawNodePolygons( model, model->node, modelOrigin, modelAxis, viewPos, radius );
}
コード例 #17
0
/*
=================
idRenderModelDecal::CreateProjectionInfo
=================
*/
void idRenderModelDecal::GlobalProjectionInfoToLocal( decalProjectionInfo_t &localInfo, const decalProjectionInfo_t &info, const idVec3 &origin, const idMat3 &axis ) {
	float modelMatrix[16];
	R_AxisToModelMatrix( axis, origin, modelMatrix );
	for( int j = 0; j < NUM_DECAL_BOUNDING_PLANES; j++ ) {
		R_GlobalPlaneToLocal( modelMatrix, info.boundingPlanes[j], localInfo.boundingPlanes[j] );
	}
	R_GlobalPlaneToLocal( modelMatrix, info.fadePlanes[0], localInfo.fadePlanes[0] );
	R_GlobalPlaneToLocal( modelMatrix, info.fadePlanes[1], localInfo.fadePlanes[1] );
	R_GlobalPlaneToLocal( modelMatrix, info.textureAxis[0], localInfo.textureAxis[0] );
	R_GlobalPlaneToLocal( modelMatrix, info.textureAxis[1], localInfo.textureAxis[1] );
	R_GlobalPointToLocal( modelMatrix, info.projectionOrigin, localInfo.projectionOrigin );
	localInfo.projectionBounds = info.projectionBounds;
	localInfo.projectionBounds.TranslateSelf( -origin );
	localInfo.projectionBounds.RotateSelf( axis.Transpose() );
	localInfo.material = info.material;
	localInfo.parallel = info.parallel;
	localInfo.fadeDepth = info.fadeDepth;
	localInfo.startTime = info.startTime;
	localInfo.force = info.force;
}
コード例 #18
0
ファイル: TraceModel.cpp プロジェクト: pdoughty/Q4--Hardqore
/*
============
idTraceModel::GetMassProperties
============
*/
void idTraceModel::GetMassProperties( const float density, float &mass, idVec3 &centerOfMass, idMat3 &inertiaTensor ) const {
	volumeIntegrals_t integrals;

	// if polygon trace model
	if ( type == TRM_POLYGON ) {
		idTraceModel trm;

		VolumeFromPolygon( trm, 1.0f );
		trm.GetMassProperties( density, mass, centerOfMass, inertiaTensor );
		return;
	}

	VolumeIntegrals( integrals );

	// if no volume
	if ( integrals.T0 == 0.0f ) {
		mass = 1.0f;
		centerOfMass.Zero();
		inertiaTensor.Identity();
		return;
	}

	// mass of model
	mass = density * integrals.T0;
	// center of mass
	centerOfMass = integrals.T1 / integrals.T0;
	// compute inertia tensor
	inertiaTensor[0][0] = density * (integrals.T2[1] + integrals.T2[2]);
	inertiaTensor[1][1] = density * (integrals.T2[2] + integrals.T2[0]);
	inertiaTensor[2][2] = density * (integrals.T2[0] + integrals.T2[1]);
	inertiaTensor[0][1] = inertiaTensor[1][0] = - density * integrals.TP[0];
	inertiaTensor[1][2] = inertiaTensor[2][1] = - density * integrals.TP[1];
	inertiaTensor[2][0] = inertiaTensor[0][2] = - density * integrals.TP[2];
	// translate inertia tensor to center of mass
	inertiaTensor[0][0] -= mass * (centerOfMass[1]*centerOfMass[1] + centerOfMass[2]*centerOfMass[2]);
	inertiaTensor[1][1] -= mass * (centerOfMass[2]*centerOfMass[2] + centerOfMass[0]*centerOfMass[0]);
	inertiaTensor[2][2] -= mass * (centerOfMass[0]*centerOfMass[0] + centerOfMass[1]*centerOfMass[1]);
	inertiaTensor[0][1] = inertiaTensor[1][0] += mass * centerOfMass[0] * centerOfMass[1];
	inertiaTensor[1][2] = inertiaTensor[2][1] += mass * centerOfMass[1] * centerOfMass[2];
	inertiaTensor[2][0] = inertiaTensor[0][2] += mass * centerOfMass[2] * centerOfMass[0];
}
コード例 #19
0
ファイル: FrobHandle.cpp プロジェクト: ProfessorKaos64/tdm
bool CFrobHandle::GetPhysicsToSoundTransform(idVec3 &origin, idMat3 &axis)
{
	idVec3 eyePos = gameLocal.GetLocalPlayer()->GetEyePosition();
	const idBounds& bounds = GetPhysics()->GetAbsBounds();

	//gameRenderWorld->DebugBounds(colorLtGrey, bounds, vec3_origin, 5000);
	
	// greebo: Choose the corner which is nearest to the player's eyeposition
	origin.x = (idMath::Fabs(bounds[0].x - eyePos.x) < idMath::Fabs(bounds[1].x - eyePos.x)) ? bounds[0].x : bounds[1].x;
	origin.y = (idMath::Fabs(bounds[0].y - eyePos.y) < idMath::Fabs(bounds[1].y - eyePos.y)) ? bounds[0].y : bounds[1].y;
	origin.z = (idMath::Fabs(bounds[0].z - eyePos.z) < idMath::Fabs(bounds[1].z - eyePos.z)) ? bounds[0].z : bounds[1].z;

	// The called expects the origin in local space
	origin -= GetPhysics()->GetOrigin();

	axis.Identity();

	//gameRenderWorld->DebugArrow(colorWhite, GetPhysics()->GetOrigin() + origin, eyePos, 0, 5000);

	return true;
}
コード例 #20
0
void hhShuttleTransport::UpdateAxis( const idMat3 &newAxis ) {
	// Yaw transport to match yaw of shuttle
	idAngles ang = newAxis.ToAngles();
	ang.pitch = ang.roll = 0.0f;
	SetAxis(ang.ToMat3());
}
コード例 #21
0
/*
================
idCollisionModelManagerLocal::Rotation180
================
*/
void idCollisionModelManagerLocal::Rotation180( trace_t *results, const idVec3 &rorg, const idVec3 &axis,
										const float startAngle, const float endAngle, const idVec3 &start,
										const idTraceModel *trm, const idMat3 &trmAxis, int contentMask,
										cmHandle_t model, const idVec3 &modelOrigin, const idMat3 &modelAxis ) {
	int i, j, edgeNum;
	float d, maxErr, initialTan;
	bool model_rotated, trm_rotated;
	idVec3 dir, dir1, dir2, tmp, vr, vup, org, at, bt;
	idMat3 invModelAxis, endAxis, tmpAxis;
	idRotation startRotation, endRotation;
	idPluecker plaxis;
	cm_trmPolygon_t *poly;
	cm_trmEdge_t *edge;
	cm_trmVertex_t *vert;
	ALIGN16( static cm_traceWork_t tw );

	if ( model < 0 || model > MAX_SUBMODELS || model > idCollisionModelManagerLocal::maxModels ) {
		common->Printf("idCollisionModelManagerLocal::Rotation180: invalid model handle\n");
		return;
	}
	if ( !idCollisionModelManagerLocal::models[model] ) {
		common->Printf("idCollisionModelManagerLocal::Rotation180: invalid model\n");
		return;
	}

	idCollisionModelManagerLocal::checkCount++;

	tw.trace.fraction = 1.0f;
	tw.trace.c.contents = 0;
	tw.trace.c.type = CONTACT_NONE;
	tw.contents = contentMask;
	tw.isConvex = true;
	tw.rotation = true;
	tw.positionTest = false;
	tw.axisIntersectsTrm = false;
	tw.quickExit = false;
	tw.angle = endAngle - startAngle;
	assert( tw.angle > -180.0f && tw.angle < 180.0f );
	tw.maxTan = initialTan = idMath::Fabs( tan( ( idMath::PI / 360.0f ) * tw.angle ) );
	tw.model = idCollisionModelManagerLocal::models[model];
	tw.start = start - modelOrigin;
	// rotation axis, axis is assumed to be normalized
	tw.axis = axis;
//	assert( tw.axis[0] * tw.axis[0] + tw.axis[1] * tw.axis[1] + tw.axis[2] * tw.axis[2] > 0.99f );
	// rotation origin projected into rotation plane through tw.start
	tw.origin = rorg - modelOrigin;
	d = (tw.axis * tw.origin) - ( tw.axis * tw.start );
	tw.origin = tw.origin - d * tw.axis;
	// radius of rotation
	tw.radius = ( tw.start - tw.origin ).Length();
	// maximum error of the circle approximation traced through the axial BSP tree
	d = tw.radius * tw.radius - (CIRCLE_APPROXIMATION_LENGTH*CIRCLE_APPROXIMATION_LENGTH*0.25f);
	if ( d > 0.0f ) {
		maxErr = tw.radius - idMath::Sqrt( d );
	} else {
		maxErr = tw.radius;
	}

	model_rotated = modelAxis.IsRotated();
	if ( model_rotated ) {
		invModelAxis = modelAxis.Transpose();
		tw.axis *= invModelAxis;
		tw.origin *= invModelAxis;
	}

	startRotation.Set( tw.origin, tw.axis, startAngle );
	endRotation.Set( tw.origin, tw.axis, endAngle );

	// create matrix which rotates the rotation axis to the z-axis
	tw.axis.NormalVectors( vr, vup );
	tw.matrix[0][0] = vr[0];
	tw.matrix[1][0] = vr[1];
	tw.matrix[2][0] = vr[2];
	tw.matrix[0][1] = -vup[0];
	tw.matrix[1][1] = -vup[1];
	tw.matrix[2][1] = -vup[2];
	tw.matrix[0][2] = tw.axis[0];
	tw.matrix[1][2] = tw.axis[1];
	tw.matrix[2][2] = tw.axis[2];

	// if optimized point trace
	if ( !trm || ( trm->bounds[1][0] - trm->bounds[0][0] <= 0.0f &&
					trm->bounds[1][1] - trm->bounds[0][1] <= 0.0f &&
					trm->bounds[1][2] - trm->bounds[0][2] <= 0.0f ) ) {

		if ( model_rotated ) {
			// rotate trace instead of model
			tw.start *= invModelAxis;
		}
		tw.end = tw.start;
		// if we start at a specific angle
		if ( startAngle != 0.0f ) {
			startRotation.RotatePoint( tw.start );
		}
		// calculate end position of rotation
		endRotation.RotatePoint( tw.end );

		// calculate rotation origin projected into rotation plane through the vertex
		tw.numVerts = 1;
		tw.vertices[0].p = tw.start;
		tw.vertices[0].endp = tw.end;
		tw.vertices[0].used = true;
		tw.vertices[0].rotationOrigin = tw.origin + tw.axis * ( tw.axis * ( tw.vertices[0].p - tw.origin ) );
		BoundsForRotation( tw.vertices[0].rotationOrigin, tw.axis, tw.start, tw.end, tw.vertices[0].rotationBounds );
		// rotation bounds
		tw.bounds = tw.vertices[0].rotationBounds;
		tw.numEdges = tw.numPolys = 0;

		// collision with single point
		tw.pointTrace = true;

		// extents is set to maximum error of the circle approximation traced through the axial BSP tree
		tw.extents[0] = tw.extents[1] = tw.extents[2] = maxErr + CM_BOX_EPSILON;

		// setup rotation heart plane
		tw.heartPlane1.SetNormal( tw.axis );
		tw.heartPlane1.FitThroughPoint( tw.start );
		tw.maxDistFromHeartPlane1 = CM_BOX_EPSILON;

		// trace through the model
		idCollisionModelManagerLocal::TraceThroughModel( &tw );

		// store results
		*results = tw.trace;
		results->endpos = start;
		if ( tw.maxTan == initialTan ) {
			results->fraction = 1.0f;
		} else {
			results->fraction = idMath::Fabs( atan( tw.maxTan ) * ( 2.0f * 180.0f / idMath::PI ) / tw.angle );
		}
		assert( results->fraction <= 1.0f );
		endRotation.Set( rorg, axis, startAngle + (endAngle-startAngle) * results->fraction );
		endRotation.RotatePoint( results->endpos );
		results->endAxis.Identity();

		if ( results->fraction < 1.0f ) {
			// rotate trace plane normal if there was a collision with a rotated model
			if ( model_rotated ) {
				results->c.normal *= modelAxis;
				results->c.point *= modelAxis;
			}
			results->c.point += modelOrigin;
			results->c.dist += modelOrigin * results->c.normal;
		}
		return;
	}

	tw.pointTrace = false;

	// setup trm structure
	idCollisionModelManagerLocal::SetupTrm( &tw, trm );

	trm_rotated = trmAxis.IsRotated();

	// calculate vertex positions
	if ( trm_rotated ) {
		for ( i = 0; i < tw.numVerts; i++ ) {
			// rotate trm around the start position
			tw.vertices[i].p *= trmAxis;
		}
	}
	for ( i = 0; i < tw.numVerts; i++ ) {
		// set trm at start position
		tw.vertices[i].p += tw.start;
	}
	if ( model_rotated ) {
		for ( i = 0; i < tw.numVerts; i++ ) {
			tw.vertices[i].p *= invModelAxis;
		}
	}
	for ( i = 0; i < tw.numVerts; i++ ) {
		tw.vertices[i].endp = tw.vertices[i].p;
	}
	// if we start at a specific angle
	if ( startAngle != 0.0f ) {
		for ( i = 0; i < tw.numVerts; i++ ) {
			startRotation.RotatePoint( tw.vertices[i].p );
		}
	}
	for ( i = 0; i < tw.numVerts; i++ ) {
		// end position of vertex
		endRotation.RotatePoint( tw.vertices[i].endp );
	}

	// add offset to start point
	if ( trm_rotated ) {
		tw.start += trm->offset * trmAxis;
	} else {
		tw.start += trm->offset;
	}
	// if the model is rotated
	if ( model_rotated ) {
		// rotate trace instead of model
		tw.start *= invModelAxis;
	}
	tw.end = tw.start;
	// if we start at a specific angle
	if ( startAngle != 0.0f ) {
		startRotation.RotatePoint( tw.start );
	}
	// calculate end position of rotation
	endRotation.RotatePoint( tw.end );

	// setup trm vertices
	for ( vert = tw.vertices, i = 0; i < tw.numVerts; i++, vert++ ) {
		// calculate rotation origin projected into rotation plane through the vertex
		vert->rotationOrigin = tw.origin + tw.axis * ( tw.axis * ( vert->p - tw.origin ) );
		// calculate rotation bounds for this vertex
		BoundsForRotation( vert->rotationOrigin, tw.axis, vert->p, vert->endp, vert->rotationBounds );
		// if the rotation axis goes through the vertex then the vertex is not used
		d = ( vert->p - vert->rotationOrigin ).LengthSqr();
		if ( d > ROTATION_AXIS_EPSILON * ROTATION_AXIS_EPSILON ) {
			vert->used = true;
		}
	}

	// setup trm edges
	for ( edge = tw.edges + 1, i = 1; i <= tw.numEdges; i++, edge++ ) {
		// if the rotation axis goes through both the edge vertices then the edge is not used
		if ( tw.vertices[edge->vertexNum[0]].used | tw.vertices[edge->vertexNum[1]].used ) {
			edge->used = true;
		}
		// edge start, end and pluecker coordinate
		edge->start = tw.vertices[edge->vertexNum[0]].p;
		edge->end = tw.vertices[edge->vertexNum[1]].p;
		edge->pl.FromLine( edge->start, edge->end );
		// pluecker coordinate for edge being rotated about the z-axis
		at = ( edge->start - tw.origin ) * tw.matrix;
		bt = ( edge->end - tw.origin ) * tw.matrix;
		edge->plzaxis.FromLine( at, bt );
		// get edge rotation bounds from the rotation bounds of both vertices
		edge->rotationBounds = tw.vertices[edge->vertexNum[0]].rotationBounds;
		edge->rotationBounds.AddBounds( tw.vertices[edge->vertexNum[1]].rotationBounds );
		// used to calculate if the rotation axis intersects the trm
		edge->bitNum = 0;
	}

	tw.bounds.Clear();

	// rotate trm polygon planes
	if ( trm_rotated & model_rotated ) {
		tmpAxis = trmAxis * invModelAxis;
		for ( poly = tw.polys, i = 0; i < tw.numPolys; i++, poly++ ) {
			poly->plane *= tmpAxis;
		}
	} else if ( trm_rotated ) {
		for ( poly = tw.polys, i = 0; i < tw.numPolys; i++, poly++ ) {
			poly->plane *= trmAxis;
		}
	} else if ( model_rotated ) {
		for ( poly = tw.polys, i = 0; i < tw.numPolys; i++, poly++ ) {
			poly->plane *= invModelAxis;
		}
	}

	// setup trm polygons
	for ( poly = tw.polys, i = 0; i < tw.numPolys; i++, poly++ ) {
		poly->used = true;
		// set trm polygon plane distance
		poly->plane.FitThroughPoint( tw.edges[abs(poly->edges[0])].start );
		// get polygon bounds from edge bounds
		poly->rotationBounds.Clear();
		for ( j = 0; j < poly->numEdges; j++ ) {
			// add edge rotation bounds to polygon rotation bounds
			edge = &tw.edges[abs( poly->edges[j] )];
			poly->rotationBounds.AddBounds( edge->rotationBounds );
		}
		// get trace bounds from polygon bounds
		tw.bounds.AddBounds( poly->rotationBounds );
	}

	// extents including the maximum error of the circle approximation traced through the axial BSP tree
	for ( i = 0; i < 3; i++ ) {
		tw.size[0][i] = tw.bounds[0][i] - tw.start[i];
		tw.size[1][i] = tw.bounds[1][i] - tw.start[i];
		if ( idMath::Fabs( tw.size[0][i] ) > idMath::Fabs( tw.size[1][i] ) ) {
			tw.extents[i] = idMath::Fabs( tw.size[0][i] ) + maxErr + CM_BOX_EPSILON;
		} else {
			tw.extents[i] = idMath::Fabs( tw.size[1][i] ) + maxErr + CM_BOX_EPSILON;
		}
	}

	// for back-face culling
	if ( tw.isConvex ) {
		if ( tw.start == tw.origin ) {
			tw.axisIntersectsTrm = true;
		} else {
			// determine if the rotation axis intersects the trm
			plaxis.FromRay( tw.origin, tw.axis );
			for ( poly = tw.polys, i = 0; i < tw.numPolys; i++, poly++ ) {
				// back face cull polygons
				if ( poly->plane.Normal() * tw.axis > 0.0f ) {
					continue;
				}
				// test if the axis goes between the polygon edges
				for ( j = 0; j < poly->numEdges; j++ ) {
					edgeNum = poly->edges[j];
					edge = tw.edges + abs( edgeNum );
					if ( ( edge->bitNum & 2 ) == 0 ) {
						d = plaxis.PermutedInnerProduct( edge->pl );
						edge->bitNum = ( ( d < 0.0f ) ? 1 : 0 ) | 2;
					}
					if ( ( edge->bitNum ^ INT32_SIGNBITSET( edgeNum ) ) & 1 ) {
						break;
					}
				}
				if ( j >= poly->numEdges ) {
					tw.axisIntersectsTrm = true;
					break;
				}
			}
		}
	}

	// setup rotation heart plane
	tw.heartPlane1.SetNormal( tw.axis );
	tw.heartPlane1.FitThroughPoint( tw.start );
	tw.maxDistFromHeartPlane1 = 0.0f;
	for ( i = 0; i < tw.numVerts; i++ ) {
		d = idMath::Fabs( tw.heartPlane1.Distance( tw.vertices[i].p ) );
		if ( d > tw.maxDistFromHeartPlane1 ) {
			tw.maxDistFromHeartPlane1 = d;
		}
	}
	tw.maxDistFromHeartPlane1 += CM_BOX_EPSILON;

	// inverse rotation to rotate model vertices towards trace model
	tw.modelVertexRotation.Set( tw.origin, tw.axis, -tw.angle );

	// trace through the model
	idCollisionModelManagerLocal::TraceThroughModel( &tw );

	// store results
	*results = tw.trace;
	results->endpos = start;
	if ( tw.maxTan == initialTan ) {
		results->fraction = 1.0f;
	} else {
		results->fraction = idMath::Fabs( atan( tw.maxTan ) * ( 2.0f * 180.0f / idMath::PI ) / tw.angle );
	}
	assert( results->fraction <= 1.0f );
	endRotation.Set( rorg, axis, startAngle + (endAngle-startAngle) * results->fraction );
	endRotation.RotatePoint( results->endpos );
	results->endAxis = trmAxis * endRotation.ToMat3();

	if ( results->fraction < 1.0f ) {
		// rotate trace plane normal if there was a collision with a rotated model
		if ( model_rotated ) {
			results->c.normal *= modelAxis;
			results->c.point *= modelAxis;
		}
		results->c.point += modelOrigin;
		results->c.dist += modelOrigin * results->c.normal;
	}
}
コード例 #22
0
ファイル: prey_sound.cpp プロジェクト: mrwonko/preymotionmod
/*
================
hhSound::GetPhysicsToSoundTransform
================
*/
bool hhSound::GetPhysicsToSoundTransform( idVec3 &origin, idMat3 &axis ) {
	origin = positionOffset;
	axis.Identity();
	return true;
}