From 997b348794eaed0329e5562865ce5758a2b0f35a Mon Sep 17 00:00:00 2001 From: Turanszki Janos Date: Mon, 20 Apr 2020 20:27:11 +0100 Subject: [PATCH] third person character capsule collision --- WickedEngine/wiScene.cpp | 279 +++++++++++++++++++++++---- WickedEngine/wiScene.h | 1 + WickedEngine/wiScene_BindLua.cpp | 56 ++++++ WickedEngine/wiVersion.cpp | 2 +- models/playground.wiscene | Bin 28868 -> 117691 bytes scripts/character_controller_tps.lua | 28 +-- 6 files changed, 315 insertions(+), 51 deletions(-) diff --git a/WickedEngine/wiScene.cpp b/WickedEngine/wiScene.cpp index 2167d2aa6..53637aa33 100644 --- a/WickedEngine/wiScene.cpp +++ b/WickedEngine/wiScene.cpp @@ -2808,7 +2808,7 @@ namespace wiScene p2 = SkinVertex(mesh, *armature, i2); } } - + p0 = XMVector3Transform(p0, objectMat); p1 = XMVector3Transform(p1, objectMat); p2 = XMVector3Transform(p2, objectMat); @@ -2822,10 +2822,10 @@ namespace wiScene // Find the nearest feature on the triangle to the sphere. XMVECTOR Dist = XMVector3Dot(XMVectorSubtract(vCenter, p0), N); - //if (XMVectorGetX(Dist) > 0) - //{ - // continue; - //} + if (!mesh.IsDoubleSided() && XMVectorGetX(Dist) > 0) + { + continue; // pass through back faces + } // If the center of the sphere is farther from the plane of the triangle than // the radius of the sphere, then there cannot be an intersection. @@ -2833,69 +2833,270 @@ namespace wiScene NoIntersection = XMVectorOrInt(NoIntersection, XMVectorGreater(Dist, vRadius)); // Project the center of the sphere onto the plane of the triangle. - XMVECTOR Point = XMVectorNegativeMultiplySubtract(N, Dist, vCenter); - XMVECTOR planeIntersection = Point; + XMVECTOR Point0 = XMVectorNegativeMultiplySubtract(N, Dist, vCenter); // Is it inside all the edges? If so we intersect because the distance // to the plane is less than the radius. - XMVECTOR Intersection = DirectX::Internal::PointOnPlaneInsideTriangle(Point, p0, p1, p2); + XMVECTOR Intersection = DirectX::Internal::PointOnPlaneInsideTriangle(Point0, p0, p1, p2); bool inside = XMVector4EqualInt(XMVectorAndCInt(Intersection, NoIntersection), XMVectorTrueInt()); - XMVECTOR bestPoint = Point; - float bestDist = inside ? 0 : FLT_MAX; // Find the nearest point on each edge. // Edge 0,1 - Point = DirectX::Internal::PointOnLineSegmentNearestPoint(p0, p1, vCenter); + XMVECTOR Point1 = DirectX::Internal::PointOnLineSegmentNearestPoint(p0, p1, vCenter); // If the distance to the center of the sphere to the point is less than // the radius of the sphere then it must intersect. - Intersection = XMVectorOrInt(Intersection, XMVectorLessOrEqual(XMVector3LengthSq(XMVectorSubtract(vCenter, Point)), RadiusSq)); - - float d = abs(XMVectorGetX(XMVector3LinePointDistance(p0, p1, planeIntersection))); - if (d < bestDist) - { - bestDist = d; - bestPoint = Point; - } + Intersection = XMVectorOrInt(Intersection, XMVectorLessOrEqual(XMVector3LengthSq(XMVectorSubtract(vCenter, Point1)), RadiusSq)); // Edge 1,2 - Point = DirectX::Internal::PointOnLineSegmentNearestPoint(p1, p2, vCenter); + XMVECTOR Point2 = DirectX::Internal::PointOnLineSegmentNearestPoint(p1, p2, vCenter); // If the distance to the center of the sphere to the point is less than // the radius of the sphere then it must intersect. - Intersection = XMVectorOrInt(Intersection, XMVectorLessOrEqual(XMVector3LengthSq(XMVectorSubtract(vCenter, Point)), RadiusSq)); - - d = abs(XMVectorGetX(XMVector3LinePointDistance(p1, p2, planeIntersection))); - if (d < bestDist) - { - bestDist = d; - bestPoint = Point; - } + Intersection = XMVectorOrInt(Intersection, XMVectorLessOrEqual(XMVector3LengthSq(XMVectorSubtract(vCenter, Point2)), RadiusSq)); // Edge 2,0 - Point = DirectX::Internal::PointOnLineSegmentNearestPoint(p2, p0, vCenter); + XMVECTOR Point3 = DirectX::Internal::PointOnLineSegmentNearestPoint(p2, p0, vCenter); // If the distance to the center of the sphere to the point is less than // the radius of the sphere then it must intersect. - Intersection = XMVectorOrInt(Intersection, XMVectorLessOrEqual(XMVector3LengthSq(XMVectorSubtract(vCenter, Point)), RadiusSq)); - - d = abs(XMVectorGetX(XMVector3LinePointDistance(p2, p0, planeIntersection))); - if (d < bestDist) - { - bestDist = d; - bestPoint = Point; - } + Intersection = XMVectorOrInt(Intersection, XMVectorLessOrEqual(XMVector3LengthSq(XMVectorSubtract(vCenter, Point3)), RadiusSq)); bool intersects = XMVector4EqualInt(XMVectorAndCInt(Intersection, NoIntersection), XMVectorTrueInt()); if (intersects) { + XMVECTOR bestPoint = Point0; + if (!inside) + { + // If the sphere center's projection on the triangle plane is not within the triangle, + // determine the closest point on triangle to the sphere center + float bestDist = FLT_MAX; + float d = abs(XMVectorGetX(XMVector3LengthSq(Point1 - vCenter))); + if (d < bestDist) + { + bestDist = d; + bestPoint = Point1; + } + d = abs(XMVectorGetX(XMVector3LengthSq(Point2 - vCenter))); + if (d < bestDist) + { + bestDist = d; + bestPoint = Point2; + } + d = abs(XMVectorGetX(XMVector3LengthSq(Point3 - vCenter))); + if (d < bestDist) + { + bestDist = d; + bestPoint = Point3; + } + } + XMVECTOR intersectionVec = vCenter - bestPoint; + XMVECTOR intersectionVecLen = XMVector3Length(intersectionVec); + result.entity = entity; - result.depth = sphere.radius - XMVectorGetX(XMVector3Length(vCenter - bestPoint)); + result.depth = sphere.radius - XMVectorGetX(intersectionVecLen); XMStoreFloat3(&result.position, bestPoint); - XMStoreFloat3(&result.normal, XMVector3Normalize(vCenter - bestPoint)); + XMStoreFloat3(&result.normal, intersectionVec / intersectionVecLen); + return result; + } + } + subsetCounter++; + } + + } + } + + return result; + } + SceneIntersectSphereResult SceneIntersectCapsule(const SPHERE& sphere, float height, uint32_t renderTypeMask, uint32_t layerMask, const Scene& scene) + { + SceneIntersectSphereResult result; + XMVECTOR vCenterBase = XMLoadFloat3(&sphere.center); + XMVECTOR vTip = vCenterBase + XMVectorSet(0, height, 0, 0); + XMVECTOR vRadius = XMVectorReplicate(sphere.radius); + XMVECTOR RadiusSq = XMVectorMultiply(vRadius, vRadius); + + AABB base_aabb; + base_aabb.createFromHalfWidth(sphere.center, XMFLOAT3(sphere.radius, sphere.radius, sphere.radius)); + XMFLOAT3 centertip; + XMStoreFloat3(¢ertip, vTip); + AABB tip_aabb; + tip_aabb.createFromHalfWidth(centertip, XMFLOAT3(sphere.radius, sphere.radius, sphere.radius)); + AABB capsule_aabb = AABB::Merge(base_aabb, tip_aabb); + + if (scene.objects.GetCount() > 0) + { + + for (size_t i = 0; i < scene.aabb_objects.GetCount(); ++i) + { + const AABB& aabb = scene.aabb_objects[i]; + if (capsule_aabb.intersects(aabb) == AABB::INTERSECTION_TYPE::OUTSIDE) + { + continue; + } + + const ObjectComponent& object = scene.objects[i]; + if (object.meshID == INVALID_ENTITY) + { + continue; + } + if (!(renderTypeMask & object.GetRenderTypes())) + { + continue; + } + + Entity entity = scene.aabb_objects.GetEntity(i); + const LayerComponent* layer = scene.layers.GetComponent(entity); + if (layer != nullptr && !(layer->GetLayerMask() & layerMask)) + { + continue; + } + + const MeshComponent& mesh = *scene.meshes.GetComponent(object.meshID); + const SoftBodyPhysicsComponent* softbody = scene.softbodies.GetComponent(object.meshID); + const bool softbody_active = softbody != nullptr && !softbody->vertex_positions_simulation.empty(); + + const XMMATRIX objectMat = object.transform_index >= 0 ? XMLoadFloat4x4(&scene.transforms[object.transform_index].world) : XMMatrixIdentity(); + + const ArmatureComponent* armature = mesh.IsSkinned() ? scene.armatures.GetComponent(mesh.armatureID) : nullptr; + + int subsetCounter = 0; + for (auto& subset : mesh.subsets) + { + for (size_t i = 0; i < subset.indexCount; i += 3) + { + const uint32_t i0 = mesh.indices[subset.indexOffset + i + 0]; + const uint32_t i1 = mesh.indices[subset.indexOffset + i + 1]; + const uint32_t i2 = mesh.indices[subset.indexOffset + i + 2]; + + XMVECTOR p0; + XMVECTOR p1; + XMVECTOR p2; + + if (softbody_active) + { + p0 = softbody->vertex_positions_simulation[i0].LoadPOS(); + p1 = softbody->vertex_positions_simulation[i1].LoadPOS(); + p2 = softbody->vertex_positions_simulation[i2].LoadPOS(); + } + else + { + if (armature == nullptr) + { + p0 = XMLoadFloat3(&mesh.vertex_positions[i0]); + p1 = XMLoadFloat3(&mesh.vertex_positions[i1]); + p2 = XMLoadFloat3(&mesh.vertex_positions[i2]); + } + else + { + p0 = SkinVertex(mesh, *armature, i0); + p1 = SkinVertex(mesh, *armature, i1); + p2 = SkinVertex(mesh, *armature, i2); + } + } + + p0 = XMVector3Transform(p0, objectMat); + p1 = XMVector3Transform(p1, objectMat); + p2 = XMVector3Transform(p2, objectMat); + + // Compute the plane of the triangle (has to be normalized). + XMVECTOR N = XMVector3Normalize(XMVector3Cross(XMVectorSubtract(p1, p0), XMVectorSubtract(p2, p0))); + + // Intersect capsule line with triangle plane: + XMVECTOR Plane = XMPlaneFromPointNormal(p0, N); + XMVECTOR LinePlaneIntersection = XMPlaneIntersectLine(Plane, vCenterBase, vTip); + // Place a sphere on closest point on line segment to intersection: + XMVECTOR ab = vTip - vCenterBase; + XMVECTOR t = XMVector3Dot(LinePlaneIntersection - vCenterBase, ab) / XMVector3Dot(ab, ab); + XMVECTOR vCenter = vCenterBase + XMVectorSaturate(t) * ab; + + // Assert that the triangle is not degenerate. + assert(!XMVector3Equal(N, XMVectorZero())); + + // Find the nearest feature on the triangle to the sphere. + XMVECTOR Dist = XMVector3Dot(XMVectorSubtract(vCenter, p0), N); + + if (!mesh.IsDoubleSided() && XMVectorGetX(Dist) > 0) + { + continue; // pass through back faces + } + + // If the center of the sphere is farther from the plane of the triangle than + // the radius of the sphere, then there cannot be an intersection. + XMVECTOR NoIntersection = XMVectorLess(Dist, XMVectorNegate(vRadius)); + NoIntersection = XMVectorOrInt(NoIntersection, XMVectorGreater(Dist, vRadius)); + + // Project the center of the sphere onto the plane of the triangle. + XMVECTOR Point0 = XMVectorNegativeMultiplySubtract(N, Dist, vCenter); + + // Is it inside all the edges? If so we intersect because the distance + // to the plane is less than the radius. + XMVECTOR Intersection = DirectX::Internal::PointOnPlaneInsideTriangle(Point0, p0, p1, p2); + + bool inside = XMVector4EqualInt(XMVectorAndCInt(Intersection, NoIntersection), XMVectorTrueInt()); + + // Find the nearest point on each edge. + + // Edge 0,1 + XMVECTOR Point1 = DirectX::Internal::PointOnLineSegmentNearestPoint(p0, p1, vCenter); + + // If the distance to the center of the sphere to the point is less than + // the radius of the sphere then it must intersect. + Intersection = XMVectorOrInt(Intersection, XMVectorLessOrEqual(XMVector3LengthSq(XMVectorSubtract(vCenter, Point1)), RadiusSq)); + + // Edge 1,2 + XMVECTOR Point2 = DirectX::Internal::PointOnLineSegmentNearestPoint(p1, p2, vCenter); + + // If the distance to the center of the sphere to the point is less than + // the radius of the sphere then it must intersect. + Intersection = XMVectorOrInt(Intersection, XMVectorLessOrEqual(XMVector3LengthSq(XMVectorSubtract(vCenter, Point2)), RadiusSq)); + + // Edge 2,0 + XMVECTOR Point3 = DirectX::Internal::PointOnLineSegmentNearestPoint(p2, p0, vCenter); + + // If the distance to the center of the sphere to the point is less than + // the radius of the sphere then it must intersect. + Intersection = XMVectorOrInt(Intersection, XMVectorLessOrEqual(XMVector3LengthSq(XMVectorSubtract(vCenter, Point3)), RadiusSq)); + + bool intersects = XMVector4EqualInt(XMVectorAndCInt(Intersection, NoIntersection), XMVectorTrueInt()); + + if (intersects) + { + XMVECTOR bestPoint = Point0; + if (!inside) + { + // If the sphere center's projection on the triangle plane is not within the triangle, + // determine the closest point on triangle to the sphere center + float bestDist = FLT_MAX; + float d = abs(XMVectorGetX(XMVector3LengthSq(Point1 - vCenter))); + if (d < bestDist) + { + bestDist = d; + bestPoint = Point1; + } + d = abs(XMVectorGetX(XMVector3LengthSq(Point2 - vCenter))); + if (d < bestDist) + { + bestDist = d; + bestPoint = Point2; + } + d = abs(XMVectorGetX(XMVector3LengthSq(Point3 - vCenter))); + if (d < bestDist) + { + bestDist = d; + bestPoint = Point3; + } + } + XMVECTOR intersectionVec = vCenter - bestPoint; + XMVECTOR intersectionVecLen = XMVector3Length(intersectionVec); + + result.entity = entity; + result.depth = sphere.radius - XMVectorGetX(intersectionVecLen); + XMStoreFloat3(&result.position, bestPoint); + XMStoreFloat3(&result.normal, intersectionVec / intersectionVecLen); return result; } } diff --git a/WickedEngine/wiScene.h b/WickedEngine/wiScene.h index 0c4fced06..53f78b1a6 100644 --- a/WickedEngine/wiScene.h +++ b/WickedEngine/wiScene.h @@ -1362,6 +1362,7 @@ namespace wiScene float depth = 0; }; SceneIntersectSphereResult SceneIntersectSphere(const SPHERE& sphere, uint32_t renderTypeMask = RENDERTYPE_OPAQUE, uint32_t layerMask = ~0, const Scene& scene = GetScene()); + SceneIntersectSphereResult SceneIntersectCapsule(const SPHERE& sphere, float height, uint32_t renderTypeMask = RENDERTYPE_OPAQUE, uint32_t layerMask = ~0, const Scene& scene = GetScene()); } diff --git a/WickedEngine/wiScene_BindLua.cpp b/WickedEngine/wiScene_BindLua.cpp index 66bcd1091..35e2d2f1f 100644 --- a/WickedEngine/wiScene_BindLua.cpp +++ b/WickedEngine/wiScene_BindLua.cpp @@ -189,6 +189,61 @@ int SceneIntersectSphere(lua_State* L) return 0; } +int SceneIntersectCapsule(lua_State* L) +{ + int argc = wiLua::SGetArgCount(L); + if (argc > 0) + { + Sphere_BindLua* sphere = Luna::lightcheck(L, 1); + if (sphere != nullptr) + { + uint32_t renderTypeMask = RENDERTYPE_OPAQUE; + uint32_t layerMask = 0xFFFFFFFF; + Scene* scene = &wiScene::GetScene(); + float height = 1; + if (argc > 1) + { + height = wiLua::SGetFloat(L, 2); + if (argc > 2) + { + renderTypeMask = (uint32_t)wiLua::SGetInt(L, 3); + if (argc > 3) + { + int mask = wiLua::SGetInt(L, 4); + layerMask = *reinterpret_cast(&mask); + + if (argc > 4) + { + Scene_BindLua* custom_scene = Luna::lightcheck(L, 5); + if (custom_scene) + { + scene = custom_scene->scene; + } + else + { + wiLua::SError(L, "SceneIntersectCapsule(Sphere sphere, float height, opt PICKTYPE pickType, opt uint layerMask, opt Scene scene) last argument is not of type Scene!"); + } + } + } + } + } + auto& pick = wiScene::SceneIntersectCapsule(sphere->sphere, height, renderTypeMask, layerMask, *scene); + wiLua::SSetInt(L, (int)pick.entity); + Luna::push(L, new Vector_BindLua(XMLoadFloat3(&pick.position))); + Luna::push(L, new Vector_BindLua(XMLoadFloat3(&pick.normal))); + wiLua::SSetFloat(L, pick.depth); + return 4; + } + + wiLua::SError(L, "SceneIntersectCapsule(Sphere sphere, float height, opt PICKTYPE pickType, opt uint layerMask, opt Scene scene) first argument must be of Ray type!"); + } + else + { + wiLua::SError(L, "SceneIntersectCapsule(Sphere sphere, float height, opt PICKTYPE pickType, opt uint layerMask, opt Scene scene) not enough arguments!"); + } + + return 0; +} void Bind() { @@ -219,6 +274,7 @@ void Bind() wiLua::GetGlobal()->RegisterFunc("LoadModel", LoadModel); wiLua::GetGlobal()->RegisterFunc("Pick", Pick); wiLua::GetGlobal()->RegisterFunc("SceneIntersectSphere", SceneIntersectSphere); + wiLua::GetGlobal()->RegisterFunc("SceneIntersectCapsule", SceneIntersectCapsule); Luna::Register(L); Luna::Register(L); diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index 97925679b..64bdb644e 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -9,7 +9,7 @@ namespace wiVersion // minor features, major updates const int minor = 39; // minor bug fixes, alterations, refactors, updates - const int revision = 73; + const int revision = 74; long GetVersion() diff --git a/models/playground.wiscene b/models/playground.wiscene index e526d65e8693629486a791e230bcdba79e3de777..72f87d7fedeadf7c223e65710772f7528956f430 100644 GIT binary patch literal 117691 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 delta 6590 zcmeHM3s6mI9KWYd-RdHxhjNihC6cJFRQH^tHla3;tUOX^l~G<<&(^`N=U~TN>$KP; zwv05YTe`{PoY=ILv1mPFBuRNRvP;;Z_WZv(Hi^P@cV@?#x$`^!@B7a8{(Zmy|GRmN z_;dwkG(hzFGbh7nyFQ)y;*lPt_ll0_0ysiC3KcwVC0P#k%8L9*z!j?Sg@6Z)7x@F` zZChsvm^S(0P{5ibNfco0vmy&XpMW|oz^?+WdjT%FD)R))FYxOQSQx!Q%mXc&mm~9n zgzRYtjRBX;%IOIhAN`jLpsM(c0pO5{$@+j!I_CC(Y(=Uypo7U_95Bi@5!G|-xitZH z$P>94;N;Ma{Q+O@UyRDV*k0cmY?p*0-ljz&KiMC)kkG%JLly5ndj$1(+_smf$0u{| zqkQ7brXf&nX;nYek#A$aLml;FDo}b>*iUExqqXKbL%9P1rE4yji;L3%>+IJA_@Jp<58+2hkZAia8OEE?#>B2OD=Uv#Ij4;sPUtvG6U z+3aIzDpNQ6qK0q84n+;CO56uQ`Q1}*ppiMm8={#xJggRt$iwjvYQQ=!zzWJ)E+32b zNadwaG$YF*^U#t?Wb=(6U+xe^qs`#7Z&(jVxYkfZ0j@2xLz~DyY-$|Xo6gw;0X7Eb zi~bmV22 zn-088`aT79L=nCoO<9ENAV)|y*lCVNK4a<4C198NTp0{Fv8WEMb=)EcRN+3=e)Qd@ z3E8fYpH;gBP4RSPTo*%aS|FD|CV@l(d4!31Px5q>JM@=slTlZX-CP)VS2bDv0@u5bSAF^^W?tWbr65f61wO#Mb4t^5CnrCmznzBO0cDtr) zb3Zwkq*NRw;m_72DBJ9-P?{6THRXwp2rFON}E4agFo&#;g8U_X>2ge8~?Os zg&?kK5mh+CHRF-C%>pDL8u3W^fwsW{T4Nq5EajUlpf%=^wkfVvW12ljK@2-Cey?jE zj1C^LGHakACN43HAVLohRu(x|;2uIKCWKx>h$Sewpzwk>D>$jT$^>^YhQsFyZsZt6 zn)@>x>HtF-NJQZ{)TGGuY084?{>_5Ql({}C9Ea-oLjD0l2q=VnLTD#=7J~OIIK@pP z5{U#NYBwi9J+lE-tl9mS*7bP3b8eW7Tj_d%MWJUj$-Q#VR8=5H_5k| zc7dwDvm>YYD3*=Wj`|sF;-g;Ps=AR>22QZ0Nm^uj+Cu6;RRUWbszr{s9!ss6?Z7?` zTuoNTE~cW&cCe`fR+EpzzobG;da~N1IWm3qLTY184GCdb@y!x0I(iaS`9r!qCt@dO zo_mjka4c~21uipqGBr!tiSRhLhf7I)K=NT3P4sNI%>5lWg}N^zO$lk)Agq$t|?n!G24UD$%6P42J; z?@3!xG^pu*v~^7Np1m@x&I zE#q2%jnfg4{2Vc(3ouVz^hzi4t1)Gy#!4?nUvUw*yc6E?AGEhoE`$wZ#PcG0<1J$;EiXK%^*9+VE(VNIwR>BVI7 zvNCE`Xc-&Tki}i}avC0Z-k3^yevwsomqpCFLTs2~zOxR)7Ghm- 0) then + ground_intersection = true + end + end end --DrawPoint(sphere.GetCenter(), 0.5, Vector(0,1,0,1)) - if intersection then - self.velocity = vector.Multiply(self.velocity, 0.87) -- ground friction + if ground_intersection then + self.velocity = vector.Multiply(self.velocity, 0.85) -- ground friction else self.velocity = vector.Multiply(self.velocity, 0.94) -- air friction end if(vector.Length(self.velocity) < 0.001) then self.state = self.states.STAND end - model_transform.Translate(vector.Subtract(sphere.GetCenter(), pp)) + model_transform.Translate(vector.Subtract(sphere.GetCenter(), original_spherecenter)) -- transform by the sphere offset model_transform.UpdateTransform() -- try to put water ripple if character head is directly above water