2 Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc.
\r
5 Physics Effects is open software; you can redistribute it and/or
\r
6 modify it under the terms of the BSD License.
\r
8 Physics Effects is distributed in the hope that it will be useful,
\r
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
\r
11 See the BSD License for more details.
\r
13 A copy of the BSD License is distributed with
\r
14 Physics Effects under the filename: physics_effects_license.txt
\r
17 #include "../../../include/physics_effects/base_level/base/pfx_vec_utils.h"
\r
18 #include "pfx_contact_tri_mesh_sphere.h"
\r
19 #include "pfx_intersect_common.h"
\r
20 #include "pfx_mesh_common.h"
\r
23 namespace PhysicsEffects {
\r
25 static SCE_PFX_FORCE_INLINE
\r
26 bool pfxContactTriangleSphere(PfxContactCache &contacts,PfxUInt32 facetId,
\r
27 const PfxVector3 &normal,const PfxVector3 &p0,const PfxVector3 &p1,const PfxVector3 &p2,
\r
28 const PfxFloat thickness,const PfxFloat angle0,const PfxFloat angle1,const PfxFloat angle2,
\r
30 PfxFloat sphereRadius,const PfxVector3 &spherePos)
\r
32 PfxVector3 facetPnts[3] = {
\r
38 PfxPlane planeA(normal,p0);
\r
39 PfxFloat len1 = planeA.onPlane(spherePos);
\r
41 if(len1 >= sphereRadius || len1 < -thickness-sphereRadius) return false;
\r
47 PfxTriangle triangleA(p0,p1,p2);
\r
49 // pfxClosestPointTriangle(spherePos,triangleA,pntA);
\r
50 bool insideTriangle = false;
\r
52 PfxVector3 ab = p1 - p0;
\r
53 PfxVector3 ac = p2 - p0;
\r
54 PfxVector3 ap = spherePos - p0;
\r
55 PfxFloat d1 = dot(ab, ap);
\r
56 PfxFloat d2 = dot(ac, ap);
\r
57 if(d1 <= 0.0f && d2 <= 0.0f) {
\r
62 PfxVector3 bp = spherePos - p1;
\r
63 PfxFloat d3 = dot(ab, bp);
\r
64 PfxFloat d4 = dot(ac, bp);
\r
65 if (d3 >= 0.0f && d4 <= d3) {
\r
70 PfxFloat vc = d1*d4 - d3*d2;
\r
71 if (vc <= 0.0f && d1 >= 0.0f && d3 <= 0.0f) {
\r
72 PfxFloat v = d1 / (d1 - d3);
\r
77 PfxVector3 cp = spherePos - p2;
\r
78 PfxFloat d5 = dot(ab, cp);
\r
79 PfxFloat d6 = dot(ac, cp);
\r
80 if (d6 >= 0.0f && d5 <= d6) {
\r
85 PfxFloat vb = d5*d2 - d1*d6;
\r
86 if (vb <= 0.0f && d2 >= 0.0f && d6 <= 0.0f) {
\r
87 PfxFloat w = d2 / (d2 - d6);
\r
92 PfxFloat va = d3*d6 - d5*d4;
\r
93 if (va <= 0.0f && (d4 - d3) >= 0.0f && (d5 - d6) >= 0.0f) {
\r
94 PfxFloat w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
\r
95 pntA = p1 + w * (p2 - p1);
\r
99 PfxFloat den = 1.0f / (va + vb + vc);
\r
100 PfxFloat v = vb * den;
\r
101 PfxFloat w = vc * den;
\r
102 pntA = p0 + ab * v + ac * w;
\r
103 insideTriangle = true;
\r
106 PfxVector3 distVec = pntA - spherePos;
\r
107 PfxFloat l = length(distVec);
\r
109 if(!insideTriangle && l >= sphereRadius) return false;
\r
112 PfxVector3 sepAxis = (l < 0.00001f || insideTriangle) ? -normal : distVec / l;
\r
115 PfxVector3 pointsOnSphere = spherePos + sphereRadius * sepAxis;
\r
116 PfxVector3 pointsOnTriangle = pntA;
\r
118 // 面上の最近接点が凸エッジ上でない場合は法線を変える
\r
119 if( ((edgeChk&0x01)&&pfxPointOnLine(pointsOnTriangle,p0,p1)) ||
\r
120 ((edgeChk&0x02)&&pfxPointOnLine(pointsOnTriangle,p1,p2)) ||
\r
121 ((edgeChk&0x04)&&pfxPointOnLine(pointsOnTriangle,p2,p0)) ) {
\r
125 PfxSubData subData;
\r
126 subData.setFacetId(facetId);
\r
127 contacts.addContactPoint(-length(pointsOnSphere-pointsOnTriangle),sepAxis,PfxPoint3(pointsOnTriangle),PfxPoint3(pointsOnSphere),subData);
\r
133 PfxInt32 pfxContactTriMeshSphere(
\r
134 PfxContactCache &contacts,
\r
135 const PfxTriMesh *meshA,
\r
136 const PfxTransform3 &transformA,
\r
137 const PfxSphere &sphereB,
\r
138 const PfxTransform3 &transformB,
\r
139 PfxFloat distanceThreshold)
\r
141 (void) distanceThreshold;
\r
143 PfxTransform3 transformAB,transformBA;
\r
144 PfxMatrix3 matrixBA;
\r
145 PfxVector3 offsetBA;
\r
148 transformAB = orthoInverse(transformA) * transformB;
\r
151 transformBA = orthoInverse(transformAB);
\r
153 matrixBA = transformBA.getUpper3x3();
\r
154 offsetBA = transformBA.getTranslation();
\r
156 //-------------------------------------------
\r
159 PfxUInt8 SCE_PFX_ALIGNED(16) selFacets[SCE_PFX_NUMMESHFACETS] = {0};
\r
160 PfxUInt32 numSelFacets = 0;
\r
162 PfxVector3 aabbB(sphereB.m_radius);
\r
163 numSelFacets = pfxGatherFacets(meshA,(PfxFloat*)&aabbB,offsetBA,matrixBA,selFacets);
\r
165 if(numSelFacets == 0) {
\r
169 //-----------------------------------------------
\r
172 PfxContactCache localContacts;
\r
174 // TriangleMeshの面->sphereの判定
\r
175 // ※TriangleMesh座標系
\r
177 for(PfxUInt32 f = 0; f < numSelFacets; f++ ) {
\r
178 const PfxFacet &facet = meshA->m_facets[selFacets[f]];
\r
180 const PfxVector3 facetNormal = pfxReadVector3(facet.m_normal);
\r
182 const PfxVector3 facetPnts[3] = {
\r
183 meshA->m_verts[facet.m_vertIds[0]],
\r
184 meshA->m_verts[facet.m_vertIds[1]],
\r
185 meshA->m_verts[facet.m_vertIds[2]],
\r
188 const PfxEdge *edge[3] = {
\r
189 &meshA->m_edges[facet.m_edgeIds[0]],
\r
190 &meshA->m_edges[facet.m_edgeIds[1]],
\r
191 &meshA->m_edges[facet.m_edgeIds[2]],
\r
194 PfxVector3 sepAxis,pntA,pntB;
\r
196 PfxUInt32 edgeChk =
\r
197 ((edge[0]->m_angleType==SCE_PFX_EDGE_CONVEX)?0x00:0x01) |
\r
198 ((edge[1]->m_angleType==SCE_PFX_EDGE_CONVEX)?0x00:0x02) |
\r
199 ((edge[2]->m_angleType==SCE_PFX_EDGE_CONVEX)?0x00:0x04);
\r
201 pfxContactTriangleSphere(localContacts,selFacets[f],
\r
202 facetNormal,facetPnts[0],facetPnts[1],facetPnts[2],
\r
204 0.5f*SCE_PFX_PI*(edge[0]->m_tilt/255.0f),
\r
205 0.5f*SCE_PFX_PI*(edge[1]->m_tilt/255.0f),
\r
206 0.5f*SCE_PFX_PI*(edge[2]->m_tilt/255.0f),
\r
208 sphereB.m_radius,transformAB.getTranslation());
\r
212 for(int i=0;i<localContacts.getNumContacts();i++) {
\r
213 PfxSubData subData = localContacts.getSubData(i);
\r
215 const PfxFacet &facet = meshA->m_facets[subData.getFacetId()];
\r
217 PfxTriangle triangleA(
\r
218 meshA->m_verts[facet.m_vertIds[0]],
\r
219 meshA->m_verts[facet.m_vertIds[1]],
\r
220 meshA->m_verts[facet.m_vertIds[2]]);
\r
222 PfxFloat s=0.0f,t=0.0f;
\r
223 pfxGetLocalCoords(PfxVector3(localContacts.getLocalPointA(i)),triangleA,s,t);
\r
224 subData.m_type = PfxSubData::MESH_INFO;
\r
225 subData.setFacetLocalS(s);
\r
226 subData.setFacetLocalT(t);
\r
228 contacts.addContactPoint(
\r
229 localContacts.getDistance(i),
\r
230 transformA.getUpper3x3() * localContacts.getNormal(i),
\r
231 localContacts.getLocalPointA(i),
\r
232 transformBA * localContacts.getLocalPointB(i),
\r
236 return contacts.getNumContacts();
\r
238 } //namespace PhysicsEffects
\r