void RotateFaceTexture(face_t* f, int nAxis, float fDeg) { vec3_t p1,p2,p3, rota; p1[0] = p1[1] = p1[2] = 0; VectorCopy(p1, p2); VectorCopy(p1, p3); VectorCopy(p1, rota); ComputeAbsolute(f, p1, p2, p3); rota[nAxis] = fDeg; VectorRotate(p1, rota, select_origin, p1); VectorRotate(p2, rota, select_origin, p2); VectorRotate(p3, rota, select_origin, p3); plane_t normal2; vec3_t vNormal; vNormal[0] = f->plane.normal[0]; vNormal[1] = f->plane.normal[1]; vNormal[2] = f->plane.normal[2]; VectorRotate(vNormal, rota, vNormal); normal2.normal[0] = vNormal[0]; normal2.normal[1] = vNormal[1]; normal2.normal[2] = vNormal[2]; AbsoluteToLocal(normal2, f, p1, p2 ,p3); }
void cCamera::UpdateInput(float deltaTime) { cVector3df ter(0.0f,0.0f,-m_speed *deltaTime), ter2(-m_speed *deltaTime,0.0f,0.0f),ter3(m_speed *deltaTime,0.0f,0.0f),ter4(0.0f,0.0f,m_speed *deltaTime); cVector3df Front,Left,Right,Back; VectorRotate(ter,ENGINE->m_activeCamera->Camera,Front); VectorRotate(ter2,ENGINE->m_activeCamera->Camera,Left); VectorRotate(ter3,ENGINE->m_activeCamera->Camera,Right); VectorRotate(ter4,ENGINE->m_activeCamera->Camera,Back); if(INPUT->getMouseButtonState(LEFT_MOUSE_BUTTON)) setEnabledMouse(); if(!INPUT->getMouseButtonState(LEFT_MOUSE_BUTTON)) setDisabledMouse(); if(INPUT->getKey('W')||INPUT->getKey('w')) move(Front); if(INPUT->getKey('S')||INPUT->getKey('s')) move(Back); if(INPUT->getKey('A')||INPUT->getKey('a')) move(Left); if(INPUT->getKey('D')||INPUT->getKey('d')) move(Right); if(INPUT->getKey('R')||INPUT->getKey('r')) move(cVector3df(0,0.1f,0)); if(INPUT->getKey('F')||INPUT->getKey('f')) move(cVector3df(0,-0.1f,0)); }
void RotateFaceTexture( face_s* f, int nAxis, float fDeg ) { edVec3_c p1, p2, p3, rota; p1.clear(); p2.clear(); p3.clear(); rota.clear(); ComputeAbsolute( f, p1, p2, p3 ); rota[nAxis] = fDeg; VectorRotate( p1, rota, select_origin, p1 ); VectorRotate( p2, rota, select_origin, p2 ); VectorRotate( p3, rota, select_origin, p3 ); edPlane_c normal2; edVec3_c vNormal; vNormal[0] = f->plane.normal[0]; vNormal[1] = f->plane.normal[1]; vNormal[2] = f->plane.normal[2]; VectorRotate( vNormal, rota, vNormal ); normal2.normal[0] = vNormal[0]; normal2.normal[1] = vNormal[1]; normal2.normal[2] = vNormal[2]; AbsoluteToLocal( normal2, f, p1, p2 , p3 ); }
void NDebugOverlay::BoxAngles(const Vector &origin, const Vector &mins, const Vector &maxs, const QAngle &angles, int r, int g, int b, int a, float duration) { // -------------------------------------------------------------- // Have to do clip the boxes before sending so we // don't overflow the client message buffer // -------------------------------------------------------------- CBasePlayer *player = UTIL_PlayerByIndex(1); if ( !player ) return; // ------------------------------------ // Clip boxes that are far away // ------------------------------------ if ((player->GetAbsOrigin() - origin).LengthSqr() > MAX_OVERLAY_DIST_SQR) return; // ------------------------------------ // Clip boxes that are behind the client // ------------------------------------ Vector clientForward; player->EyeVectors( &clientForward ); // Build a rotation matrix from orientation matrix3x4_t fRotateMatrix; AngleMatrix(angles, fRotateMatrix); // Transform the mins and maxs Vector tmins, tmaxs; VectorRotate( mins, fRotateMatrix, tmins); VectorAdd(tmins,origin,tmins); VectorRotate( maxs, fRotateMatrix, tmaxs); VectorAdd(tmaxs,origin,tmaxs); Vector toMins = tmins - player->GetAbsOrigin(); Vector toMaxs = tmaxs - player->GetAbsOrigin(); float dotMins = DotProduct(clientForward,toMins); float dotMaxs = DotProduct(clientForward,toMaxs); if (dotMins < 0 && dotMaxs < 0) return; CSingleUserRecipientFilter user( player ); MessageBegin( user, SVC_DEBUG_BOX_OVERLAY ); WRITE_VEC3COORD(origin); WRITE_VEC3COORD(mins); WRITE_VEC3COORD(maxs); WRITE_ANGLES(angles); WRITE_SHORT(r); WRITE_SHORT(g); WRITE_SHORT(b); WRITE_SHORT(a); WRITE_FLOAT(duration); MessageEnd(); }
inline void VectorRotate(const Vector &i, const Angle &angles, Vector &o) { matrix3x4 matrix; AngleMatrix(angles, matrix); VectorRotate(i, matrix, o); }
inline Vector Vector::Rotate(const Angle &angles) const { Vector o; VectorRotate(*this, angles, o); return o; }
//----------------------------------------------------------------------------- // Purpose: Get the absolute position of the desired attachment point //----------------------------------------------------------------------------- void CAI_PassengerBehaviorZombie::GetAttachmentPoint( Vector *vecPoint ) { Vector vecEntryOffset, vecFinalOffset; GetEntryTarget( &vecEntryOffset, NULL ); VectorRotate( vecEntryOffset, m_hVehicle->GetAbsAngles(), vecFinalOffset ); *vecPoint = ( m_hVehicle->GetAbsOrigin() + vecFinalOffset ); }
void CPhysicsObject::LocalToWorldVector( Vector &worldVector, const Vector &localVector ) { matrix3x4_t matrix; GetPositionMatrix( matrix ); // copy in case the src == dest VectorRotate( Vector(localVector), matrix, worldVector ); }
void VectorRotate (vec3_t vIn, vec3_t vRotation, vec3_t vOrigin, vec3_t out) { vec3_t vTemp, vTemp2; VectorSubtract(vIn, vOrigin, vTemp); VectorRotate(vTemp, vRotation, vTemp2); VectorAdd(vTemp2, vOrigin, out); }
void CPhysicsObject::LocalToWorldVector(Vector *worldVector, const Vector &localVector) const { if (!worldVector) return; matrix3x4_t matrix; GetPositionMatrix(&matrix); VectorRotate(localVector, matrix, *worldVector); }
void ComputeAbsolute(face_t* f, vec3_t& p1, vec3_t& p2, vec3_t& p3) { vec3_t ex,ey,ez; // local axis base #ifdef _DEBUG if (g_qeglobals.m_bBrushPrimitMode) Sys_Printf("Warning : illegal call of ComputeAbsolute in brush primitive mode\n"); #endif // compute first local axis base TextureAxisFromPlane(&f->plane, ex, ey); CrossProduct(ex, ey, ez); vec3_t aux; VectorCopy(ex, aux); VectorScale(aux, -f->texdef.shift[0], aux); VectorCopy(aux, p1); VectorCopy(ey, aux); VectorScale(aux, -f->texdef.shift[1], aux); VectorAdd(p1, aux, p1); VectorCopy(p1, p2); VectorAdd(p2, ex, p2); VectorCopy(p1, p3); VectorAdd(p3, ey, p3); VectorCopy(ez, aux); VectorScale(aux, -f->texdef.rotate, aux); VectorRotate(p1, aux, p1); VectorRotate(p2, aux, p2); VectorRotate(p3, aux, p3); // computing rotated local axis base vec3_t rex,rey; VectorCopy(ex, rex); VectorRotate(rex, aux, rex); VectorCopy(ey, rey); VectorRotate(rey, aux, rey); ComputeScale(rex,rey,p1,f); ComputeScale(rex,rey,p2,f); ComputeScale(rex,rey,p3,f); // project on normal plane // along ez // assumes plane normal is normalized ProjectOnPlane(f->plane.normal,f->plane.dist,ez,p1); ProjectOnPlane(f->plane.normal,f->plane.dist,ez,p2); ProjectOnPlane(f->plane.normal,f->plane.dist,ez,p3); };
/** * Method is used to rotate solid by vectors and angle. * @param a is rotate vector. * @param b is rotate vector. * @param angle is rotate angle value. */ void Rotate(const Vector& a, const Vector& b, float angle) { for(unsigned i = 0; i < vertices.size(); i++) { Vector v = vertices[i]; v = VectorRotate(v, a, b, angle); vertices[i] = v; } }
void ComputeAbsolute( face_s* f, edVec3_c& p1, edVec3_c& p2, edVec3_c& p3 ) { edVec3_c ex, ey, ez; // local axis base #ifdef _DEBUG if ( g_qeglobals.m_bBrushPrimitMode ) Sys_Printf( "Warning : illegal call of ComputeAbsolute in brush primitive mode\n" ); #endif // compute first local axis base TextureAxisFromPlane( f->plane, ex, ey ); ez.crossProduct( ex, ey ); edVec3_c aux = ex * -f->texdef.shift[0]; p1 = aux; aux = ey * -f->texdef.shift[1]; p1 += aux; p2 = p1; p2 += ex; p3 = p1; p3 += ey; aux = ez; aux *= -f->texdef.rotate; VectorRotate( p1, aux, p1 ); VectorRotate( p2, aux, p2 ); VectorRotate( p3, aux, p3 ); // computing rotated local axis base edVec3_c rex = ex; VectorRotate( rex, aux, rex ); edVec3_c rey = ey; VectorRotate( rey, aux, rey ); ComputeScale( rex, rey, p1, f ); ComputeScale( rex, rey, p2, f ); ComputeScale( rex, rey, p3, f ); // project on normal plane // along ez // assumes plane normal is normalized f->plane.projectOnPlane( ez, p1 ); f->plane.projectOnPlane( ez, p2 ); f->plane.projectOnPlane( ez, p3 ); };
void DBrush::Rotate(vec3_t vOrigin, vec3_t vRotation) { for(list<DPlane *>::const_iterator rotPlane=faceList.begin(); rotPlane!=faceList.end(); rotPlane++) { for(int i = 0; i < 3; i++) VectorRotate((*rotPlane)->points[i], vRotation, vOrigin); (*rotPlane)->Rebuild(); } }
void CAI_Spotlight::UpdateSpotlightDirection( void ) { if ( !m_hSpotlight ) { CreateSpotlightEntities(); } // Compute the current beam direction Vector vTargetDir; VectorSubtract( m_vSpotlightTargetPos, m_hSpotlight->GetAbsStartPos(), vTargetDir ); VectorNormalize(vTargetDir); ConstrainToCone( &vTargetDir ); // Compute the amount to rotate float flDot = DotProduct( vTargetDir, m_vSpotlightDir ); flDot = clamp( flDot, -1.0f, 1.0f ); float flAngle = AngleNormalize( RAD2DEG( acos( flDot ) ) ); float flClampedAngle = clamp( flAngle, 0.0f, 45.0f ); float flBeamTurnRate = SimpleSplineRemapVal( flClampedAngle, 0.0f, 45.0f, 10.0f, 45.0f ); if ( fabs(flAngle) > flBeamTurnRate * gpGlobals->frametime ) { flAngle = flBeamTurnRate * gpGlobals->frametime; } // Compute the rotation axis Vector vecRotationAxis; CrossProduct( m_vSpotlightDir, vTargetDir, vecRotationAxis ); if ( VectorNormalize( vecRotationAxis ) < 1e-3 ) { vecRotationAxis.Init( 0, 0, 1 ); } // Compute the actual rotation amount, using quat slerp blending Quaternion desiredQuat, resultQuat; AxisAngleQuaternion( vecRotationAxis, flAngle, desiredQuat ); QuaternionSlerp( m_vAngularVelocity, desiredQuat, QUAT_BLEND_FACTOR, resultQuat ); m_vAngularVelocity = resultQuat; // If we're really close, and we're not moving very quickly, slam. float flActualRotation = AngleNormalize( RAD2DEG(2 * acos(m_vAngularVelocity.w)) ); if (( flActualRotation < 1e-3 ) && (flAngle < 1e-3 )) { m_vSpotlightDir = vTargetDir; m_vAngularVelocity.Init( 0, 0, 0, 1 ); return; } // Update the desired direction matrix3x4_t rot; Vector vecNewDir; QuaternionMatrix( m_vAngularVelocity, rot ); VectorRotate( m_vSpotlightDir, rot, vecNewDir ); m_vSpotlightDir = vecNewDir; VectorNormalize(m_vSpotlightDir); }
//----------------------------------------------------------------------------- // Purpose: // Input : flConvergencePerc - // vecBasis - //----------------------------------------------------------------------------- void CNPC_Combine_Cannon::UpdateAncillaryBeams( float flConvergencePerc, const Vector &vecOrigin, const Vector &vecBasis ) { // Multiple beams deviate from the basis direction by a certain number of degrees and "converge" // at the basis vector over a duration of time, the position in that duration expressed by // flConvergencePerc. The beams are most deviated at 0 and fully converged at 1. float flRotationOffset = (2*M_PI)/(float)NUM_ANCILLARY_BEAMS; // Degrees separating each beam, in radians float flDeviation = DEG2RAD(90) * ( 1.0f - flConvergencePerc ); float flOffset; Vector vecFinal; Vector vecOffset; matrix3x4_t matRotate; QAngle vecAngles; VectorAngles( vecBasis, vecAngles ); vecAngles[PITCH] += 90.0f; AngleMatrix( vecAngles, vecOrigin, matRotate ); trace_t tr; float flScale = LINE_LENGTH * flDeviation; // For each beam, find its offset and trace outwards to place its endpoint for ( int i = 0; i < NUM_ANCILLARY_BEAMS; i++ ) { if ( flConvergencePerc >= 0.99f ) { m_pAncillaryBeams[i]->TurnOn(); continue; } m_pAncillaryBeams[i]->TurnOff(); // Find the number of radians offset we are flOffset = (float) i * flRotationOffset + DEG2RAD( 30.0f ); flOffset += (M_PI/8.0f) * sin( gpGlobals->curtime * 3.0f ); // Construct a circle that's also offset by the line's length vecOffset.x = cos( flOffset ) * flScale; vecOffset.y = sin( flOffset ) * flScale; vecOffset.z = LINE_LENGTH; // Rotate this whole thing into the space of the basis vector VectorRotate( vecOffset, matRotate, vecFinal ); VectorNormalize( vecFinal ); // Trace a line down that vector to find where we'll eventually stop our line UTIL_TraceLine( vecOrigin, vecOrigin + ( vecFinal * LINE_LENGTH ), MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); // Move the beam to that position m_pAncillaryBeams[i]->SetBrightness( static_cast<int>(255.0f * flConvergencePerc) ); m_pAncillaryBeams[i]->SetEndPos( tr.startpos ); m_pAncillaryBeams[i]->SetStartPos( tr.endpos ); } }
/* ================= S_SpatializeOrigin Used for spatializing s_channels ================= */ void S_SpatializeOrigin (vec3_t origin, int master_vol, int *left_vol, int *right_vol) { vec_t dot; vec_t dist; vec_t lscale, rscale, scale; vec3_t source_vec; vec3_t vec; const float dist_mult = SOUND_ATTENUATE; // calculate stereo seperation and distance attenuation VectorSubtract(origin, listener_origin, source_vec); dist = VectorNormalize(source_vec); dist -= SOUND_FULLVOLUME; if (dist < 0) dist = 0; // close enough to be at full volume dist *= dist_mult; // different attenuation levels VectorRotate( source_vec, listener_axis, vec ); dot = -vec[1]; if (dma.channels == 1) { // no attenuation = no spatialization rscale = 1.0; lscale = 1.0; } else { rscale = 0.5 * (1.0 + dot); lscale = 0.5 * (1.0 - dot); //rscale = s_separation->value + ( 1.0 - s_separation->value ) * dot; //lscale = s_separation->value - ( 1.0 - s_separation->value ) * dot; if ( rscale < 0 ) { rscale = 0; } if ( lscale < 0 ) { lscale = 0; } } // add in distance effect scale = (1.0 - dist) * rscale; *right_vol = (master_vol * scale); if (*right_vol < 0) *right_vol = 0; scale = (1.0 - dist) * lscale; *left_vol = (master_vol * scale); if (*left_vol < 0) *left_vol = 0; }
void ComputeAbsolute(face_t* f, vec3_t& p1, vec3_t& p2, vec3_t& p3) { vec3_t ex,ey,ez; // local axis base // compute first local axis base TextureAxisFromPlane(&f->plane, ex, ey); CrossProduct(ex, ey, ez); vec3_t aux; VectorCopy(ex, aux); VectorScale(aux, -f->texdef.shift[0], aux); VectorCopy(aux, p1); VectorCopy(ey, aux); VectorScale(aux, -f->texdef.shift[1], aux); VectorAdd(p1, aux, p1); VectorCopy(p1, p2); VectorAdd(p2, ex, p2); VectorCopy(p1, p3); VectorAdd(p3, ey, p3); VectorCopy(ez, aux); VectorScale(aux, -f->texdef.rotate, aux); VectorRotate(p1, aux, p1); VectorRotate(p2, aux, p2); VectorRotate(p3, aux, p3); // computing rotated local axis base vec3_t rex,rey; VectorCopy(ex, rex); VectorRotate(rex, aux, rex); VectorCopy(ey, rey); VectorRotate(rey, aux, rey); ComputeScale(rex,rey,p1,f); ComputeScale(rex,rey,p2,f); ComputeScale(rex,rey,p3,f); // project on normal plane // along ez // assumes plane normal is normalized ProjectOnPlane(f->plane.normal,f->plane.dist,ez,p1); ProjectOnPlane(f->plane.normal,f->plane.dist,ez,p2); ProjectOnPlane(f->plane.normal,f->plane.dist,ez,p3); };
void Solid::Rotate(const Vector & a, const Vector & b, float angle) { for(int i = 0; i < vertices.GetSize(); i++) { Vector v = vertices.GetVector(i); v = VectorRotate(v, a, b, angle); vertices.SetVector(i, v); } }
void CalculateMinsMaxs (const vec3_t angles, const vec3_t mins, const vec3_t maxs, const vec3_t origin, vec3_t absmin, vec3_t absmax) { /* expand for rotation */ if (VectorNotEmpty(angles)) { vec3_t minVec, maxVec, tmpMinVec, tmpMaxVec; vec3_t centerVec, halfVec, newCenterVec, newHalfVec; vec3_t m[3]; /* Find the center of the extents. */ VectorCenterFromMinsMaxs(mins, maxs, centerVec); /* Find the half height and half width of the extents. */ VectorSubtract(maxs, centerVec, halfVec); /* Rotate the center about the origin. */ VectorCreateRotationMatrix(angles, m); VectorRotate(m, centerVec, newCenterVec); VectorRotate(m, halfVec, newHalfVec); /* Set minVec and maxVec to bound around newCenterVec at halfVec size. */ VectorSubtract(newCenterVec, newHalfVec, tmpMinVec); VectorAdd(newCenterVec, newHalfVec, tmpMaxVec); /* rotation may have changed min and max of the box, so adjust it */ minVec[0] = min(tmpMinVec[0], tmpMaxVec[0]); minVec[1] = min(tmpMinVec[1], tmpMaxVec[1]); minVec[2] = min(tmpMinVec[2], tmpMaxVec[2]); maxVec[0] = max(tmpMinVec[0], tmpMaxVec[0]); maxVec[1] = max(tmpMinVec[1], tmpMaxVec[1]); maxVec[2] = max(tmpMinVec[2], tmpMaxVec[2]); /* Adjust the absolute mins/maxs */ VectorAdd(origin, minVec, absmin); VectorAdd(origin, maxVec, absmax); } else { /* normal */ VectorAdd(origin, mins, absmin); VectorAdd(origin, maxs, absmax); } }
void TransformNormal (MS3D *ms3d, const ms3d_vertex_t *vertex, const vec3_t normal, vec3_t out) { int i; int jointIndices[4], jointWeights[4]; FillJointIndicesAndWeights(vertex, jointIndices, jointWeights); //if (jointIndices[0] < 0 || jointIndices[0] >= (int) m_joints.size() || m_currentTime < 0.0f) if (jointIndices[0] < 0 || jointIndices[0] >= ms3d->nNumJoints || ms3d->fCurrentTime < 0.0f) { out[0] = normal[0]; out[1] = normal[1]; out[2] = normal[2]; } else { // count valid weights int numWeights = 0; for (i = 0; i < 4; i++) { if (jointWeights[i] > 0 && jointIndices[i] >= 0 && jointIndices[i] < ms3d->nNumJoints) ++numWeights; else break; } // init out[0] = 0.0f; out[1] = 0.0f; out[2] = 0.0f; float weights[4] = { (float) jointWeights[0] / 100.0f, (float) jointWeights[1] / 100.0f, (float) jointWeights[2] / 100.0f, (float) jointWeights[3] / 100.0f }; if (numWeights == 0) { numWeights = 1; weights[0] = 1.0f; } // add weighted vertices for (i = 0; i < numWeights; i++) { //const ms3d_joint_t *joint = &m_joints[jointIndices[i]]; const ms3d_joint_t *joint = &ms3d->joints[jointIndices[i]]; vec3_t tmp, norm; VectorIRotate(normal, joint->matGlobalSkeleton, tmp); VectorRotate(tmp, joint->matGlobal, norm); out[0] += norm[0] * weights[i]; out[1] += norm[1] * weights[i]; out[2] += norm[2] * weights[i]; } } }
/** * @brief Rotates AABB around given origin point; note that it will expand the box unless all angles are multiples of 90 degrees * @note Not fully verified so far */ void AABB::rotateAround (const vec3_t origin, const vec3_t angles) { /* reject non-rotations */ if (VectorEmpty(angles)) return; /* construct box-centered coordinates (center and corners) */ vec3_t center, halfDiagonal; VectorInterpolation(mins, maxs, 0.5f, center); VectorSubtract(maxs, center, halfDiagonal); /* offset coordinate frame to rotation origin */ VectorSubtract(center, origin, center); /* rotate center by given angles */ vec3_t m[3]; VectorCreateRotationMatrix(angles, m); vec3_t newCenter; VectorRotate(m, center, newCenter); /* short-circuit calculation of the rotated box half-extents */ /* shortcut is: instead of calculating all 8 AABB corners, use the symmetry by rotating box around it's center. */ VectorAbs(m[0]); VectorAbs(m[1]); VectorAbs(m[2]); vec3_t newHalfDiagonal; VectorRotate(m, halfDiagonal, newHalfDiagonal); /* de-offset coordinate frame from rotation origin */ VectorAdd(newCenter, origin, newCenter); /* finally, combine results into new AABB */ VectorAdd(newCenter, newHalfDiagonal, maxs); VectorSubtract(newCenter, newHalfDiagonal, mins); }
//-------------------------------- void CPoly::Rotate() { vec3_t temp[MAX_CPOLY_VERTS]; float dif = fabs( (double)(mLastFrameTime - theFxHelper.mFrameTime) ); // Very generous check with frameTimes if ( dif > 0.5f * mLastFrameTime ) { CalcRotateMatrix(); } // Multiply our rotation matrix by each of the offset verts to get their new position for ( int i = 0; i < mCount; i++ ) { VectorRotate( mOrg[i], mRot, temp[i] ); VectorCopy( temp[i], mOrg[i] ); } }
int qlua_VectorRotate(lua_State *L) { vec3_t in,out; vec3_t axis[3]; luaL_checktype(L,1,LUA_TVECTOR); luaL_checktype(L,2,LUA_TVECTOR); luaL_checktype(L,3,LUA_TVECTOR); luaL_checktype(L,4,LUA_TVECTOR); lua_tovector(L,1,in); lua_tovector(L,2,axis[0]); lua_tovector(L,3,axis[1]); lua_tovector(L,4,axis[2]); VectorRotate(in,axis,out); lua_pushvector(L,out); return 1; }
//------------------------------------------------------------------------------ // Constrain to cone //------------------------------------------------------------------------------ bool CAI_Spotlight::ConstrainToCone( Vector *pDirection ) { Vector vecOrigin, vecForward; if ( m_nSpotlightAttachment == 0 ) { QAngle vecAngles; vecAngles = GetOuter()->GetAbsAngles(); AngleVectors( vecAngles, &vecForward ); } else { GetOuter()->GetAttachment( m_nSpotlightAttachment, vecOrigin, &vecForward ); } if ( m_flConstraintAngle == 0.0f ) { *pDirection = vecForward; return true; } float flDot = DotProduct( vecForward, *pDirection ); if ( flDot >= cos( DEG2RAD( m_flConstraintAngle ) ) ) return false; Vector vecAxis; CrossProduct( *pDirection, vecForward, vecAxis ); VectorNormalize( vecAxis ); Quaternion q; AxisAngleQuaternion( vecAxis, -m_flConstraintAngle, q ); Vector vecResult; matrix3x4_t rot; QuaternionMatrix( q, rot ); VectorRotate( vecForward, rot, vecResult ); VectorNormalize( vecResult ); *pDirection = vecResult; return true; }
void InvertMatrix(GLfloat mtxin[16], GLfloat mtxout[16]) { MatrixInvRotate(mtxin, mtxout); GLfloat vTmp[4], vTmp2[4]; vTmp[0] = -mtxin[12]; vTmp[1] = -mtxin[13]; vTmp[2] = -mtxin[14]; VectorRotate(vTmp, mtxout, vTmp2); mtxout[12] = vTmp2[0]; mtxout[13] = vTmp2[1]; mtxout[14] = vTmp2[2]; mtxout[3] = mtxout[7] = mtxout[11] = 0.0f; mtxout[15] = 1.0f; }
IMotionEvent::simresult_e CKeepUpright::Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular ) { if ( !m_bActive ) return SIM_NOTHING; Vector currentAxis; matrix3x4_t matrix; // get the object's local to world transform pObject->GetPositionMatrix( matrix ); // Get the object's local test axis in world space VectorRotate( m_localTestAxis, matrix, currentAxis ); Vector rotationAxis = CrossProduct( currentAxis, m_worldGoalAxis ); // atan2() is well defined, so do a Dot & Cross instead of asin(Cross) float cosine = DotProduct( currentAxis, m_worldGoalAxis ); float sine = VectorNormalize( rotationAxis ); float angle = atan2( sine, cosine ); angle = RAD2DEG(angle); rotationAxis *= angle; VectorIRotate( rotationAxis, matrix, angular ); float invDeltaTime = (1/deltaTime); angular *= invDeltaTime * invDeltaTime; AngularImpulse angVel; pObject->GetVelocity( NULL, &angVel ); angular -= angVel; float len = VectorNormalize( angular ); if ( len > m_angularLimit * invDeltaTime ) len = m_angularLimit * invDeltaTime; angular *= len; linear.Init(); return SIM_LOCAL_ACCELERATION; }
/* =============== ComputeColors =============== */ static void ComputeColors( shaderStage_t *pStage ) { int i; // // rgbGen // switch ( pStage->rgbGen ) { case CGEN_IDENTITY: memset( tess.svars.colors, 0xff, tess.numVertexes * 4 ); break; default: case CGEN_IDENTITY_LIGHTING: memset( tess.svars.colors, tr.identityLightByte, tess.numVertexes * 4 ); break; case CGEN_LIGHTING_DIFFUSE: RB_CalcDiffuseColor( ( unsigned char * ) tess.svars.colors ); break; case CGEN_EXACT_VERTEX: memcpy( tess.svars.colors, tess.vertexColors, tess.numVertexes * sizeof( tess.vertexColors[0].v ) ); break; case CGEN_CONST: for ( i = 0; i < tess.numVertexes; i++ ) { *(int *)tess.svars.colors[i] = *(int *)pStage->constantColor; } break; case CGEN_VERTEX: if ( tr.identityLight == 1 ) { memcpy( tess.svars.colors, tess.vertexColors, tess.numVertexes * sizeof( tess.vertexColors[0].v ) ); } else { for ( i = 0; i < tess.numVertexes; i++ ) { tess.svars.colors[i][0] = tess.vertexColors[i].v[0] * tr.identityLight; tess.svars.colors[i][1] = tess.vertexColors[i].v[1] * tr.identityLight; tess.svars.colors[i][2] = tess.vertexColors[i].v[2] * tr.identityLight; tess.svars.colors[i][3] = tess.vertexColors[i].v[3]; } } break; case CGEN_ONE_MINUS_VERTEX: if ( tr.identityLight == 1 ) { for ( i = 0; i < tess.numVertexes; i++ ) { tess.svars.colors[i][0] = 255 - tess.vertexColors[i].v[0]; tess.svars.colors[i][1] = 255 - tess.vertexColors[i].v[1]; tess.svars.colors[i][2] = 255 - tess.vertexColors[i].v[2]; } } else { for ( i = 0; i < tess.numVertexes; i++ ) { tess.svars.colors[i][0] = ( 255 - tess.vertexColors[i].v[0] ) * tr.identityLight; tess.svars.colors[i][1] = ( 255 - tess.vertexColors[i].v[1] ) * tr.identityLight; tess.svars.colors[i][2] = ( 255 - tess.vertexColors[i].v[2] ) * tr.identityLight; } } break; case CGEN_FOG: { fog_t *fog; fog = tr.world->fogs + tess.fogNum; for ( i = 0; i < tess.numVertexes; i++ ) { *( int * )&tess.svars.colors[i] = fog->shader->fogParms.colorInt; } } break; case CGEN_WAVEFORM: RB_CalcWaveColor( &pStage->rgbWave, ( unsigned char * ) tess.svars.colors ); break; case CGEN_ENTITY: RB_CalcColorFromEntity( ( unsigned char * ) tess.svars.colors ); break; case CGEN_ONE_MINUS_ENTITY: RB_CalcColorFromOneMinusEntity( ( unsigned char * ) tess.svars.colors ); break; } // // alphaGen // switch ( pStage->alphaGen ) { case AGEN_SKIP: break; case AGEN_IDENTITY: if ( pStage->rgbGen != CGEN_IDENTITY ) { if ( ( pStage->rgbGen == CGEN_VERTEX && tr.identityLight != 1 ) || pStage->rgbGen != CGEN_VERTEX ) { for ( i = 0; i < tess.numVertexes; i++ ) { tess.svars.colors[i][3] = 0xff; } } } break; case AGEN_CONST: if ( pStage->rgbGen != CGEN_CONST ) { for ( i = 0; i < tess.numVertexes; i++ ) { tess.svars.colors[i][3] = pStage->constantColor[3]; } } break; case AGEN_WAVEFORM: RB_CalcWaveAlpha( &pStage->alphaWave, ( unsigned char * ) tess.svars.colors ); break; case AGEN_LIGHTING_SPECULAR: RB_CalcSpecularAlpha( ( unsigned char * ) tess.svars.colors ); break; case AGEN_ENTITY: RB_CalcAlphaFromEntity( ( unsigned char * ) tess.svars.colors ); break; case AGEN_ONE_MINUS_ENTITY: RB_CalcAlphaFromOneMinusEntity( ( unsigned char * ) tess.svars.colors ); break; // Ridah case AGEN_NORMALZFADE: { float alpha, range, lowest, highest, dot; vec3_t worldUp; qboolean zombieEffect = qfalse; if ( VectorCompare( backEnd.currentEntity->e.fireRiseDir, vec3_origin ) ) { VectorSet( backEnd.currentEntity->e.fireRiseDir, 0, 0, 1 ); } if ( backEnd.currentEntity->e.hModel ) { // world surfaces dont have an axis VectorRotate( backEnd.currentEntity->e.fireRiseDir, backEnd.currentEntity->e.axis, worldUp ); } else { VectorCopy( backEnd.currentEntity->e.fireRiseDir, worldUp ); } lowest = pStage->zFadeBounds[0]; if ( lowest == -1000 ) { // use entity alpha lowest = backEnd.currentEntity->e.shaderTime; zombieEffect = qtrue; } highest = pStage->zFadeBounds[1]; if ( highest == -1000 ) { // use entity alpha highest = backEnd.currentEntity->e.shaderTime; zombieEffect = qtrue; } range = highest - lowest; for ( i = 0; i < tess.numVertexes; i++ ) { dot = DotProduct( tess.normal[i].v, worldUp ); // special handling for Zombie fade effect if ( zombieEffect ) { alpha = (float)backEnd.currentEntity->e.shaderRGBA[3] * ( dot + 1.0 ) / 2.0; alpha += ( 2.0 * (float)backEnd.currentEntity->e.shaderRGBA[3] ) * ( 1.0 - ( dot + 1.0 ) / 2.0 ); if ( alpha > 255.0 ) { alpha = 255.0; } else if ( alpha < 0.0 ) { alpha = 0.0; } tess.svars.colors[i][3] = (byte)( alpha ); continue; } if ( dot < highest ) { if ( dot > lowest ) { if ( dot < lowest + range / 2 ) { alpha = ( (float)pStage->constantColor[3] * ( ( dot - lowest ) / ( range / 2 ) ) ); } else { alpha = ( (float)pStage->constantColor[3] * ( 1.0 - ( ( dot - lowest - range / 2 ) / ( range / 2 ) ) ) ); } if ( alpha > 255.0 ) { alpha = 255.0; } else if ( alpha < 0.0 ) { alpha = 0.0; } // finally, scale according to the entity's alpha if ( backEnd.currentEntity->e.hModel ) { alpha *= (float)backEnd.currentEntity->e.shaderRGBA[3] / 255.0; } tess.svars.colors[i][3] = (byte)( alpha ); } else { tess.svars.colors[i][3] = 0; } } else { tess.svars.colors[i][3] = 0; } } } break; // done. case AGEN_VERTEX: if ( pStage->rgbGen != CGEN_VERTEX ) { for ( i = 0; i < tess.numVertexes; i++ ) { tess.svars.colors[i][3] = tess.vertexColors[i].v[3]; } } break; case AGEN_ONE_MINUS_VERTEX: for ( i = 0; i < tess.numVertexes; i++ ) { tess.svars.colors[i][3] = 255 - tess.vertexColors[i].v[3]; } break; case AGEN_PORTAL: { unsigned char alpha; for ( i = 0; i < tess.numVertexes; i++ ) { float len; vec3_t v; VectorSubtract( tess.xyz[i].v, backEnd.viewParms.orientation.origin, v ); len = VectorLength( v ); len /= tess.shader->portalRange; if ( len < 0 ) { alpha = 0; } else if ( len > 1 ) { alpha = 0xff; } else { alpha = len * 0xff; } tess.svars.colors[i][3] = alpha; } } break; } // // fog adjustment for colors to fade out as fog increases // if ( tess.fogNum && !tess.shader->noFog ) { switch ( pStage->adjustColorsForFog ) { case ACFF_MODULATE_RGB: RB_CalcModulateColorsByFog( ( unsigned char * ) tess.svars.colors ); break; case ACFF_MODULATE_ALPHA: RB_CalcModulateAlphasByFog( ( unsigned char * ) tess.svars.colors ); break; case ACFF_MODULATE_RGBA: RB_CalcModulateRGBAsByFog( ( unsigned char * ) tess.svars.colors ); break; case ACFF_NONE: break; } } }
/** * @brief This function recalculates the routing surrounding the entity name. * @sa CM_InlineModel * @sa CM_CheckUnit * @sa CM_UpdateConnection * @sa CMod_LoadSubmodels * @sa Grid_RecalcBoxRouting * @param[in] mapTiles List of tiles the current (RMA-)map is composed of * @param[in] routing The routing map (either server or client map) * @param[in] name Name of the inline model to compute the mins/maxs for * @param[in] box The box around the inline model (alternative to name) * @param[in] list The local models list (a local model has a name starting with * followed by the model number) */ void Grid_RecalcRouting (mapTiles_t *mapTiles, Routing &routing, const char *name, const GridBox &box, const char **list) { if (box.isZero()) { pos3_t min, max; vec3_t absmin, absmax; const cBspModel_t *model; unsigned int i; /* get inline model, if it is one */ if (*name != '*') { Com_Printf("Called Grid_RecalcRouting with no inline model\n"); return; } model = CM_InlineModel(mapTiles, name); if (!model) { Com_Printf("Called Grid_RecalcRouting with invalid inline model name '%s'\n", name); return; } #if 1 /* An attempt to fix the 'doors starting opened' bug (# 3456). * The main difference is the (missing) rotation of the halfVec. * The results are better, but do not fix the problem. */ CalculateMinsMaxs(model->angles, model->mins, model->maxs, model->origin, absmin, absmax); #else /* get the target model's dimensions */ if (VectorNotEmpty(model->angles)) { vec3_t minVec, maxVec; vec3_t centerVec, halfVec, newCenterVec; vec3_t m[3]; /* Find the center of the extents. */ VectorCenterFromMinsMaxs(model->mins, model->maxs, centerVec); /* Find the half height and half width of the extents. */ VectorSubtract(model->maxs, centerVec, halfVec); /* Rotate the center about the origin. */ VectorCreateRotationMatrix(model->angles, m); VectorRotate(m, centerVec, newCenterVec); /* Set minVec and maxVec to bound around newCenterVec at halfVec size. */ VectorSubtract(newCenterVec, halfVec, minVec); VectorAdd(newCenterVec, halfVec, maxVec); /* Now offset by origin then convert to position (Doors do not have 0 origins) */ VectorAdd(minVec, model->origin, absmin); VectorAdd(maxVec, model->origin, absmax); } else { /* normal */ /* Now offset by origin then convert to position (Doors do not have 0 origins) */ VectorAdd(model->mins, model->origin, absmin); VectorAdd(model->maxs, model->origin, absmax); } #endif VecToPos(absmin, min); VecToPos(absmax, max); /* fit min/max into the world size */ max[0] = std::min(max[0], (pos_t)(PATHFINDING_WIDTH - 1)); max[1] = std::min(max[1], (pos_t)(PATHFINDING_WIDTH - 1)); max[2] = std::min(max[2], (pos_t)(PATHFINDING_HEIGHT - 1)); for (i = 0; i < 3; i++) min[i] = std::max(min[i], (pos_t)0); /* We now have the dimensions, call the generic rerouting function. */ GridBox rerouteBox(min, max); Grid_RecalcBoxRouting(mapTiles, routing, rerouteBox, list); } else { /* use the passed box */ Grid_RecalcBoxRouting(mapTiles, routing, box, list); } }
//----------------------------------------------------------------------------- //----------------------------------------------------------------------------- bool CGrabController::UpdateObject( CBasePlayer *pPlayer, float flError ) { CBaseEntity *pEntity = GetAttached(); if ( !pEntity || ComputeError() > flError || pPlayer->GetGroundEntity() == pEntity || !pEntity->VPhysicsGetObject() ) { return false; } //Adrian: Oops, our object became motion disabled, let go! IPhysicsObject *pPhys = pEntity->VPhysicsGetObject(); if ( pPhys && pPhys->IsMoveable() == false ) { return false; } Vector forward, right, up; QAngle playerAngles = pPlayer->EyeAngles(); AngleVectors( playerAngles, &forward, &right, &up ); float pitch = AngleDistance(playerAngles.x,0); if( !m_bAllowObjectOverhead ) { playerAngles.x = clamp( pitch, -75, 75 ); } else { playerAngles.x = clamp( pitch, -90, 75 ); } // Now clamp a sphere of object radius at end to the player's bbox Vector radial = physcollision->CollideGetExtent( pPhys->GetCollide(), vec3_origin, pEntity->GetAbsAngles(), -forward ); Vector player2d = pPlayer->CollisionProp()->OBBMaxs(); float playerRadius = player2d.Length2D(); float radius = playerRadius + fabs(DotProduct( forward, radial )); float distance = 24 + ( radius * 2.0f ); // Add the prop's distance offset distance += m_flDistanceOffset; Vector start = pPlayer->Weapon_ShootPosition(); Vector end = start + ( forward * distance ); trace_t tr; CTraceFilterSkipTwoEntities traceFilter( pPlayer, pEntity, COLLISION_GROUP_NONE ); Ray_t ray; ray.Init( start, end ); enginetrace->TraceRay( ray, MASK_SOLID_BRUSHONLY, &traceFilter, &tr ); if ( tr.fraction < 0.5 ) { end = start + forward * (radius*0.5f); } else if ( tr.fraction <= 1.0f ) { end = start + forward * ( distance - radius ); } Vector playerMins, playerMaxs, nearest; pPlayer->CollisionProp()->WorldSpaceAABB( &playerMins, &playerMaxs ); Vector playerLine = pPlayer->CollisionProp()->WorldSpaceCenter(); CalcClosestPointOnLine( end, playerLine+Vector(0,0,playerMins.z), playerLine+Vector(0,0,playerMaxs.z), nearest, NULL ); if( !m_bAllowObjectOverhead ) { Vector delta = end - nearest; float len = VectorNormalize(delta); if ( len < radius ) { end = nearest + radius * delta; } } //Show overlays of radius if ( g_debug_physcannon.GetBool() ) { NDebugOverlay::Box( end, -Vector( 2,2,2 ), Vector(2,2,2), 0, 255, 0, true, 0 ); NDebugOverlay::Box( GetAttached()->WorldSpaceCenter(), -Vector( radius, radius, radius), Vector( radius, radius, radius ), 255, 0, 0, true, 0.0f ); } QAngle angles = TransformAnglesFromPlayerSpace( m_attachedAnglesPlayerSpace, pPlayer ); // If it has a preferred orientation, update to ensure we're still oriented correctly. Pickup_GetPreferredCarryAngles( pEntity, pPlayer, pPlayer->EntityToWorldTransform(), angles ); // We may be holding a prop that has preferred carry angles if ( m_bHasPreferredCarryAngles ) { matrix3x4_t tmp; ComputePlayerMatrix( pPlayer, tmp ); angles = TransformAnglesToWorldSpace( m_vecPreferredCarryAngles, tmp ); } matrix3x4_t attachedToWorld; Vector offset; AngleMatrix( angles, attachedToWorld ); VectorRotate( m_attachedPositionObjectSpace, attachedToWorld, offset ); SetTargetPosition( end - offset, angles ); return true; }