Skip to content

Commit 72f53ab

Browse files
committed
ecere/gfx/3D/Display: Support for picking skinned meshes
1 parent 1625a0f commit 72f53ab

File tree

1 file changed

+82
-5
lines changed

1 file changed

+82
-5
lines changed

ecere/src/gfx/Display.ec

Lines changed: 82 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1697,10 +1697,11 @@ private class Display3D : struct
16971697

16981698
bool PickPrimitives(Mesh mesh, PrimitiveSingle primitive, Vector3D rayDiff, Vector3D rayIntersect)
16991699
{
1700-
return PickPrimitivesEx(mesh, primitive, rayDiff, rayIntersect, 0, null);
1700+
float * vertices = (float *)(mesh.skin && mesh.skin.vertices ? mesh.skin.vertices : mesh.vertices);
1701+
return PickPrimitivesEx(mesh, vertices, primitive, rayDiff, rayIntersect, 0, null);
17011702
}
17021703

1703-
bool PickPrimitivesEx(Mesh mesh, PrimitiveSingle primitive, Vector3D rayDiff, Vector3D rayIntersect,
1704+
bool PickPrimitivesEx(Mesh mesh, float * vertices, PrimitiveSingle primitive, Vector3D rayDiff, Vector3D rayIntersect,
17041705
int groupIx, uint64 * id)
17051706
{
17061707
Plane * planes = localPickingPlanes;
@@ -1720,7 +1721,7 @@ private class Display3D : struct
17201721
Array<MeshPart> parts = mesh.parts;
17211722
int pi;
17221723
int firstPart = 0, lastPart = 0;
1723-
float * vertices = (float *)(mesh.skin && mesh.skin.vertices ? mesh.skin.vertices : mesh.vertices);
1724+
// float * vertices = (float *)(mesh.skin && mesh.skin.vertices ? mesh.skin.vertices : mesh.vertices);
17241725
int vStride = mesh.flags.interleaved ? 8 : 3;
17251726

17261727
if(!vertices || (!indices32 && !indices16)) return false; // Need vertices and indices here...
@@ -2000,11 +2001,85 @@ private class Display3D : struct
20002001
return PickMeshEx(object, rayIntersect, null);
20012002
}
20022003

2004+
#define GPU_SKIN
2005+
static inline void ::inlineMultMatrix(Vector3Df dest, const Vector3Df source, const Matrixf matrix)
2006+
{
2007+
dest.x = (float)(source.x * matrix.m[0][0] + source.y * matrix.m[1][0] + source.z * matrix.m[2][0] + matrix.m[3][0]);
2008+
dest.y = (float)(source.x * matrix.m[0][1] + source.y * matrix.m[1][1] + source.z * matrix.m[2][1] + matrix.m[3][1]);
2009+
dest.z = (float)(source.x * matrix.m[0][2] + source.y * matrix.m[1][2] + source.z * matrix.m[2][2] + matrix.m[3][2]);
2010+
}
2011+
20032012
bool PickMeshEx(Object object, Vector3D rayIntersect, uint64 * id)
20042013
{
20052014
Mesh mesh = object.mesh;
20062015
bool result = false;
20072016
Vector3D rayDiff { MAXFLOAT, MAXFLOAT, MAXFLOAT };
2017+
Vector3Df * vertices = mesh.vertices;
2018+
Vector3Df * tmpVertices = null;
2019+
// We need to apply bone weights for picking
2020+
MeshSkin skin = mesh.skin;
2021+
if(skin)
2022+
{
2023+
#ifdef GPU_SKIN
2024+
Vector3Df * oVertices = mesh.vertices;
2025+
int nVertices = skin.skinVerts.count;
2026+
Array<Matrixf> matBones = mesh.matBones;
2027+
int i;
2028+
2029+
// Lock({ vertices = true });
2030+
vertices = tmpVertices = new Vector3Df[mesh.nVertices];
2031+
2032+
for(i = 0; i < nVertices; i++)
2033+
{
2034+
Vector3Df * vert = &vertices[i];
2035+
SkinVert * sv = &skin.skinVerts[i];
2036+
int j;
2037+
float tw = 0;
2038+
Vector3Df vt { };
2039+
for(j = 0; j < MAX_BONES; j++)
2040+
{
2041+
int b = sv->bones[j];
2042+
if(b != NO_BONE)
2043+
{
2044+
float w = sv->weights[j] / 255.0f;
2045+
Vector3Df v;
2046+
inlineMultMatrix(v, oVertices[i], matBones[b]);
2047+
tw += w;
2048+
vt.x += w * v.x;
2049+
vt.y += w * v.y;
2050+
vt.z += w * v.z;
2051+
}
2052+
else
2053+
break;
2054+
}
2055+
2056+
if(tw)
2057+
{
2058+
tw = 1.0f / tw;
2059+
vert->x = vt.x * tw;
2060+
vert->y = vt.y * tw;
2061+
vert->z = vt.z * tw;
2062+
}
2063+
else
2064+
*vert = oVertices[i];
2065+
}
2066+
2067+
if(mesh.dupVerts)
2068+
{
2069+
int * dv = mesh.dupVerts.array - nVertices;
2070+
int count = nVertices + mesh.dupVerts.count;
2071+
for(i = nVertices; i < count; i++)
2072+
{
2073+
int ix = dv[i];
2074+
vertices[i] = vertices[ix];
2075+
}
2076+
}
2077+
}
2078+
#else
2079+
if(skin.vertices)
2080+
vertices = skin.vertices;
2081+
#endif
2082+
20082083
if(rayIntersect != null)
20092084
rayIntersect = { MAXFLOAT, MAXFLOAT, MAXFLOAT };
20102085

@@ -2015,7 +2090,7 @@ private class Display3D : struct
20152090

20162091
for(group = mesh.groups.first; group; group = group.next)
20172092
{
2018-
if(!group.type.hide && PickPrimitivesEx(mesh, (PrimitiveSingle *)&group.type, rayDiff, rayIntersect, groupIX, id))
2093+
if(!group.type.hide && PickPrimitivesEx(mesh, (float *) vertices, (PrimitiveSingle *)&group.type, rayDiff, rayIntersect, groupIX, id))
20192094
{
20202095
result = true;
20212096
if(!intersecting)
@@ -2030,14 +2105,16 @@ private class Display3D : struct
20302105
int c;
20312106
for(c = 0; c < mesh.nPrimitives; c++)
20322107
{
2033-
if(PickPrimitives(mesh, mesh.primitives[c], rayDiff, rayIntersect))
2108+
if(PickPrimitivesEx(mesh, (float *) vertices, mesh.primitives[c], rayDiff, rayIntersect, 0, null))
20342109
{
20352110
result = true;
20362111
if(!intersecting)
20372112
break;
20382113
}
20392114
}
20402115
}
2116+
delete tmpVertices;
2117+
20412118
return result;
20422119
}
20432120
};

0 commit comments

Comments
 (0)