坐标系:

 z-axis
^
|
| y-axis
| /
| /
|/
+----------------> x-axis

围绕Z轴旋转叫做偏航角,Yaw;围绕X轴旋转叫做 俯仰角,Pitch;围绕Y轴旋转,叫做滚转角,Roll 

///////////////////////////////////////////////////////////////////////////////////////////////////////////////

相机的标记:
//使用三个标记,记录相机行进方向;相机无非就是向前,向后,旋转,这三个状态
int m_flags;
int m_forwardFlags;
int m_backwardsFlags;

初始化时:

    m_flags = eVCam_goingForwards | eVCam_canRotate; // 向前 + 可旋转
m_forwardFlags = eVCam_rotationSpring | eVCam_rotationClamp; //带悬架的旋转 + 限制旋转角度
m_backwardsFlags = m_forwardFlags;//和上面那个值一样,所以感觉没什么用处

接受用户输入的旋转:

void CVehicleViewSteer::OnAction(const TVehicleActionId actionId, int activationMode, float value)
{//看看上面的图就了然了
if (m_flags & eVCam_canRotate)
{
if (actionId == eVAI_RotateYaw)
{
m_rotatingAction.z += value;
}
else if (actionId == eVAI_RotatePitch)
{
m_rotatingAction.x += value;
}
}
}

//////////////////////////////////////////////////////////////////////////////////////////////////

    IEntity * pEntity = m_pVehicle->GetEntity();
