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 ); } }
/* ============ 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; }
/* ================ 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(); }
/* ============ 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(); } }
/* ======================================================================================================================= ======================================================================================================================= */ 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; }
/* ================ 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(); }
/* ============ 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; }
/* ===================== sdWalker::SetAxis ===================== */ void sdWalker::SetAxis( const idMat3& axis ) { viewAxis = axis; if ( vehicleControl ) { idAngles angles = axis.ToAngles(); vehicleControl->OnYawChanged( angles.yaw ); } UpdateVisuals(); }
/* ================ 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 ); } }
/* ===================== 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 ); }
/* ================ 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; }
/* ===================== 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; }
/* ================ 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 ); } } }
/* ================ 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(); }
/* ============ 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]; } } }
/* ================ 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 ); }
/* ================= 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; }
/* ============ idTraceModel::GetMassProperties ============ */ void idTraceModel::GetMassProperties( const float density, float &mass, idVec3 ¢erOfMass, 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]; }
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; }
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()); }
/* ================ 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; } }
/* ================ hhSound::GetPhysicsToSoundTransform ================ */ bool hhSound::GetPhysicsToSoundTransform( idVec3 &origin, idMat3 &axis ) { origin = positionOffset; axis.Identity(); return true; }