From 3b85fe29d981ee415fa13b436ff0ad598a0957fb Mon Sep 17 00:00:00 2001 From: Rbn3D Date: Tue, 6 Feb 2018 22:27:15 +0100 Subject: [PATCH 1/9] Improved behavior of lookBehind (1st person) --- CustomCameraVPlus.ini | 5 ++++- script.cpp | 10 ++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/CustomCameraVPlus.ini b/CustomCameraVPlus.ini index b3b8770..e68403e 100644 --- a/CustomCameraVPlus.ini +++ b/CustomCameraVPlus.ini @@ -13,7 +13,10 @@ lookRightAngle = 80.0 [general] -# Support Look left/right/behind from Manual Transmission mod by ikt +# Support Look left/right/behind from Manual Transmission mod by ikt (Requires latest AppVeyor build of Manual Transmission Mod) +# +# https://ci.appveyor.com/project/E66666666/gtavmanualtransmission/build/artifacts +# # Set to 1 to enable, 0 to disable GetInputFromGearsAsi = 1 diff --git a/script.cpp b/script.cpp index 74ba1b9..dfc0b1c 100644 --- a/script.cpp +++ b/script.cpp @@ -1161,6 +1161,8 @@ void lookBehind1p() boneName = "windscreen_r"; offset = (vehUpVector * 0.08f) + (-vehForwardVector * 0.08f); hasBone = true; + + goto setBonePos; } if (vehHasBone("bumper_r")) @@ -1168,6 +1170,8 @@ void lookBehind1p() boneName = "bumper_r"; offset = (vehUpVector * 0.18f) + (-vehForwardVector * 0.08f); hasBone = true; + + goto setBonePos; } if (vehHasBone("brakelight_m")) @@ -1175,6 +1179,8 @@ void lookBehind1p() boneName = "brakelight_m"; offset = (vehUpVector * 0.08f) + (-vehForwardVector * 0.08f); hasBone = true; + + goto setBonePos; } if (vehHasBone("boot")) @@ -1182,8 +1188,12 @@ void lookBehind1p() boneName = "boot"; offset = vehUpVector * 0.28f; hasBone = true; + + goto setBonePos; } + setBonePos: + if (hasBone) { if (VEHICLE::GET_VEHICLE_MOD(veh, 0) >= 0) // Has spoiler? From e6e8cd7b12aa0dffe513ece5b51370e4ce6a83d1 Mon Sep 17 00:00:00 2001 From: Rbn3D Date: Sat, 10 Feb 2018 20:51:11 +0100 Subject: [PATCH 2/9] Testing a new 3rd person camera algorithm --- script.cpp | 138 ++++++++++++++++++++++++++++++++++++++++++----------- script.h | 3 ++ 2 files changed, 113 insertions(+), 28 deletions(-) diff --git a/script.cpp b/script.cpp index dfc0b1c..fc893a6 100644 --- a/script.cpp +++ b/script.cpp @@ -36,10 +36,12 @@ float lastVelocityMagnitude; Vector3f vehForwardVector; Vector3f vehRightVector; Vector3f vehUpVector; -Vector3f vehRelativeRotation; +Vector3f vehRelativeSpeedVector; +Vector3f vehAngularVelocity; float vehAcceleration = 0.f; float smoothAccelerationFactor = 0.f; +float prevVehAcceleration = 0.f; eVehicleClass vehClass; bool vehHasTowBone = false; @@ -92,6 +94,7 @@ Quaternionf smoothQuat3P = Quaternionf(); Vector3f smoothRotSeat = Vector3f(); Quaternionf smoothQuatSeat = Quaternionf(); float smoothIsInAir = 0.f; +float smoothIsInAirNfs = 0.f; float maxHighSpeed = 130.f; float maxHighSpeedDistanceIncrement = 1.45f; float accelerationCamDistanceMultiplier = 1.45f; @@ -153,12 +156,18 @@ float LookRightAngle1p = 80.0f; float LookLeftAngle3p = 90.0f; float LookRightAngle3p = 90.0f; +float semiDelayedVehSpeed = 0.f; +float delayedVehSpeed = 0.f; + +Vector3f prevCamPos; + bool isLookingBack = false; // look left = -1.f; lookRight = 1.f; Center = 0.f (For smooth transitions) float RelativeLookFactor = 0.f; bool readInputFromMt = true; +float deccelerationSmooth = 0.f; char * reloadKey = "F10"; char * toggleModKey = "1"; @@ -319,14 +328,8 @@ Vector3 getRightVector(Vector3f rotation) return vec; } -void SET_CAM_QUATERNION(Camera c, Quaternionf q) +Vector3f QuatToEuler(Quaternionf q) { - //Matrix3f rot = q.toRotationMatrix(); - - //float ax = asinf(rot(1,0)); - //float ay = atan2f(rot(2,0), rot(2,1)); - //float az = atan2f(rot(0,0), rot(0,1)); - float r11 = -2 * (q.x() * q.y() - q.w() * q.z()); float r12 = q.w() * q.w() - q.x() * q.x() + q.y() * q.y() - q.z() * q.z(); float r21 = 2 * (q.y() * q.z() + q.w() * q.x()); @@ -342,7 +345,22 @@ void SET_CAM_QUATERNION(Camera c, Quaternionf q) ay *= f; az *= f; - CAM::SET_CAM_ROT(c, ax, ay, az, 2); + Vector3f ret = Vector3f(ax, ay, az); + + return ret; +} + +void SET_CAM_QUATERNION(Camera c, Quaternionf q) +{ + //Matrix3f rot = q.toRotationMatrix(); + + //float ax = asinf(rot(1,0)); + //float ay = atan2f(rot(2,0), rot(2,1)); + //float az = atan2f(rot(0,0), rot(0,1)); + + Vector3f ret = QuatToEuler(q); + + CAM::SET_CAM_ROT(c, ret.x(), ret.y(), ret.z(), 2); } Vector3f toV3f(const Vector3 &vec) { @@ -369,19 +387,25 @@ float DegToRad(const float °) return float(deg * M_PI / 180.0); } -Quaternionf GET_CAM_QUATERNION(Camera c) +Quaternionf QuatEuler(Vector3f &camVec) { - Vector3f rotVec = DegToRad(1.0f)*toV3f(CAM::GET_CAM_ROT(c, 0)); + Vector3f rotVec = DegToRad(1.0f) * camVec; Matrix3f xRot = AngleAxisf(rotVec.x(), Vector3f(1.0f, 0.0f, 0.0f)).matrix(); Matrix3f yRot = AngleAxisf(rotVec.y(), Vector3f(0.0f, 1.0f, 0.0f)).matrix(); Matrix3f zRot = AngleAxisf(rotVec.z(), Vector3f(0.0f, 0.0f, 1.0f)).matrix(); - Matrix3f rot = zRot*yRot*xRot; + Matrix3f rot = zRot * yRot*xRot; return Quaternionf(rot); } +Quaternionf GET_CAM_QUATERNION(Camera c) +{ + Vector3f camVec = toV3f(CAM::GET_CAM_ROT(c, 0)); + return QuatEuler(camVec); +} + Vector2i getMouseCoords() { int mX = CONTROLS::GET_CONTROL_VALUE(0, 239) - 127 / 127.f * 1280; int mY = CONTROLS::GET_CONTROL_VALUE(0, 240) - 127 / 127.f * 720; @@ -771,6 +795,11 @@ Quaternionf slerp(Quaternionf& q1, Quaternionf& q2, float time) return q1.slerp(time, q2); } +Quaternionf nlerp(Quaternionf& q1, Quaternionf& q2, float time) +{ + return QuatEuler(lerp(QuatToEuler(q1), QuatToEuler(q2), time)); +} + //Quaternionf lerp(float t, const Quaternionf& a, const Quaternionf& b) //{ // return a.slerp(t, b); @@ -945,14 +974,16 @@ void updateVehicleVars() vehPos = toV3f(ENTITY::GET_ENTITY_COORDS(veh, true)); vehRot = toV3f(ENTITY::GET_ENTITY_ROTATION(veh, 2)); vehVelocity = toV3f(ENTITY::GET_ENTITY_VELOCITY(veh)); + vehForwardVector = toV3f(ENTITY::GET_ENTITY_FORWARD_VECTOR(veh)); vehSpeed = ENTITY::GET_ENTITY_SPEED(veh); - smoothVelocity = lerp(smoothVelocity, vehVelocity, 10.f * getDeltaTime()); + smoothVelocity = lerp(smoothVelocity, vehSpeed > 2.f ? vehVelocity : vehForwardVector, 10.f * getDeltaTime()); smoothIsInAir = lerp(smoothIsInAir, (ENTITY::IS_ENTITY_IN_AIR(veh) || ENTITY::IS_ENTITY_UPSIDEDOWN(veh)) ? 1.f : 0.f, 2.f * getDeltaTime()); - vehForwardVector = toV3f(ENTITY::GET_ENTITY_FORWARD_VECTOR(veh)); + smoothIsInAirNfs = lerp(smoothIsInAirNfs, (ENTITY::IS_ENTITY_IN_AIR(veh)) ? 1.f : 0.f, 0.75f * getDeltaTime()); vehRightVector = toV3f(getRightVector(vehRot)); vehUpVector = vehRightVector.cross(vehForwardVector); vehAcceleration = getVehicleAcceleration(); - vehRelativeRotation = toV3f(ENTITY::GET_ENTITY_SPEED_VECTOR(veh, true)); + vehRelativeSpeedVector = toV3f(ENTITY::GET_ENTITY_SPEED_VECTOR(veh, true)); + vehAngularVelocity = toV3f(ENTITY::GET_ENTITY_ROTATION_VELOCITY(veh)); } void setupCurrentCamera() { @@ -1237,7 +1268,8 @@ Vector3f GetBonePos(Entity entity, char * boneName) return toV3f(ENTITY::GET_WORLD_POSITION_OF_ENTITY_BONE(veh, ENTITY::GET_ENTITY_BONE_INDEX_BY_NAME(entity, boneName))); } -void updateCameraSmooth3P() { +void updateCam3pSmoothAlgorithm() +{ Vector3f extraCamHeight = up * (0.14f + extraAngleCamHeight); Vector3f posCenter = vehPos + (up * heightOffset3P); @@ -1245,7 +1277,7 @@ void updateCameraSmooth3P() { if (useVariableRotSpeed3P) { float lerpFactor = min(1.f, easeOutCubic(vehSpeed / (maxHighSpeed * 0.5f))); - float rotFactor = abs(vehRelativeRotation.x()) * 2.75f; + float rotFactor = abs(vehRelativeSpeedVector.x()) * 2.75f; lerpFactor -= rotFactor; @@ -1259,13 +1291,13 @@ void updateCameraSmooth3P() { if (speedFactor >= 0.00001f) velocityQuat3P = /*lookRotation(smoothVelocity);*/ slerp(velocityQuat3P, lookRotation(smoothVelocity), 4.f * getDeltaTime()); else if (vehSpeed >= 0.00001f) // fix instant cam rotation when rollovers/sudden rotation changes and speeds goes below 5.0f (if speedFactor < 0.00001f) - velocityQuat3P = slerp(velocityQuat3P, lookRotation(smoothVelocity), 0.2f * getDeltaTime()); + velocityQuat3P = slerp(velocityQuat3P, lookRotation(smoothVelocity), 0.2f * getDeltaTime()); smoothSpeedFactor = lerp(smoothSpeedFactor, speedFactor, clamp(6.f * getDeltaTime(), 0.f, 0.1f)); velocityQuat3P = slerp(vehQuat, velocityQuat3P, smoothSpeedFactor); - if (isBike && vehSpeed >= 3.f) + if (isBike && vehSpeed >= 3.f) smoothQuat3P = slerp(smoothQuat3P, velocityQuat3P, currentRotSpeed3P * getDeltaTime()); else smoothQuat3P = slerp(smoothQuat3P, vehQuat, currentRotSpeed3P * getDeltaTime()); @@ -1333,7 +1365,7 @@ void updateCameraSmooth3P() { Vector3f relativeLookDir = back; - if(lookBehind) { + if (lookBehind) { relativeLookDir = front; finalDistMult *= -1.f; } @@ -1347,7 +1379,7 @@ void updateCameraSmooth3P() { Vector3f camPos = posCenter + extraCamHeight + V3CurrentTowHeightIncrement + (finalQuat * relativeLookDir * (longitudeOffset3P + (currentDistanceIncrement * finalDistMult) + currentTowLongitudeIncrement)); Vector3f offsetLatPoint = Vector3f(0.f, 0.f, 0.f); - Vector3f offsetLatPointFront = Vector3f(0.f,0.f,0.f); + Vector3f offsetLatPointFront = Vector3f(0.f, 0.f, 0.f); Vector3f camForward = getCameraForwardVector(customCam).normalized(); @@ -1367,13 +1399,13 @@ void updateCameraSmooth3P() { angle = lerp(0.f, maxAngle + 2.f, easeInCubic(unlerp(0.f, maxAngle, angle))); // apply easing angleFront = lerp(0.f, maxAngle + 2.f, unlerp(0.f, maxAngle, angleFront)); // apply easing - if (distanceOnAxisNoAbs(camPos, vehPos, latVector) < 0.f) + if (distanceOnAxisNoAbs(camPos, vehPos, latVector) < 0.f) { angle = -angle; relAngle3p = -relAngle3p; angleFront = -angleFront; } - + if (!lookBehind /* && !isBike */) { angle = angle * 0.003f; @@ -1386,7 +1418,7 @@ void updateCameraSmooth3P() { //if (isBike) // setCamPos(customCam, camPos); //else - setCamPos(customCam, camPos + (offsetLatPointFront * 1.455f)); + setCamPos(customCam, camPos + (offsetLatPointFront * 1.455f)); //if (smoothIsMouseLooking > 0.001f) { // Vector3f camPos = lerp(camPos, getGameplayCameraPos(), smoothIsMouseLooking); @@ -1397,9 +1429,9 @@ void updateCameraSmooth3P() { int ray = WORLDPROBE::_START_SHAPE_TEST_RAY(finalPosCenter.x(), finalPosCenter.y(), finalPosCenter.z(), camPos.x(), camPos.y(), camPos.z(), 1, veh, 7); - Vector3 endCoords, surfaceNormal; - BOOL hit; - Entity entityHit = 0; + Vector3 endCoords, surfaceNormal; + BOOL hit; + Entity entityHit = 0; WORLDPROBE::GET_SHAPE_TEST_RESULT(ray, &hit, &endCoords, &surfaceNormal, &entityHit); @@ -1410,7 +1442,57 @@ void updateCameraSmooth3P() { //if(isBike) // camPointAt(customCam, finalPosCenter + (-up * .170f)); //else - camPointAt(customCam, finalPosCenter + (-up * .170f) + (offsetLatPointFront * -1.4825f)); + camPointAt(customCam, finalPosCenter + (-up * .170f) + (offsetLatPointFront * -1.4825f)); +} + +void updateCam3pNfsAlgorithm() +{ + Vector3f extraCamHeight = up * (0.14f + extraAngleCamHeight); + Vector3f posCenter = vehPos + (up * heightOffset3P); + + semiDelayedVehSpeed = lerp(semiDelayedVehSpeed, vehSpeed, clamp01(max(2.5f, vehSpeed) * getDeltaTime())); + delayedVehSpeed = lerp(delayedVehSpeed, semiDelayedVehSpeed, clamp01(max(0.5f, semiDelayedVehSpeed * 0.75f) * getDeltaTime())); + + Quaternionf vehQuat = getEntityQuaternion(veh); + smoothQuat3P = slerp(smoothQuat3P, vehQuat, 3.f * getDeltaTime()); + + currentTowHeightIncrement = lerp(currentTowHeightIncrement, towHeightIncrement, 1.45f * getDeltaTime()); + currentTowLongitudeIncrement = lerp(currentTowLongitudeIncrement, towLongitudeIncrement, 1.75f * getDeltaTime()); + + Vector3f V3CurrentTowHeightIncrement = up * currentTowHeightIncrement; + + deccelerationSmooth = lerp(deccelerationSmooth, clamp(vehAcceleration * 65.f, -9999.f, 0.f), 1.25f * getDeltaTime()); + + float distInc = clamp(semiDelayedVehSpeed * 0.035f * (vehVelocity.normalized().dot(vehForwardVector) * clamp01(vehSpeed + 0.05f)), -5.f, 5.f); + float discIncAir = clamp(semiDelayedVehSpeed * 0.035f * clamp01(vehSpeed + 0.05f), -5.f, 5.f); + + float distIncFinal = lerp(distInc, discIncAir, smoothIsInAir); + + distIncFinal += deccelerationSmooth * (1.f - smoothIsInAir); + + float airDistance = lerp(0.f, 2.5f, smoothIsInAirNfs * ENTITY::IS_ENTITY_IN_AIR(veh) ? 0.6f : 1.2f); + + velocityQuat3P = lookRotation(smoothVelocity); + Quaternionf finalQuat3P = slerp(smoothQuat3P, velocityQuat3P, smoothIsInAir); + + Vector3f camPosSmooth = posCenter + extraCamHeight + V3CurrentTowHeightIncrement + (finalQuat3P * back * (longitudeOffset3P + distIncFinal + airDistance)); + Vector3f camPosFinal = camPosSmooth; + + Vector3f lookAt = posCenter + finalQuat3P * front * (longitudeOffset3P); + + setCamPos(customCam, camPosFinal); + //camPointAt(customCam, lookAt); + + Vector3f rotEuler = QuatToEuler(finalQuat3P); + + rotEuler[1] = 0.f; + + CAM::SET_CAM_ROT(customCam, rotEuler.x(), rotEuler.y(), rotEuler.z(), 2); +} + +void updateCameraSmooth3P() { + //UpdateCam3pSmoothAlgorithm(); + updateCam3pNfsAlgorithm(); } void updateCustomCamera() diff --git a/script.h b/script.h index 47ca305..6488fe9 100644 --- a/script.h +++ b/script.h @@ -50,6 +50,8 @@ BOOL GetDecoratorBool(char * decoratorKey); Vector3f GetBonePos(Entity entity, char * boneName); +void updateCam3pSmoothAlgorithm(); + void updateVehicleProperties(); void setupCurrentCamera(); @@ -482,3 +484,4 @@ const char* const vehicleBones[] = "neon_b" }; +Quaternionf QuatEuler(Eigen::Vector3f &camVec); From 06a1b6329a07c291bbb6b81357607ba32a8b2f62 Mon Sep 17 00:00:00 2001 From: Rbn_3D Date: Wed, 7 Mar 2018 16:18:33 +0100 Subject: [PATCH 3/9] Minor update --- CustomCameraVPlus.vcxproj | 75 +++++++++++++++++++++++++++++++++++++++ script.cpp | 49 ++----------------------- 2 files changed, 77 insertions(+), 47 deletions(-) create mode 100644 CustomCameraVPlus.vcxproj diff --git a/CustomCameraVPlus.vcxproj b/CustomCameraVPlus.vcxproj new file mode 100644 index 0000000..3dfccea --- /dev/null +++ b/CustomCameraVPlus.vcxproj @@ -0,0 +1,75 @@ + + + + + Release + x64 + + + + + + + + + + + + + + + + + {8D82F34A-1D64-465B-84B1-37F89AD3D20B} + Win32Proj + CustomCameraVPlus + CustomCameraVPlus + + + + DynamicLibrary + false + v141 + true + MultiByte + + + + + + + + + + false + .asi + bin\$(Configuration)\ + tmp\$(Configuration)\ + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;NativeSpeedo_EXPORTS;%(PreprocessorDefinitions) + MultiThreaded + Fast + + + Windows + false + true + true + ..\..\lib\ScriptHookV.lib %(AdditionalOptions) + + + copy "$(TargetPath)" "E:\SteamLibrary\steamapps\common\Grand Theft Auto V\$(ProjectName).asi" + + + + + + \ No newline at end of file diff --git a/script.cpp b/script.cpp index fc893a6..a00c513 100644 --- a/script.cpp +++ b/script.cpp @@ -750,48 +750,8 @@ Vector3f Vector3fInertialDampAngle(Vector3f& v1, Vector3f& v2, float t) InertialDampAngle(v1.z(), v2.z(), t)); } -//Quaternionf QuatScalarMultiply(Quaternionf& input, float scalar) -//{ -// return Quaternionf(input.x()/* * scalar*/, input.y()/* * scalar*/, input.z()/* * scalar*/, input.w() * scalar); -//} -// -//Quaternionf QuatAdd(Quaternionf& p, Quaternionf& q) -//{ -// return Quaternionf(p.x() + q.x(), p.y() + q.y(), p.z() + q.z(), p.w() + q.w()); -//} -// -//float reciprocal(float f) { -// return 1.0 / f; -//} -// -//Quaternionf lerp(Quaternionf q1, Quaternionf q2, float time) -//{ -// const float scale = 1.0f - time; -// return QuatAdd(QuatScalarMultiply(q1, scale), QuatScalarMultiply(q2, time)); -//} - Quaternionf slerp(Quaternionf& q1, Quaternionf& q2, float time) { - //float angle = q1.dot(q2); - - //// make sure we use the short rotation - ////if (angle < 0.0f) - ////{ - //// q1 = QuatScalarMultiply(q1, -1.0f); - //// angle *= -1.0f; - ////} - - //if (angle <= (1 - threshold)) // spherical interpolation - //{ - // const float theta = acosf(angle); - // const float invsintheta = reciprocal(sinf(theta)); - // const float scale = sinf(theta * (1.0f - time)) * invsintheta; - // const float invscale = sinf(theta * time) * invsintheta; - // return QuatAdd(QuatScalarMultiply(q1, scale), QuatScalarMultiply(q2, invscale)); - //} - //else // linear interpolation - // return lerp(q1, q2, time); - return q1.slerp(time, q2); } @@ -800,11 +760,6 @@ Quaternionf nlerp(Quaternionf& q1, Quaternionf& q2, float time) return QuatEuler(lerp(QuatToEuler(q1), QuatToEuler(q2), time)); } -//Quaternionf lerp(float t, const Quaternionf& a, const Quaternionf& b) -//{ -// return a.slerp(t, b); -//} - float smoothStep(float from, float to, float t) { t = clamp01(t); @@ -1491,8 +1446,8 @@ void updateCam3pNfsAlgorithm() } void updateCameraSmooth3P() { - //UpdateCam3pSmoothAlgorithm(); - updateCam3pNfsAlgorithm(); + updateCam3pSmoothAlgorithm(); + //updateCam3pNfsAlgorithm(); } void updateCustomCamera() From 9e9a14a2537d41dbcdc5308df909683aa2d98806 Mon Sep 17 00:00:00 2001 From: Rbn_3D Date: Sun, 11 Mar 2018 13:19:01 +0100 Subject: [PATCH 4/9] Progress in alternative camera version --- script.cpp | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/script.cpp b/script.cpp index a00c513..3efbee3 100644 --- a/script.cpp +++ b/script.cpp @@ -180,7 +180,8 @@ bool AreSameFloat(float a, float b) } float getDeltaTime() { - return SYSTEM::TIMESTEP(); + //return SYSTEM::TIMESTEP(); + return GAMEPLAY::GET_FRAME_TIME(); } std::string SubstringOfCString(const char *cstr, @@ -1397,13 +1398,17 @@ void updateCam3pSmoothAlgorithm() //if(isBike) // camPointAt(customCam, finalPosCenter + (-up * .170f)); //else - camPointAt(customCam, finalPosCenter + (-up * .170f) + (offsetLatPointFront * -1.4825f)); + Vector3f rotEuler = QuatToEuler(finalQuat); + + rotEuler[1] = 0.f; + + CAM::SET_CAM_ROT(customCam, rotEuler.x(), rotEuler.y(), rotEuler.z(), 2); } void updateCam3pNfsAlgorithm() { Vector3f extraCamHeight = up * (0.14f + extraAngleCamHeight); - Vector3f posCenter = vehPos + (up * heightOffset3P); + Vector3f posCenter = vehPos + (up * heightOffset3P) + (vehForwardVector * 0.4f); semiDelayedVehSpeed = lerp(semiDelayedVehSpeed, vehSpeed, clamp01(max(2.5f, vehSpeed) * getDeltaTime())); delayedVehSpeed = lerp(delayedVehSpeed, semiDelayedVehSpeed, clamp01(max(0.5f, semiDelayedVehSpeed * 0.75f) * getDeltaTime())); @@ -1425,12 +1430,12 @@ void updateCam3pNfsAlgorithm() distIncFinal += deccelerationSmooth * (1.f - smoothIsInAir); - float airDistance = lerp(0.f, 2.5f, smoothIsInAirNfs * ENTITY::IS_ENTITY_IN_AIR(veh) ? 0.6f : 1.2f); + float airDistance = lerp(0.f, 2.5f, smoothIsInAirNfs * (lerp(0.6f, 1.2f, smoothIsInAirNfs))); velocityQuat3P = lookRotation(smoothVelocity); Quaternionf finalQuat3P = slerp(smoothQuat3P, velocityQuat3P, smoothIsInAir); - Vector3f camPosSmooth = posCenter + extraCamHeight + V3CurrentTowHeightIncrement + (finalQuat3P * back * (longitudeOffset3P + distIncFinal + airDistance)); + Vector3f camPosSmooth = posCenter + extraCamHeight + V3CurrentTowHeightIncrement + (finalQuat3P * back * ((longitudeOffset3P) + distIncFinal + airDistance)); Vector3f camPosFinal = camPosSmooth; Vector3f lookAt = posCenter + finalQuat3P * front * (longitudeOffset3P); @@ -1446,8 +1451,8 @@ void updateCam3pNfsAlgorithm() } void updateCameraSmooth3P() { - updateCam3pSmoothAlgorithm(); - //updateCam3pNfsAlgorithm(); + //updateCam3pSmoothAlgorithm(); + updateCam3pNfsAlgorithm(); } void updateCustomCamera() @@ -1796,7 +1801,9 @@ void update() if (IsKeyJustUp(str2key(reloadKey))) { //showDebug = !showDebug; // TODO Comment this line out before release! + haltCurrentCamera(); ReadSettings(true); + setupCurrentCamera(); } updateTimers(); From a0e08f67baf9b03edaa518e2a5d7d094e31536e5 Mon Sep 17 00:00:00 2001 From: Rbn_3D Date: Tue, 13 Mar 2018 18:48:11 +0100 Subject: [PATCH 5/9] Look with gamepad support (horizontal rotation, like most racing games) --- script.cpp | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 96 insertions(+), 4 deletions(-) diff --git a/script.cpp b/script.cpp index 3efbee3..fae352c 100644 --- a/script.cpp +++ b/script.cpp @@ -174,6 +174,9 @@ char * toggleModKey = "1"; char * lookLeftKey = "B"; char * lookRightKey = "N"; +bool hasGamepadInputThisFrame = false; +bool hasMouseInputThisFrame = false; + bool AreSameFloat(float a, float b) { return fabs(a - b) < FLT_EPSILON; @@ -427,11 +430,27 @@ void updateMouseState() { if (isAiming || movX >= 1 || movY >= 1) { // Mouse moved on last frame + hasMouseInputThisFrame = true; + if (isInVehicle && customCamEnabled && mouseMoveCountdown <= 0.0001f && smoothIsMouseLooking <= 0.001f) setGameplayCamRelativeRotation(relAngle3p); // Sync gameplay cam rotarion mouseMoveCountdown = 1.5f; } + else + hasMouseInputThisFrame = false; + + if ( + CONTROLS::IS_CONTROL_PRESSED(2, eControl::ControlLookUpOnly) || + CONTROLS::IS_CONTROL_PRESSED(2, eControl::ControlLookLeftOnly) || + CONTROLS::IS_CONTROL_PRESSED(2, eControl::ControlLookRightOnly) || + CONTROLS::IS_CONTROL_PRESSED(2, eControl::ControlLookDownOnly) + ) + { + hasGamepadInputThisFrame = true; + } + else + hasGamepadInputThisFrame = false; if((veh != NULL && (vehSpeed > 0.1)) || veh == NULL) mouseMoveCountdown = max(0.f, mouseMoveCountdown - (SYSTEM::TIMESTEP() * clamp01(vehSpeed * 0.08f))); @@ -933,6 +952,13 @@ void updateVehicleVars() vehForwardVector = toV3f(ENTITY::GET_ENTITY_FORWARD_VECTOR(veh)); vehSpeed = ENTITY::GET_ENTITY_SPEED(veh); smoothVelocity = lerp(smoothVelocity, vehSpeed > 2.f ? vehVelocity : vehForwardVector, 10.f * getDeltaTime()); + + if ((ENTITY::IS_ENTITY_IN_AIR(veh) || (ENTITY::GET_ENTITY_UPRIGHT_VALUE(veh) < 0.6f)) && smoothIsInAir < 0.001f) + { + smoothVelocity = getCameraForwardVector(customCam); + velocityQuat3P = lookRotation(smoothVelocity); + } + smoothIsInAir = lerp(smoothIsInAir, (ENTITY::IS_ENTITY_IN_AIR(veh) || ENTITY::IS_ENTITY_UPSIDEDOWN(veh)) ? 1.f : 0.f, 2.f * getDeltaTime()); smoothIsInAirNfs = lerp(smoothIsInAirNfs, (ENTITY::IS_ENTITY_IN_AIR(veh)) ? 1.f : 0.f, 0.75f * getDeltaTime()); vehRightVector = toV3f(getRightVector(vehRot)); @@ -1408,7 +1434,7 @@ void updateCam3pSmoothAlgorithm() void updateCam3pNfsAlgorithm() { Vector3f extraCamHeight = up * (0.14f + extraAngleCamHeight); - Vector3f posCenter = vehPos + (up * heightOffset3P) + (vehForwardVector * 0.4f); + Vector3f posCenter = vehPos + (up * heightOffset3P) + (vehForwardVector * 0.365f); semiDelayedVehSpeed = lerp(semiDelayedVehSpeed, vehSpeed, clamp01(max(2.5f, vehSpeed) * getDeltaTime())); delayedVehSpeed = lerp(delayedVehSpeed, semiDelayedVehSpeed, clamp01(max(0.5f, semiDelayedVehSpeed * 0.75f) * getDeltaTime())); @@ -1433,9 +1459,66 @@ void updateCam3pNfsAlgorithm() float airDistance = lerp(0.f, 2.5f, smoothIsInAirNfs * (lerp(0.6f, 1.2f, smoothIsInAirNfs))); velocityQuat3P = lookRotation(smoothVelocity); - Quaternionf finalQuat3P = slerp(smoothQuat3P, velocityQuat3P, smoothIsInAir); - Vector3f camPosSmooth = posCenter + extraCamHeight + V3CurrentTowHeightIncrement + (finalQuat3P * back * ((longitudeOffset3P) + distIncFinal + airDistance)); + bool lookBehind = false; + if (CONTROLS::IS_CONTROL_PRESSED(0, eControl::ControlLookBehind) || isLookingBack) + lookBehind = true; + + float lookHorizontalAngle = 0.f; + if (!lookBehind) { + lookHorizontalAngle = RelativeLookFactor < 0 ? + lerp(0.f, -LookLeftAngle3p, -RelativeLookFactor) + : + lerp(0.f, LookRightAngle3p, RelativeLookFactor) + ; + } + else + { + lookHorizontalAngle = 180.f; + } + + if (hasGamepadInputThisFrame && AreSameFloat(lookHorizontalAngle, 0.f)) + { + //float leftNormal = CONTROLS::GET_CONTROL_NORMAL(2, eControl::ControlLookLeftOnly); + float rightNormal = CONTROLS::GET_CONTROL_NORMAL(2, eControl::ControlLookRight); + float upNormal = CONTROLS::GET_CONTROL_NORMAL(2, eControl::ControlLookUp); + //float downNormal = CONTROLS::GET_CONTROL_NORMAL(2, eControl::ControlLookDownOnly); + + float x = rightNormal;// - leftNormal; + float y = upNormal;// - downNormal; + + float r = sqrt(x * x + y * y); + float maxComp = max(abs(x), abs(y)); + if (maxComp > 0) { + x *= r / maxComp; + y *= r / maxComp; + } + + float degress = atan2(y, x) * 180.f / PI; + + lookHorizontalAngle = degress - 90.f; + } + + + float leftRightRad = lookHorizontalAngle * DEG_TO_RAD; + + float roll = 0.f, pitch = 0.f, yaw = leftRightRad; + Quaternionf qLookLeftRight; + qLookLeftRight = AngleAxisf(roll, Vector3f::UnitX()) + * AngleAxisf(pitch, Vector3f::UnitY()) + * AngleAxisf(yaw, Vector3f::UnitZ()); + + float btnLookingFactor = (abs(RelativeLookFactor)); + + if (lookBehind) + btnLookingFactor = 1.f; + + Quaternionf finalQuat3P = slerp(smoothQuat3P * qLookLeftRight, velocityQuat3P, smoothIsInAir); + + Vector3f camPosSmooth = posCenter + extraCamHeight + V3CurrentTowHeightIncrement + (finalQuat3P * back * ((longitudeOffset3P) + 0.15f + airDistance)); + + camPosSmooth += slerp(smoothQuat3P, velocityQuat3P, smoothIsInAir) * back * distIncFinal; + Vector3f camPosFinal = camPosSmooth; Vector3f lookAt = posCenter + finalQuat3P * front * (longitudeOffset3P); @@ -1443,6 +1526,7 @@ void updateCam3pNfsAlgorithm() setCamPos(customCam, camPosFinal); //camPointAt(customCam, lookAt); + Vector3f rotEuler = QuatToEuler(finalQuat3P); rotEuler[1] = 0.f; @@ -1484,6 +1568,7 @@ void DisableCustomCamera() CAM::RENDER_SCRIPT_CAMS(false, false, 3000, true, false); camInitialized = false; isInVehicle = false; + veh = NULL; haltCurrentCamera(); } @@ -1800,9 +1885,16 @@ void update() } if (IsKeyJustUp(str2key(reloadKey))) { - //showDebug = !showDebug; // TODO Comment this line out before release! + haltCurrentCamera(); + + updateVehicleVars(); + updateVehicleProperties(); + + setupCustomCamera(); + ReadSettings(true); + setupCurrentCamera(); } From e700106d6f69fe2f4697ab7f42ffcc3d75e96100 Mon Sep 17 00:00:00 2001 From: Rbn_3D Date: Thu, 15 Mar 2018 17:32:05 +0100 Subject: [PATCH 6/9] Mouse / Gamepad look around better implementation --- CustomCameraVPlus.vcxproj | 1 + script.cpp | 144 +++++++++++++++++++++++++++----------- script.h | 3 +- 3 files changed, 105 insertions(+), 43 deletions(-) diff --git a/CustomCameraVPlus.vcxproj b/CustomCameraVPlus.vcxproj index 3dfccea..91c41cc 100644 --- a/CustomCameraVPlus.vcxproj +++ b/CustomCameraVPlus.vcxproj @@ -64,6 +64,7 @@ true true ..\..\lib\ScriptHookV.lib %(AdditionalOptions) + E:\Trabajo\Dev\ScriptHookV_SDK_1.0.617.1a\inc\gainput\build\lib\Debug\gainput-d.lib;xinput.lib;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.16299.0\um\x64\WS2_32.lib;%(AdditionalDependencies) copy "$(TargetPath)" "E:\SteamLibrary\steamapps\common\Grand Theft Auto V\$(ProjectName).asi" diff --git a/script.cpp b/script.cpp index fae352c..2e70495 100644 --- a/script.cpp +++ b/script.cpp @@ -17,6 +17,8 @@ using namespace NativeMenu; +HWND hWnd; + float smoothIsMouseLooking = 0.f; float viewLock = 0.f; float smoothViewLock = 0.f; @@ -91,6 +93,7 @@ Vector3f smoothSurfaceNormal; Vector3f smoothVelocity = Vector3f(); Quaternionf velocityQuat3P = Quaternionf(); Quaternionf smoothQuat3P = Quaternionf(); +Quaternionf ultraSmoothQuat3P = Quaternionf(); Vector3f smoothRotSeat = Vector3f(); Quaternionf smoothQuatSeat = Quaternionf(); float smoothIsInAir = 0.f; @@ -163,6 +166,13 @@ Vector3f prevCamPos; bool isLookingBack = false; +float timerResetLook = 0.f; +Quaternionf lookQuat; + +float mouseDeltaX = 0.f; +float mouseDeltaY = 0.f; + + // look left = -1.f; lookRight = 1.f; Center = 0.f (For smooth transitions) float RelativeLookFactor = 0.f; @@ -174,7 +184,7 @@ char * toggleModKey = "1"; char * lookLeftKey = "B"; char * lookRightKey = "N"; -bool hasGamepadInputThisFrame = false; +bool hasInputThisFrame = false; bool hasMouseInputThisFrame = false; bool AreSameFloat(float a, float b) @@ -428,6 +438,9 @@ void updateMouseState() { int movX = abs(lastX - currX); int movY = abs(lastY - currY); + mouseDeltaX = currX - lastX; + mouseDeltaY = currY - lastY; + if (isAiming || movX >= 1 || movY >= 1) { // Mouse moved on last frame hasMouseInputThisFrame = true; @@ -440,17 +453,19 @@ void updateMouseState() { else hasMouseInputThisFrame = false; + float x = CONTROLS::GET_CONTROL_NORMAL(2, eControl::ControlLookLeftRight); + float y = CONTROLS::GET_CONTROL_NORMAL(2, eControl::ControlLookUpDown); + if ( - CONTROLS::IS_CONTROL_PRESSED(2, eControl::ControlLookUpOnly) || - CONTROLS::IS_CONTROL_PRESSED(2, eControl::ControlLookLeftOnly) || - CONTROLS::IS_CONTROL_PRESSED(2, eControl::ControlLookRightOnly) || - CONTROLS::IS_CONTROL_PRESSED(2, eControl::ControlLookDownOnly) + (fabs(x) > 0.005f) + || + (fabs(y) > 0.005f) ) { - hasGamepadInputThisFrame = true; + hasInputThisFrame = true; } else - hasGamepadInputThisFrame = false; + hasInputThisFrame = false; if((veh != NULL && (vehSpeed > 0.1)) || veh == NULL) mouseMoveCountdown = max(0.f, mouseMoveCountdown - (SYSTEM::TIMESTEP() * clamp01(vehSpeed * 0.08f))); @@ -554,7 +569,7 @@ void ReadSettings(bool notify) ShowNotification("CCVPlus: Cannot load settings! Missing ini file?"); } -/* + // showText() taken from https://github.com/E66666666/GTAVManualTransmission/ void showText(float x, float y, float scale, const char* text, int font, const Color &rgba, bool outline) { UI::SET_TEXT_FONT(font); @@ -567,7 +582,7 @@ void showText(float x, float y, float scale, const char* text, int font, const C UI::ADD_TEXT_COMPONENT_SUBSTRING_PLAYER_NAME(CharAdapter(text)); UI::END_TEXT_COMMAND_DISPLAY_TEXT(x, y); } -*/ + Vector3f getDimensions(Hash modelHash) { Vector3 min; @@ -607,6 +622,13 @@ void firstInit() address = address + *reinterpret_cast(address) + 4; gamePlayCameraAddr = *reinterpret_cast(*reinterpret_cast(address + 3) + address + 7); + hWnd = FindWindow(NULL, "Grand Theft Auto V"); + + enum Button + { + ButtonConfirm + }; + ReadSettings(false); } @@ -1431,6 +1453,11 @@ void updateCam3pSmoothAlgorithm() CAM::SET_CAM_ROT(customCam, rotEuler.x(), rotEuler.y(), rotEuler.z(), 2); } +bool LastInputMethodWasMouseAndKeyboard() +{ + return CONTROLS::_IS_INPUT_DISABLED(2); +} + void updateCam3pNfsAlgorithm() { Vector3f extraCamHeight = up * (0.14f + extraAngleCamHeight); @@ -1441,6 +1468,21 @@ void updateCam3pNfsAlgorithm() Quaternionf vehQuat = getEntityQuaternion(veh); smoothQuat3P = slerp(smoothQuat3P, vehQuat, 3.f * getDeltaTime()); + ultraSmoothQuat3P = slerp(ultraSmoothQuat3P, vehQuat, 1.8f * getDeltaTime()); + velocityQuat3P = lookRotation(smoothVelocity); + + if (isBike && vehSpeed > 1.f) + { + Vector3f smoothEuler = QuatToEuler(ultraSmoothQuat3P); + + Vector3f latv = vehRightVector.cross(smoothVelocity); + latv[1] = 0.f; + latv.normalize(); + + smoothEuler[0] = latv[0]; + + smoothQuat3P = QuatEuler(smoothEuler); + } currentTowHeightIncrement = lerp(currentTowHeightIncrement, towHeightIncrement, 1.45f * getDeltaTime()); currentTowLongitudeIncrement = lerp(currentTowLongitudeIncrement, towLongitudeIncrement, 1.75f * getDeltaTime()); @@ -1458,8 +1500,6 @@ void updateCam3pNfsAlgorithm() float airDistance = lerp(0.f, 2.5f, smoothIsInAirNfs * (lerp(0.6f, 1.2f, smoothIsInAirNfs))); - velocityQuat3P = lookRotation(smoothVelocity); - bool lookBehind = false; if (CONTROLS::IS_CONTROL_PRESSED(0, eControl::ControlLookBehind) || isLookingBack) lookBehind = true; @@ -1477,28 +1517,27 @@ void updateCam3pNfsAlgorithm() lookHorizontalAngle = 180.f; } - if (hasGamepadInputThisFrame && AreSameFloat(lookHorizontalAngle, 0.f)) - { - //float leftNormal = CONTROLS::GET_CONTROL_NORMAL(2, eControl::ControlLookLeftOnly); - float rightNormal = CONTROLS::GET_CONTROL_NORMAL(2, eControl::ControlLookRight); - float upNormal = CONTROLS::GET_CONTROL_NORMAL(2, eControl::ControlLookUp); - //float downNormal = CONTROLS::GET_CONTROL_NORMAL(2, eControl::ControlLookDownOnly); - - float x = rightNormal;// - leftNormal; - float y = upNormal;// - downNormal; - - float r = sqrt(x * x + y * y); - float maxComp = max(abs(x), abs(y)); - if (maxComp > 0) { - x *= r / maxComp; - y *= r / maxComp; - } + //if (!isAiming && hasInputThisFrame && AreSameFloat(lookHorizontalAngle, 0.f)) + //{ + // //float leftNormal = CONTROLS::GET_CONTROL_NORMAL(2, eControl::ControlLookLeftOnly); + // float rightNormal = CONTROLS::GET_CONTROL_NORMAL(2, eControl::ControlLookLeft); + // float upNormal = CONTROLS::GET_CONTROL_NORMAL(2, eControl::ControlLookDown); + // //float downNormal = CONTROLS::GET_CONTROL_NORMAL(2, eControl::ControlLookDownOnly); - float degress = atan2(y, x) * 180.f / PI; + // float x = rightNormal;// - leftNormal; + // float y = upNormal;// - downNormal; - lookHorizontalAngle = degress - 90.f; - } + // float r = sqrt(x * x + y * y); + // float maxComp = max(abs(x), abs(y)); + // if (maxComp > 0) { + // x *= r / maxComp; + // y *= r / maxComp; + // } + // float degress = atan2(y, x) * 180.f / PI; + + // lookHorizontalAngle = degress - 90.f; + //} float leftRightRad = lookHorizontalAngle * DEG_TO_RAD; @@ -1515,17 +1554,44 @@ void updateCam3pNfsAlgorithm() Quaternionf finalQuat3P = slerp(smoothQuat3P * qLookLeftRight, velocityQuat3P, smoothIsInAir); - Vector3f camPosSmooth = posCenter + extraCamHeight + V3CurrentTowHeightIncrement + (finalQuat3P * back * ((longitudeOffset3P) + 0.15f + airDistance)); + if (isAiming || hasInputThisFrame) + { + if (timerResetLook < 0.00001f) + { + lookQuat = finalQuat3P; + } + timerResetLook = 2.f; + + float mx = (CONTROLS::GET_CONTROL_NORMAL(2, eControl::ControlLookLeftRight)) * -5.f; + float my = (CONTROLS::GET_CONTROL_NORMAL(2, eControl::ControlLookUpDown)) * -5.f; + + if (!LastInputMethodWasMouseAndKeyboard()) + { + mx *= 0.6f; + my *= -0.6f; + } + + Vector3f vecLook = Vector3f(my, 0.f, mx); + Quaternionf result = lookQuat * QuatEuler(vecLook); + Vector3f resultEuler = QuatToEuler(result); + + float rx = clamp(resultEuler[0], -62.f, 40.f); + + lookQuat = QuatEuler(Vector3f(rx, 0.f, resultEuler[2])); + } + + timerResetLook = clamp(timerResetLook - getDeltaTime(), 0.f, 2.f); + + finalQuat3P = slerp(finalQuat3P, lookQuat, clamp01(timerResetLook)); + //finalQuat3P = lookQuat; + + Vector3f camPosSmooth = posCenter + extraCamHeight + V3CurrentTowHeightIncrement + (finalQuat3P * back * ((longitudeOffset3P) + 0.15f + airDistance)); camPosSmooth += slerp(smoothQuat3P, velocityQuat3P, smoothIsInAir) * back * distIncFinal; Vector3f camPosFinal = camPosSmooth; - Vector3f lookAt = posCenter + finalQuat3P * front * (longitudeOffset3P); - setCamPos(customCam, camPosFinal); - //camPointAt(customCam, lookAt); - Vector3f rotEuler = QuatToEuler(finalQuat3P); @@ -1581,12 +1647,6 @@ float getVehicleLongitude(Vehicle vehicle) { float maxBackDistance = 0.f; float maxFrontDistance = 0.f; - //Vector3f backBonePos; - //Vector3f frontBonePos; - - //const char * boneNameBack; - //const char * boneNameFront; - for (const char *boneName : vehicleBones) { int boneIndex = ENTITY::GET_ENTITY_BONE_INDEX_BY_NAME(vehicle, (char*)boneName); @@ -1926,7 +1986,7 @@ void update() } else { - veh = -1; + veh = NULL; ResetMouseLook(); DisableCustomCamera(); return; diff --git a/script.h b/script.h index 6488fe9..a355657 100644 --- a/script.h +++ b/script.h @@ -29,7 +29,6 @@ using namespace Eigen; #define M_PI 3.14159265358979323846 #endif - void DisableCustomCamera(); float getVehicleLongitude(Vehicle vehicle); @@ -52,6 +51,8 @@ Vector3f GetBonePos(Entity entity, char * boneName); void updateCam3pSmoothAlgorithm(); +bool LastInputMethodWasMouseAndKeyboard(); + void updateVehicleProperties(); void setupCurrentCamera(); From a3de220784e4bdcd925df411e90ef6b10dafc4ed Mon Sep 17 00:00:00 2001 From: Rbn_3D Date: Sun, 18 Mar 2018 21:02:12 +0100 Subject: [PATCH 7/9] Mouse/gamepad look around rewritten pitch of camera rotation/position based on vehicle velocity --- script.cpp | 189 ++++++++++++++++++++++++++++++----------------------- script.h | 18 ++--- 2 files changed, 115 insertions(+), 92 deletions(-) diff --git a/script.cpp b/script.cpp index 2e70495..e7b69b2 100644 --- a/script.cpp +++ b/script.cpp @@ -401,15 +401,15 @@ float DegToRad(const float °) return float(deg * M_PI / 180.0); } -Quaternionf QuatEuler(Vector3f &camVec) +Quaternionf QuatEuler(Vector3f &euler) { - Vector3f rotVec = DegToRad(1.0f) * camVec; + Vector3f rotVec = DegToRad(1.0f) * euler; Matrix3f xRot = AngleAxisf(rotVec.x(), Vector3f(1.0f, 0.0f, 0.0f)).matrix(); Matrix3f yRot = AngleAxisf(rotVec.y(), Vector3f(0.0f, 1.0f, 0.0f)).matrix(); Matrix3f zRot = AngleAxisf(rotVec.z(), Vector3f(0.0f, 0.0f, 1.0f)).matrix(); - Matrix3f rot = zRot * yRot*xRot; + Matrix3f rot = zRot * yRot * xRot; return Quaternionf(rot); } @@ -427,32 +427,8 @@ Vector2i getMouseCoords() { return Vector2i(mX, mY); } -void updateMouseState() { - int lastX = lastMouseCoords.x(); - int lastY = lastMouseCoords.y(); - - Vector2i currXY = getMouseCoords(); - int currX = currXY.x(); - int currY = currXY.y(); - - int movX = abs(lastX - currX); - int movY = abs(lastY - currY); - - mouseDeltaX = currX - lastX; - mouseDeltaY = currY - lastY; - - if (isAiming || movX >= 1 || movY >= 1) { // Mouse moved on last frame - - hasMouseInputThisFrame = true; - - if (isInVehicle && customCamEnabled && mouseMoveCountdown <= 0.0001f && smoothIsMouseLooking <= 0.001f) - setGameplayCamRelativeRotation(relAngle3p); // Sync gameplay cam rotarion - - mouseMoveCountdown = 1.5f; - } - else - hasMouseInputThisFrame = false; - +void updateMouseState() +{ float x = CONTROLS::GET_CONTROL_NORMAL(2, eControl::ControlLookLeftRight); float y = CONTROLS::GET_CONTROL_NORMAL(2, eControl::ControlLookUpDown); @@ -466,11 +442,6 @@ void updateMouseState() { } else hasInputThisFrame = false; - - if((veh != NULL && (vehSpeed > 0.1)) || veh == NULL) - mouseMoveCountdown = max(0.f, mouseMoveCountdown - (SYSTEM::TIMESTEP() * clamp01(vehSpeed * 0.08f))); - - lastMouseCoords = currXY; } void setGameplayCamRelativeRotation(float heading) { @@ -866,10 +837,6 @@ Vector3f lookRotEuler(Vector3f dir, Vector3f upVector) { return lookM.eulerAngles(2, 1, 0); } -Vector3f QuatEuler(Quaternionf quat) { - return quat.toRotationMatrix().eulerAngles(1, 0, 2); -} - Quaternionf getEntityQuaternion(Entity entity) { float x, y, z, w; @@ -1085,49 +1052,63 @@ void updateCameraDriverSeat() { //smoothRotSeat = Vector3fLerpAngle(smoothRotSeat, rot, clamp01(30.f * getDeltaTime())); smoothQuatSeat = getEntityQuaternion(veh); - if (smoothIsMouseLooking > 0.001f && btnLookingFactor < 0.001f) { - Vector3f gameplayCamRot = toV3f(CAM::GET_GAMEPLAY_CAM_ROT(2)); - Vector3f finalRotSeat = Vector3fLerpAngle(rot, gameplayCamRot, smoothIsMouseLooking); - CAM::SET_CAM_ROT(customCam, finalRotSeat.x(), finalRotSeat.y(), finalRotSeat.z(), 2); - } - else + float leftRightAngle = RelativeLookFactor < 0 ? + lerp(0.f, -LookLeftAngle1p, -RelativeLookFactor) + : + lerp(0.f, LookRightAngle1p, RelativeLookFactor) + ; + + float leftRightRad = leftRightAngle * DEG_TO_RAD; + + float roll = 0.f, pitch = 0.f, yaw = leftRightRad; + Quaternionf qLookLeftRight; + qLookLeftRight = AngleAxisf(roll, Vector3f::UnitX()) + * AngleAxisf(pitch, Vector3f::UnitY()) + * AngleAxisf(yaw, Vector3f::UnitZ()); + + Quaternionf finalQ = smoothQuatSeat * qLookLeftRight; + + if (isAiming || hasInputThisFrame) { - float leftRightAngle = RelativeLookFactor < 0 ? - lerp(0.f, -LookLeftAngle1p, -RelativeLookFactor) - : - lerp(0.f, LookRightAngle1p, RelativeLookFactor) - ; + if (timerResetLook < 0.00001f) + { + lookQuat = finalQ; + } + timerResetLook = 2.f; - float leftRightRad = leftRightAngle * DEG_TO_RAD; + float mx = (CONTROLS::GET_CONTROL_NORMAL(2, eControl::ControlLookLeftRight)) * -5.f; + float my = (CONTROLS::GET_CONTROL_NORMAL(2, eControl::ControlLookUpDown)) * (LastInputMethodWasMouseAndKeyboard ? -5.f : 5.f); - float roll = 0.f, pitch = 0.f, yaw = leftRightRad; - Quaternionf qLookLeftRight; - qLookLeftRight = AngleAxisf(roll, Vector3f::UnitX()) - * AngleAxisf(pitch, Vector3f::UnitY()) - * AngleAxisf(yaw, Vector3f::UnitZ()); + if (!LastInputMethodWasMouseAndKeyboard()) + { + mx *= 0.6f; + my *= 0.6f; + } + + Vector3f vecLook = Vector3f(my, 0.f, mx); + + Quaternionf result = lookQuat * QuatEuler(vecLook); + Vector3f resultEuler = QuatToEuler(result); - SET_CAM_QUATERNION(customCam, smoothQuatSeat * qLookLeftRight); + float rx = clamp(resultEuler[0], -62.f, 40.f); + lookQuat = QuatEuler(Vector3f(rx, 0.f, resultEuler[2])); } + + timerResetLook = clamp(timerResetLook - getDeltaTime(), 0.f, 2.f); + + finalQ = slerp(finalQ, lookQuat, clamp01(timerResetLook)); + + SET_CAM_QUATERNION(customCam, finalQ); } else { CAM::STOP_CAM_POINTING(customCam); Vector3f rot = toV3f(ENTITY::GET_ENTITY_ROTATION(veh, 2)); - Quaternionf rotQuat = getEntityQuaternion(veh); - //smoothRotSeat = Vector3fLerpAngle(smoothRotSeat, rot, clamp01(30.f * SYSTEM::TIMESTEP())); - //smoothRotSeat = Vector3fInertialDampAngle(smoothRotSeat, rot, 0.06f); - smoothRotSeat = Vector3fLerpAngle(smoothRotSeat, rot, clamp01(30.f * getDeltaTime())); - smoothQuatSeat = slerp(smoothQuatSeat, rotQuat, clamp01(30.f * getDeltaTime())); - - if (smoothIsMouseLooking > 0.001f && btnLookingFactor < 0.001f) { - Vector3f gameplayCamRot = toV3f(CAM::GET_GAMEPLAY_CAM_ROT(2)); - Vector3f finalRotSeat = Vector3fLerpAngle(smoothRotSeat, gameplayCamRot, smoothIsMouseLooking); - CAM::SET_CAM_ROT(customCam, finalRotSeat.x(), finalRotSeat.y(), finalRotSeat.z(), 2); - } - else - { + smoothQuatSeat = getEntityQuaternion(veh); + + float leftRightAngle = RelativeLookFactor < 0 ? lerp(0.f, -LookLeftAngle1p, -RelativeLookFactor) : @@ -1142,8 +1123,40 @@ void updateCameraDriverSeat() { * AngleAxisf(pitch, Vector3f::UnitY()) * AngleAxisf(yaw, Vector3f::UnitZ()); - SET_CAM_QUATERNION(customCam, smoothQuatSeat * qLookLeftRight); - } + Quaternionf finalQ = smoothQuatSeat * qLookLeftRight; + + if (isAiming || hasInputThisFrame) + { + if (timerResetLook < 0.00001f) + { + lookQuat = finalQ; + } + timerResetLook = 2.f; + + float mx = (CONTROLS::GET_CONTROL_NORMAL(2, eControl::ControlLookLeftRight)) * -5.f; + float my = (CONTROLS::GET_CONTROL_NORMAL(2, eControl::ControlLookUpDown)) * (LastInputMethodWasMouseAndKeyboard ? -5.f : 5.f); + + if (!LastInputMethodWasMouseAndKeyboard()) + { + mx *= 0.6f; + my *= 0.6f; + } + + Vector3f vecLook = Vector3f(my, 0.f, mx); + + Quaternionf result = lookQuat * QuatEuler(vecLook); + Vector3f resultEuler = QuatToEuler(result); + + float rx = clamp(resultEuler[0], -62.f, 40.f); + + lookQuat = QuatEuler(Vector3f(rx, 0.f, resultEuler[2])); + } + + timerResetLook = clamp(timerResetLook - getDeltaTime(), 0.f, 2.f); + + finalQ = slerp(finalQ, lookQuat, clamp01(timerResetLook)); + + SET_CAM_QUATERNION(customCam, finalQ); } CAM::RENDER_SCRIPT_CAMS(true, false, 3000, 1, 0); @@ -1468,20 +1481,20 @@ void updateCam3pNfsAlgorithm() Quaternionf vehQuat = getEntityQuaternion(veh); smoothQuat3P = slerp(smoothQuat3P, vehQuat, 3.f * getDeltaTime()); - ultraSmoothQuat3P = slerp(ultraSmoothQuat3P, vehQuat, 1.8f * getDeltaTime()); velocityQuat3P = lookRotation(smoothVelocity); - if (isBike && vehSpeed > 1.f) + //float vehPitch = QuatToEuler(velocityQuat3P).x(); + + if (/*isBike && */ vehSpeed > 1.f) { - Vector3f smoothEuler = QuatToEuler(ultraSmoothQuat3P); + Quaternionf quatVel = velocityQuat3P; - Vector3f latv = vehRightVector.cross(smoothVelocity); - latv[1] = 0.f; - latv.normalize(); + Vector3f VquatVel = QuatToEuler(velocityQuat3P); + Vector3f sm3p = QuatToEuler(smoothQuat3P); - smoothEuler[0] = latv[0]; + VquatVel[2] = sm3p[2]; - smoothQuat3P = QuatEuler(smoothEuler); + smoothQuat3P = QuatEuler(VquatVel); } currentTowHeightIncrement = lerp(currentTowHeightIncrement, towHeightIncrement, 1.45f * getDeltaTime()); @@ -1563,12 +1576,12 @@ void updateCam3pNfsAlgorithm() timerResetLook = 2.f; float mx = (CONTROLS::GET_CONTROL_NORMAL(2, eControl::ControlLookLeftRight)) * -5.f; - float my = (CONTROLS::GET_CONTROL_NORMAL(2, eControl::ControlLookUpDown)) * -5.f; + float my = (CONTROLS::GET_CONTROL_NORMAL(2, eControl::ControlLookUpDown)) * (LastInputMethodWasMouseAndKeyboard ? -5.f : 5.f); if (!LastInputMethodWasMouseAndKeyboard()) { mx *= 0.6f; - my *= -0.6f; + my *= 0.6f; } Vector3f vecLook = Vector3f(my, 0.f, mx); @@ -1586,7 +1599,18 @@ void updateCam3pNfsAlgorithm() finalQuat3P = slerp(finalQuat3P, lookQuat, clamp01(timerResetLook)); //finalQuat3P = lookQuat; - Vector3f camPosSmooth = posCenter + extraCamHeight + V3CurrentTowHeightIncrement + (finalQuat3P * back * ((longitudeOffset3P) + 0.15f + airDistance)); + if (smoothIsAiming > 0.00001f) { + float currentFov = lerp(fov3P, fov3PAiming, smoothIsAiming); + CAM::SET_CAM_FOV(customCam, currentFov); + } + + if (isAiming) { + UI::SHOW_HUD_COMPONENT_THIS_FRAME(eHudComponent::HudComponentReticle); + } + + float aimHeightIncrement = lerp(0.f, 0.22f, smoothIsAiming); + + Vector3f camPosSmooth = posCenter + extraCamHeight + V3CurrentTowHeightIncrement + (finalQuat3P * back * ((longitudeOffset3P) + 0.15f + airDistance)) + (up * aimHeightIncrement); camPosSmooth += slerp(smoothQuat3P, velocityQuat3P, smoothIsInAir) * back * distIncFinal; Vector3f camPosFinal = camPosSmooth; @@ -1986,7 +2010,6 @@ void update() } else { - veh = NULL; ResetMouseLook(); DisableCustomCamera(); return; diff --git a/script.h b/script.h index a355657..f6b48e4 100644 --- a/script.h +++ b/script.h @@ -162,8 +162,8 @@ const char* const vehicleBones[] = "steering", "hbgrip_l", "hbgrip_r", - "headlight_l", - "headlight_r", + //"headlight_l", + //"headlight_r", //"taillight_l", //"taillight_r", //"indicator_lf", @@ -173,13 +173,13 @@ const char* const vehicleBones[] = //"brakelight_l", //"brakelight_r", //"brakelight_m", - "reversinglight_l", - "reversinglight_r", - "extralight_1", - "extralight_2", - "extralight_3", - "extralight_4", - "numberplate", + //"reversinglight_l", + //"reversinglight_r", + //"extralight_1", + //"extralight_2", + //"extralight_3", + //"extralight_4", + //"numberplate", //"interiorlight", "siren1", "siren2", From 456e01d2f4bb51230b36a6d6a96e6d0efc534ad3 Mon Sep 17 00:00:00 2001 From: Rbn_3D Date: Sat, 24 Mar 2018 21:25:47 +0100 Subject: [PATCH 8/9] Release 1.0 work (mostly ready) Changelog: * Reworked 3rd person camera algorithm (completely rewritten) * 3rd person camera rotation doesn't get affected by suspension bounciness * Look around/aim/shoot has been reimplemented and now supports gamepad as well as keyboard * Progressive deadzone implemented when looking with gamepad, for better aim precision * Look left/right quickly by pressing hotkeys (configurable via ini file) * Support to look left/right/back from steering wheel! Requires an AppVeyor build of Manual Transmission Mod by @ikt (link below): https://ci.appveyor.com/project/E66666666/gtavmanualtransmission/build/artifacts * Other minor fixes and improvements Release soon --- CustomCameraVPlus.ini | 4 +-- Install.txt | 3 +++ changelog.txt | 13 +++++++++ script.cpp | 61 ++++++++++++++++++++++++++++++------------- 4 files changed, 61 insertions(+), 20 deletions(-) create mode 100644 changelog.txt diff --git a/CustomCameraVPlus.ini b/CustomCameraVPlus.ini index e68403e..e7027ce 100644 --- a/CustomCameraVPlus.ini +++ b/CustomCameraVPlus.ini @@ -13,9 +13,9 @@ lookRightAngle = 80.0 [general] -# Support Look left/right/behind from Manual Transmission mod by ikt (Requires latest AppVeyor build of Manual Transmission Mod) +# Support Look left/right/behind from Manual Transmission mod by ikt (Requires latest AppVeyor build of Manual Transmission Mod) # -# https://ci.appveyor.com/project/E66666666/gtavmanualtransmission/build/artifacts +# https://ci.appveyor.com/project/E66666666/gtavmanualtransmission/build/artifacts # # Set to 1 to enable, 0 to disable GetInputFromGearsAsi = 1 diff --git a/Install.txt b/Install.txt index 712c8e5..8b523bc 100644 --- a/Install.txt +++ b/Install.txt @@ -13,6 +13,9 @@ Usage: * Enter on any vehicle (except boat, helis and planes) and custom camera will be automatically enabled * Look around, aim and shoot just like with the built-in camera. * Switch between 3rd and 1st person view by pressing V (or other key mapped to switch views) +* Look left by pressing B, look right by pressing N * Look behind by pressing C (or other key mapped to look behind) * Toggle mod enabled by pressing 1. * Reload ini settings by pressing F10. + +* Lots of settings are configurable (check CustomCameraVPlus.ini) \ No newline at end of file diff --git a/changelog.txt b/changelog.txt new file mode 100644 index 0000000..dd7580e --- /dev/null +++ b/changelog.txt @@ -0,0 +1,13 @@ + +1.0: + +* Reworked 3rd person camera algorithm (completely rewritten) +* 3rd person camera rotation doesn't get affected by suspension bounciness +* Look around/aim/shoot has been reimplemented and now supports gamepad as well as keyboard +* Progressive deadzone implemented when looking with gamepad, for better aim precision +* Look left/right quickly by pressing hotkeys (configurable via ini file) +* Support to look left/right/back from steering wheel! + Requires an AppVeyor build of Manual Transmission Mod by @ikt (link below): + https://ci.appveyor.com/project/E66666666/gtavmanualtransmission/build/artifacts + +* Other minor fixes and improvements \ No newline at end of file diff --git a/script.cpp b/script.cpp index e7b69b2..a513b53 100644 --- a/script.cpp +++ b/script.cpp @@ -91,9 +91,10 @@ Vector3f cachedSurfaceNormal; Vector3f smoothSurfaceNormal; Vector3f smoothVelocity = Vector3f(); +Vector3f ultraSmoothVelocity = Vector3f(); Quaternionf velocityQuat3P = Quaternionf(); Quaternionf smoothQuat3P = Quaternionf(); -Quaternionf ultraSmoothQuat3P = Quaternionf(); +Quaternionf ultraSmoothVelocity3P = Quaternionf(); Vector3f smoothRotSeat = Vector3f(); Quaternionf smoothQuatSeat = Quaternionf(); float smoothIsInAir = 0.f; @@ -554,6 +555,9 @@ void showText(float x, float y, float scale, const char* text, int font, const C UI::END_TEXT_COMMAND_DISPLAY_TEXT(x, y); } +void showText(int index, const char* text) { + showText(0.1f, 0.03f * (float)index, 0.3f, text, 0, solidWhite, true); +} Vector3f getDimensions(Hash modelHash) { Vector3 min; @@ -941,6 +945,7 @@ void updateVehicleVars() vehForwardVector = toV3f(ENTITY::GET_ENTITY_FORWARD_VECTOR(veh)); vehSpeed = ENTITY::GET_ENTITY_SPEED(veh); smoothVelocity = lerp(smoothVelocity, vehSpeed > 2.f ? vehVelocity : vehForwardVector, 10.f * getDeltaTime()); + ultraSmoothVelocity = lerp(ultraSmoothVelocity, vehSpeed > 2.f ? vehVelocity : vehForwardVector, 3.f * getDeltaTime()); if ((ENTITY::IS_ENTITY_IN_AIR(veh) || (ENTITY::GET_ENTITY_UPRIGHT_VALUE(veh) < 0.6f)) && smoothIsInAir < 0.001f) { @@ -1471,6 +1476,13 @@ bool LastInputMethodWasMouseAndKeyboard() return CONTROLS::_IS_INPUT_DISABLED(2); } +Vector3f V3Reflect(Vector3f vector, Vector3f normal) +{ + float dot = vector.dot(normal); + Vector3f temp = normal * dot * 2.f; + return vector - temp; +} + void updateCam3pNfsAlgorithm() { Vector3f extraCamHeight = up * (0.14f + extraAngleCamHeight); @@ -1481,16 +1493,23 @@ void updateCam3pNfsAlgorithm() Quaternionf vehQuat = getEntityQuaternion(veh); smoothQuat3P = slerp(smoothQuat3P, vehQuat, 3.f * getDeltaTime()); + velocityQuat3P = lookRotation(smoothVelocity); + ultraSmoothVelocity3P = lookRotation(ultraSmoothVelocity); //float vehPitch = QuatToEuler(velocityQuat3P).x(); - if (/*isBike && */ vehSpeed > 1.f) + float forwardness = vehForwardVector.dot(vehVelocity); + + if (/*isBike && */forwardness >= 0.f && vehSpeed > 1.f) { - Quaternionf quatVel = velocityQuat3P; + Vector3f VquatVel = QuatToEuler(ultraSmoothVelocity3P); + Vector3f sm3p; - Vector3f VquatVel = QuatToEuler(velocityQuat3P); - Vector3f sm3p = QuatToEuler(smoothQuat3P); + //if (forwardness >= 0.f) + sm3p = QuatToEuler(smoothQuat3P); + //else + // sm3p = QuatToEuler(inverseSmoothQuat3P); VquatVel[2] = sm3p[2]; @@ -1578,10 +1597,23 @@ void updateCam3pNfsAlgorithm() float mx = (CONTROLS::GET_CONTROL_NORMAL(2, eControl::ControlLookLeftRight)) * -5.f; float my = (CONTROLS::GET_CONTROL_NORMAL(2, eControl::ControlLookUpDown)) * (LastInputMethodWasMouseAndKeyboard ? -5.f : 5.f); - if (!LastInputMethodWasMouseAndKeyboard()) + if (!LastInputMethodWasMouseAndKeyboard()) // if gamepad { - mx *= 0.6f; - my *= 0.6f; + mx *= 0.2f; + my *= 0.2f; + + //showText(1, std::to_string(mx).c_str()); + //showText(2, std::to_string(my).c_str()); + + float deadzone = 0.275f; + Vector2f stickInput = Vector2f(mx, my); + if (stickInput.norm() < deadzone) + stickInput = Vector2f(0.f, 0.f); + else + stickInput = stickInput.normalized() * ((stickInput.norm() - deadzone) / (1.f - deadzone)); + + mx = stickInput.x() * 2.f; + my = stickInput.y() * 2.f; } Vector3f vecLook = Vector3f(my, 0.f, mx); @@ -1610,7 +1642,7 @@ void updateCam3pNfsAlgorithm() float aimHeightIncrement = lerp(0.f, 0.22f, smoothIsAiming); - Vector3f camPosSmooth = posCenter + extraCamHeight + V3CurrentTowHeightIncrement + (finalQuat3P * back * ((longitudeOffset3P) + 0.15f + airDistance)) + (up * aimHeightIncrement); + Vector3f camPosSmooth = posCenter + extraCamHeight + V3CurrentTowHeightIncrement + (finalQuat3P * back * ((longitudeOffset3P) + 0.185f + airDistance)) + (up * aimHeightIncrement); camPosSmooth += slerp(smoothQuat3P, velocityQuat3P, smoothIsInAir) * back * distIncFinal; Vector3f camPosFinal = camPosSmooth; @@ -1658,7 +1690,7 @@ void DisableCustomCamera() CAM::RENDER_SCRIPT_CAMS(false, false, 3000, true, false); camInitialized = false; isInVehicle = false; - veh = NULL; + //veh = NULL; haltCurrentCamera(); } @@ -1969,17 +2001,10 @@ void update() } if (IsKeyJustUp(str2key(reloadKey))) { - - haltCurrentCamera(); - + ReadSettings(true); updateVehicleVars(); updateVehicleProperties(); - setupCustomCamera(); - - ReadSettings(true); - - setupCurrentCamera(); } updateTimers(); From 63eef0d9e7e854e5b6b15048ffd10351524c5352 Mon Sep 17 00:00:00 2001 From: Rbn_3D Date: Sat, 24 Mar 2018 21:40:03 +0100 Subject: [PATCH 9/9] Implemented raycast, so camera cannot go over walls --- CustomCameraVPlus.vcxproj | 6 ++++++ script.cpp | 14 ++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/CustomCameraVPlus.vcxproj b/CustomCameraVPlus.vcxproj index 91c41cc..2790de6 100644 --- a/CustomCameraVPlus.vcxproj +++ b/CustomCameraVPlus.vcxproj @@ -19,6 +19,12 @@ + + + + + + {8D82F34A-1D64-465B-84B1-37F89AD3D20B} Win32Proj diff --git a/script.cpp b/script.cpp index a513b53..8e417ee 100644 --- a/script.cpp +++ b/script.cpp @@ -1649,6 +1649,20 @@ void updateCam3pNfsAlgorithm() setCamPos(customCam, camPosFinal); + // Raycast // + int ray = WORLDPROBE::_START_SHAPE_TEST_RAY(posCenter.x(), posCenter.y(), posCenter.z(), camPosFinal.x(), camPosFinal.y(), camPosFinal.z(), 1, veh, 7); + + Vector3 endCoords, surfaceNormal; + BOOL hit; + Entity entityHit = 0; + + WORLDPROBE::GET_SHAPE_TEST_RESULT(ray, &hit, &endCoords, &surfaceNormal, &entityHit); + + if (hit) { + setCamPos(customCam, toV3f(endCoords) + (finalQuat3P * front * 0.1f)); + } + // End raycast // + Vector3f rotEuler = QuatToEuler(finalQuat3P); rotEuler[1] = 0.f;