//----------------------------------------------------------------------------- // Computes the position of the canister //----------------------------------------------------------------------------- void CEnvHeadcrabCanisterShared::GetPositionAtTime( float flTime, Vector &vecPosition, QAngle &vecAngles ) { float flDeltaTime = flTime - m_flLaunchTime; if ( flDeltaTime > m_flFlightTime ) { flDeltaTime = m_flFlightTime; } VMatrix initToWorld; if ( m_bLaunchedFromWithinWorld || m_bInSkybox ) { VectorMA( m_vecStartPosition, flDeltaTime * m_flHorizSpeed, m_vecParabolaDirection, vecPosition ); vecPosition.z += m_flInitialZSpeed * flDeltaTime + 0.5f * m_flZAcceleration * flDeltaTime * flDeltaTime; Vector vecLeft; CrossProduct( m_vecParabolaDirection, Vector( 0, 0, 1 ), vecLeft ); Vector vecForward; VectorMultiply( m_vecParabolaDirection, -1.0f, vecForward ); vecForward.z = -(m_flInitialZSpeed + m_flZAcceleration * flDeltaTime) / m_flHorizSpeed; // This is -dz/dx. VectorNormalize( vecForward ); Vector vecUp; CrossProduct( vecForward, vecLeft, vecUp ); initToWorld.SetBasisVectors( vecForward, vecLeft, vecUp ); } else { flDeltaTime -= m_flWorldEnterTime; Vector vecVelocity; VectorMultiply( m_vecDirection, m_flFlightSpeed, vecVelocity ); VectorMA( m_vecEnterWorldPosition, flDeltaTime, vecVelocity, vecPosition ); MatrixFromAngles( m_vecStartAngles.Get(), initToWorld ); } VMatrix rotation; MatrixBuildRotationAboutAxis( rotation, Vector( 1, 0, 0 ), flDeltaTime * ROTATION_SPEED ); VMatrix newAngles; MatrixMultiply( initToWorld, rotation, newAngles ); MatrixToAngles( newAngles, vecAngles ); }
VMatrix VMatrix::NormalizeBasisVectors() const { Vector vecs[3]; VMatrix mRet; GetBasisVectors(vecs[0], vecs[1], vecs[2]); VectorNormalize( vecs[0] ); VectorNormalize( vecs[1] ); VectorNormalize( vecs[2] ); mRet.SetBasisVectors(vecs[0], vecs[1], vecs[2]); // Set everything but basis vectors to identity. mRet.m[3][0] = mRet.m[3][1] = mRet.m[3][2] = 0.0f; mRet.m[3][3] = 1.0f; return mRet; }
void EmitClipPortalGeometry( node_t *pHeadNode, portal_t *pPortal, int iSrcArea, dareaportal_t *dp ) { // Build a list of all the points in portals from the same original face. CUtlVector<portal_t*> portals; FindPortalsLeadingToArea_R( pHeadNode, iSrcArea, dp->otherarea, &pPortal->plane, portals ); CUtlVector<Vector> points; for( int iPortal=0; iPortal < portals.Size(); iPortal++ ) { portal_t *pPointPortal = portals[iPortal]; winding_t *pWinding = pPointPortal->winding; for( int i=0; i < pWinding->numpoints; i++ ) { points.AddToTail( pWinding->p[i] ); } } // Get the 2D convex hull. //// First transform them into a plane. QAngle vAngles; Vector vecs[3]; VectorAngles( pPortal->plane.normal, vAngles ); AngleVectors( vAngles, &vecs[0], &vecs[1], &vecs[2] ); VMatrix mTransform; mTransform.Identity(); mTransform.SetBasisVectors( vecs[0], vecs[1], vecs[2] ); VMatrix mInvTransform = mTransform.Transpose(); int i; CUtlVector<Vector2D> points2D; for( i=0; i < points.Size(); i++ ) { Vector vTest = mTransform * points[i]; points2D.AddToTail( Vector2D( vTest.y, vTest.z ) ); } // Build the hull. int indices[512]; int nIndices = Convex2D( points2D.Base(), points2D.Size(), indices, 512 ); // Output the hull. dp->m_FirstClipPortalVert = g_nClipPortalVerts; dp->m_nClipPortalVerts = nIndices; if ( nIndices >= 32 ) { Warning( "Warning: area portal has %d verts. Could be a vbsp bug.\n", nIndices ); } if( dp->m_FirstClipPortalVert + dp->m_nClipPortalVerts >= MAX_MAP_PORTALVERTS ) { Vector *p = pPortal->winding->p; Error( "MAX_MAP_PORTALVERTS (probably a broken areaportal near %.1f %.1f %.1f ", p->x, p->y, p->z ); } for( i=0; i < nIndices; i++ ) { g_ClipPortalVerts[g_nClipPortalVerts] = points[ indices[i] ]; ++g_nClipPortalVerts; } }
static void PlaceDetail( DetailModel_t const& model, const Vector& pt, const Vector& normal ) { // But only place it on the surface if it meets the angle constraints... float cosAngle = normal.z; // Never emit if the angle's too steep if (cosAngle < model.m_MaxCosAngle) return; // If it's between min + max, flip a coin... if (cosAngle < model.m_MinCosAngle) { float probability = (cosAngle - model.m_MaxCosAngle) / (model.m_MinCosAngle - model.m_MaxCosAngle); float t = rand() / (float)RAND_MAX; if (t > probability) return; } // Compute the orientation of the detail QAngle angles; if (model.m_Flags & MODELFLAG_UPRIGHT) { // If it's upright, we just select a random yaw angles.Init( 0, 360.0f * rand() / (float)RAND_MAX, 0.0f ); } else { // It's not upright, so it must conform to the ground. Choose // a random orientation based on the surface normal Vector zaxis; VectorCopy( normal, zaxis ); // Choose any two arbitrary axes which are perpendicular to the normal Vector xaxis( 1, 0, 0 ); if (fabs(xaxis.Dot(zaxis)) - 1.0 > -1e-3) xaxis.Init( 0, 1, 0 ); Vector yaxis; CrossProduct( zaxis, xaxis, yaxis ); CrossProduct( yaxis, zaxis, xaxis ); VMatrix matrix; matrix.SetBasisVectors( xaxis, yaxis, zaxis ); float rotAngle = 360.0f * rand() / (float)RAND_MAX; VMatrix rot = SetupMatrixAxisRot( Vector( 0, 0, 1 ), rotAngle ); matrix = matrix * rot; MatrixToAngles( matrix, angles ); } // FIXME: We may also want a purely random rotation too // Insert an element into the object dictionary if it aint there... switch ( model.m_Type ) { case DETAIL_PROP_TYPE_MODEL: AddDetailToLump( model.m_ModelName.String(), pt, angles, model.m_Orientation ); break; case DETAIL_PROP_TYPE_SPRITE: { float flScale = 1.0f; if ( model.m_flRandomScaleStdDev != 0.0f ) { flScale = fabs( RandomGaussianFloat( 1.0f, model.m_flRandomScaleStdDev ) ); } AddDetailSpriteToLump( pt, angles, model.m_Orientation, model.m_Pos, model.m_Tex, flScale ); } break; } }