assert(pEntity); CVehicleMovementBase * pVehicleMovement = static_cast<CVehicleMovementBase*>(m_pVehicle->GetMovement());
const pe_status_dynamics& dynStatus = pVehicleMovement->GetPhysicsDyn(); //这个貌似是取出了物理系统 SMovementState movementState;
pVehicleMovement->GetMovementState(movementState);
const float pedal = pVehicleMovement->GetEnginePedal();//获取坦克引擎力
const float maxSpeed = movementState.maxSpeed;//获取当前坦克的最大速度
const Matrix34& pose = m_pAimPart ? m_pAimPart->GetWorldTM() : pEntity->GetWorldTM();//取出坦克的世界坐标到局部坐标的矩阵
const Vec3 entityPos = pose.GetColumn3();
const Vec3 xAxis = pose.GetColumn0();
const Vec3 yAxis = pose.GetColumn1();
const Vec3 zAxis = pose.GetColumn2();
const float forwardSpeed = dynStatus.v.dot(yAxis);//当前坦克的速度,在Y轴上的投影,就是Y轴方向上的速度了
const float speedNorm = clamp(forwardSpeed / maxSpeed, 0.0f, 1.0f);//计算出这个Y轴的速度与最大速度比例,其实就是个百分比
const Vec3 maxRotation = m_maxRotation + speedNorm * (m_maxRotation2 - m_maxRotation);//这个不知道 CalcLookAt(pose);//根据世界坐标矩阵,计算 m_lookAt,看起来是将look at转到坦克本地坐标系下
if (m_lookAt.IsValid())
{
if (!m_lastOffset.IsValid())
{
       //如果之前没有设置过last offset
m_position = pose * m_localSpaceCameraOffset; //这个应该是想把相机设置到坦克局部坐标系下,同时偏移了一个offset
m_lastOffset = m_position - m_lookAt;// 基本上相当于相机和坦克之间的向量
m_lastOffsetBeforeElev = m_lastOffset;
} Vec3 offset = m_lastOffsetBeforeElev; if (pedal<0.1f && forwardSpeed<1.0f)
{//Y轴速度小于 1,并且当前引擎马力小于 0.1,说明相机要向后移动
// Going Backwards
m_flags &= ~(eVCam_goingForwards | m_forwardFlags);
m_flags |= m_backwardsFlags;
} if (offset.dot(yAxis) < 0.8f && forwardSpeed>.f)
{//Y轴速度大于1,并且上次的偏移在Y轴上的投影大于等于0.8,说明相机要向前移动
// Going Forwards
m_flags &= ~m_backwardsFlags;
m_flags |= eVCam_goingForwards | m_forwardFlags;
}

     
float sensitivity = (.f-speedNorm) * m_stickSensitivity.z + speedNorm * m_stickSensitivity2.z;//影响值。speedNorm是个比例,意义是,在stickSensitivity1,2之间做插值
float rotate = -m_rotatingAction.z * sensitivity;//输入的Z要乘以个0.5,即sensitivity的值
rotate = rotate * dt;//再乘以时间? if (zAxis.z > 0.1f)
{//如果坦克的高度超过 0.1
// Safe to update curYaw
Vec3 projectedX = xAxis; projectedX.z = .f;
Vec3 projectedY = yAxis; projectedY.z = .f;
const float newYaw = atan2_tpl(offset.dot(projectedX), -(offset.dot(projectedY)));
const float maxChange = DEG2RAD(.f)*dt;
const float delta = clamp(newYaw - m_curYaw, -maxChange, +maxChange);
m_curYaw += delta;
} // Rotation Action
{
if (m_flags & eVCam_rotationClamp)
{
float newYaw = clamp(m_curYaw + rotate, -maxRotation.z, +maxRotation.z);
rotate = newYaw - m_curYaw;
rotate = clamp(newYaw - m_curYaw, -fabsf(rotate), +fabsf(rotate));
m_rotation.z += rotate;
}
else
{
m_rotation.z=.f;
} if (speedNorm > 0.1f)
{
float reduce = dt * .f;
m_rotation.z = m_rotation.z - reduce*m_rotation.z/(fabsf(m_rotation.z) + reduce);
}
} // Ang Spring
{
float angSpeedCorrection = dt*dt*m_angSpeedCorrection/(dt*m_angSpeedCorrection+.f)*dynStatus.w.z;
if ((m_flags & eVCam_rotationSpring)==)
{
m_angReturnSpeed = .f;
angSpeedCorrection = .f;
} float difference = m_rotation.z - m_curYaw;
float relax = difference * (m_angReturnSpeed*dt) / ((m_angReturnSpeed*dt) + .f); const float delta = +relax + angSpeedCorrection + rotate;
m_curYaw += delta; Matrix33 rot = Matrix33::CreateRotationZ(delta);
offset = rot * offset; // Lerp the spring speed
float angSpeedTarget = m_angReturnSpeed1 + speedNorm * (m_angReturnSpeed2 - m_angReturnSpeed1);
m_angReturnSpeed += (angSpeedTarget - m_angReturnSpeed) * (dt/(dt+0.3f));
m_angSpeedCorrection += (m_angSpeedCorrection0 - m_angSpeedCorrection) * (dt/(dt+0.3f));
} if (!offset.IsValid()) offset = m_lastOffset; // Velocity influence
Vec3 displacement = -((.f-speedNorm) * dt) * dynStatus.v;//车辆产生位移,这里算的是位移和2倍位移之间的插值,例如,-5和-10之间的插值 float dot = offset.dot(displacement); //Offset 是从相机的偏移位置 到 坦克位置的向量,这个向量和坦克的移动做点积,根据两个向量的方向 ,判断是向前还是向后,再做修正。
if (dot < .f)
{
displacement = displacement + offset * -0.1f * (offset.dot(displacement) / offset.GetLengthSquared());
}
offset = offset + displacement;//这个部分计算的应该是跟随,车辆的移动,需要对偏移值做修正 const float radius0 = fabsf(m_localSpaceCameraOffset.y);
const float minRadius = radius0 * m_radiusMin;
const float maxRadius = radius0 * m_radiusMax;
float radiusXY = sqrtf(sqr(offset.x) + sqr(offset.y)); Vec3 offsetXY = offset; offsetXY.z = .f;
Vec3 accelerationV = (dynStatus.v - m_lastVehVel);//速度变化,加速度
float acceleration = offsetXY.dot(accelerationV) / radiusXY; // m_lastVehVel = dynStatus.v;
m_radiusVel -= acceleration;
m_radius += m_radiusVel * dt - dt*m_radiusVelInfluence * offsetXY.dot(dynStatus.v)/radiusXY;
m_radiusVel *= expf(-dt*m_radiusDampRate);
m_radius += (radius0-m_radius)*(dt*m_radiusRelaxRate)/(dt*m_radiusRelaxRate+.f);
m_radius = clamp(m_radius, minRadius, maxRadius);
offset = offset * (m_radius/radiusXY); // Vertical motion
float targetOffsetHeight = m_localSpaceCameraOffset.z * (m_radius/radius0);//
float oldOffsetHeight = offset.z;
offset.z += (targetOffsetHeight - offset.z)*(dt/(dt+0.3f));
Limit(offset.z, targetOffsetHeight - .f, targetOffsetHeight + .f);
float verticalChange = offset.z - oldOffsetHeight; m_lastOffsetBeforeElev = offset; // Add up and down camera tilt
{
offset.z -= verticalChange;
m_rotation.x += dt * m_stickSensitivity.x * m_rotatingAction.x;
m_rotation.x = clamp(m_rotation.x, -maxRotation.x, +maxRotation.x); float elevAngleVehicle = m_inheritedElev * yAxis.z; // yAxis.z == approx elevation angle float elevationAngle = m_rotation.x - elevAngleVehicle; float sinElev, cosElev;
cry_sincosf(elevationAngle, &sinElev, &cosElev);
float horizLen = sqrtf(offset.GetLengthSquared2D());
float horizLenNew = horizLen * cosElev - sinElev * offset.z;
if (horizLen>1e-4f)
{
horizLenNew /= horizLen;
offset.x *= horizLenNew;
offset.y *= horizLenNew;
offset.z = offset.z * cosElev + sinElev * horizLen;
}
offset.z += verticalChange;
} if (!offset.IsValid()) offset = m_lastOffset; m_position = m_lookAt + offset; // intersection check...
{
IPhysicalEntity* pSkipEntities[];
int nSkip = ;
if(m_pVehicle)
{
nSkip = m_pVehicle->GetSkipEntities(pSkipEntities, );
} primitives::sphere sphere;
sphere.center = m_lookAt;
sphere.r = g_CameraRadius;
Vec3 dir = m_position-m_lookAt; geom_contact *pContact = ;
float hitDist = gEnv->pPhysicalWorld->PrimitiveWorldIntersection(sphere.type, &sphere, dir, ent_static|ent_terrain|ent_rigid|ent_sleeping_rigid,
&pContact, , (geom_colltype_player<<rwi_colltype_bit) | rwi_stop_at_pierceable, , , , pSkipEntities, nSkip);
if(hitDist > 0.0f)
{
// Interpolate the offset
Vec3 newPos = m_lookAt + hitDist * dir.GetNormalizedSafe();
offset = newPos - m_lookAt;
}
} Interpolate(m_lastOffset, offset, .f, dt); m_position = m_lookAt + m_lastOffset;
}
else
{
CRY_ASSERT_MESSAGE(, "camera will fail because lookat position is invalid");
} //float sensitivity = (m_pSensitivity) ? m_pSensitivity->GetFVal() : 1.0f;
m_rotatingAction.zero();

