void ArMoveProperty::UpdateRotation(ArGameEntity* srcEntity, const DiK2Pos& targetPos, float dt, int turnRate) { DiK2RenderObject* renderObj = srcEntity->GetRenderObj(); auto newPos = renderObj->GetPosition(); DiVec3 direction = DiVec3(targetPos.x, 0, targetPos.z) - DiVec3(newPos.x, 0, newPos.z); direction.y = 0; direction.normalise(); float yawToGoal; DiVec3 srcVec = renderObj->GetRotQuat() * DiVec3::UNIT_Z; if ((1.0f + srcVec.dotProduct(direction)) < 0.0001f) yawToGoal = 180; else { DiQuat toGoal = renderObj->GetRotQuat().zAxis().getRotationTo(direction); yawToGoal = toGoal.getYaw().valueDegrees(); } float yawAtSpeed = yawToGoal / DiMath::Abs(yawToGoal) * dt * ((float)turnRate); if (yawToGoal < 0) yawToGoal = std::min<float>(0, std::max<float>(yawToGoal, yawAtSpeed)); else if (yawToGoal > 0) yawToGoal = std::max<float>(0, std::min<float>(yawToGoal, yawAtSpeed)); DiQuat actorOrientation = renderObj->GetRotQuat(); actorOrientation = DiQuat(DiDegree(yawToGoal), DiVec3::UNIT_Y) * actorOrientation; float rotrad = actorOrientation.getYaw().valueRadians(); renderObj->SetRotation(rotrad); }
DiMat4 DiFocusedShadowPolicy::buildViewMatrix(const DiVec3& pos, const DiVec3& dir, const DiVec3& up) const { DiVec3 xN = dir.crossProduct(up); xN.normalise(); DiVec3 upN = xN.crossProduct(dir); upN.normalise(); DiMat4 m(xN.x, xN.y, xN.z, -xN.dotProduct(pos), upN.x, upN.y, upN.z, -upN.dotProduct(pos), -dir.x, -dir.y, -dir.z, dir.dotProduct(pos), 0.0, 0.0, 0.0, 1.0 ); return m; }
void DiNormalShadowPolicy::getShadowCamera (const DiSceneManager *sm, const DiCamera *cam, const DiViewport *vp, const DiLight *light, DiCamera *texCam, size_t iteration) const { DiVec3 pos, dir; // reset custom view / projection matrix in case already set texCam->SetCustomViewMatrix(false); texCam->SetCustomProjectionMatrix(false); texCam->SetNearClipDistance(light->DeriveShadowNearClipDistance(cam)); texCam->SetFarClipDistance(light->DeriveShadowFarClipDistance(cam)); // get the shadow frustum's far distance float shadowDist = sm->GetShadowFarDistance(); if (!shadowDist) { // need a shadow distance, make one up shadowDist = cam->GetNearClipDistance() * 300; } float shadowOffset = shadowDist * (sm->GetShadowDirLightTextureOffset()); // Directional lights if (light->GetType() == LIGHT_DIRECTIONAL) { // set up the shadow texture // Set ortho projection texCam->SetProjectionType(PT_ORTHOGRAPHIC); // set ortho window so that texture covers far dist texCam->SetOrthoWindow(shadowDist * 2, shadowDist * 2); // Calculate look at position // We want to look at a spot shadowOffset away from near plane // 0.5 is a litle too close for angles DiVec3 target = cam->GetDerivedPosition() + (cam->GetDerivedDirection() * shadowOffset); // Calculate direction, which same as directional light direction dir = - light->GetDerivedDirection(); // backwards since point down -z dir.normalise(); // Calculate position // We want to be in the -ve direction of the light direction // far enough to project for the dir light extrusion distance pos = target + dir * sm->GetShadowDirLightExtrusionDistance(); float worldTexelSize = (shadowDist * 2) / (vp->mWidth * vp->mParent->GetWidth()); //get texCam orientation DiVec3 up = DiVec3::UNIT_Y; // Check it's not coincident with dir if (DiMath::Abs(up.dotProduct(dir)) >= 1.0f) { // Use camera up up = DiVec3::UNIT_Z; } // cross twice to rederive, only direction is unaltered DiVec3 left = dir.crossProduct(up); left.normalise(); up = dir.crossProduct(left); up.normalise(); // Derive quaternion from axes DiQuat q; q.FromAxes(left, up, dir); //convert world space camera position into light space DiVec3 lightSpacePos = q.Inverse() * pos; //snap to nearest texel lightSpacePos.x -= fmod(lightSpacePos.x, worldTexelSize); lightSpacePos.y -= fmod(lightSpacePos.y, worldTexelSize); //convert back to world space pos = q * lightSpacePos; } else if (light->GetType() == LIGHT_SPOT) { const DiSpotLight* spot = static_cast<const DiSpotLight*>(light); // Set perspective projection texCam->SetProjectionType(PT_PERSPECTIVE); // set FOV slightly larger than the spotlight range to ensure coverage DiRadian fovy = spot->GetOuterAngle() * 1.2; // limit angle if (fovy.valueDegrees() > 175) fovy = DiDegree(175); texCam->SetFOVy(fovy); // Calculate position, which same as spotlight position pos = light->GetDerivedPosition(); // Calculate direction, which same as spotlight direction dir = - light->GetDerivedDirection(); // backwards since point down -z dir.normalise(); } else { DI_ASSERT_FAIL; } // Finally set position texCam->SetPosition(pos); DiVec3 up = DiVec3::UNIT_Y; // Check it's not coincident with dir if (DiMath::Abs(up.dotProduct(dir)) >= 1.0f) { // Use camera up up = DiVec3::UNIT_Z; } // cross twice to rederive, only direction is unaltered DiVec3 left = dir.crossProduct(up); left.normalise(); up = dir.crossProduct(left); up.normalise(); // Derive quaternion from axes DiQuat q; q.FromAxes(left, up, dir); texCam->SetOrientation(q); }
//----------------------------------------------------------------------- void DiPlane::redefine(const DiVec3& rkNormal, const DiVec3& rkPoint) { normal = rkNormal; d = -rkNormal.dotProduct(rkPoint); }