最新文章

  1. LUA之string的使用
  2. 8000401a 错误 ,检索 COM 类工厂中 CLSID 为 的组件时失败,原因是出现以下错误: 8000401a。
  3. file的getPath getAbsolutePath和getCanonicalPath的不同
  4. bootstrap开始咯
  5. VB 如何调用 c++ DLL?
  6. 二维前缀和好题hdu6514
  7. Python3基础 list del 从内存中删除整个列表
  8. superset--presto sql
  9. include_path=&#39;.;C:\php5\pear&#39;解决方法
  10. [Java] jdk与jre的区别
  11. 盒子模型之margin相关技巧!
  12. Java并发编程原理与实战八:产生线程安全性问题原因(javap字节码分析)
  13. Laravel 5.x HTTPS反向代理的实现
  14. 51nod 1118 机器人走方格
  15. MySQL☞substr函数
  16. 【NLP_Stanford课堂】分词
  17. Java环境变量配置以及作用、JDK与JRE区别以及命令行引入jar包
  18. hdu 3641 数论 二分求符合条件的最小值数学杂题
  19. 关于postman、postman interceptor的安装、配置问题
  20. hibernate 事务的隔离级别

热门文章

  1. github常见问题【转自百度知道】
  2. 扩展方法(C#)
  3. 本博客现已迁移到chuxiuhong.com
  4. 移动端HTML
  5. Struts2入门(四)——数据输入验证
  6. Linux归档压缩、分区管理与LVM管理
  7. transformjs污染了DOM?是你不了解它的强大
  8. eclipse启动tomcat无法访问
  9. script在html中的摆放位置
  10. 学习笔记 MYSQL报错注入(count()、rand()、group by)