Skip to content

Commit 23c7bbc

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

File tree

1 file changed

+80
-5
lines changed

1 file changed

+80
-5
lines changed

ecere/src/gfx/Display.ec

Lines changed: 80 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,83 @@ 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+
2020+
#ifdef GPU_SKIN
2021+
// We need to apply bone weights for picking
2022+
MeshSkin skin = mesh.skin;
2023+
if(skin)
2024+
{
2025+
Vector3Df * oVertices = mesh.vertices;
2026+
int nVertices = skin.skinVerts.count;
2027+
Array<Matrixf> matBones = mesh.matBones;
2028+
int i;
2029+
2030+
// Lock({ vertices = true });
2031+
vertices = tmpVertices = new Vector3Df[mesh.nVertices];
2032+
2033+
for(i = 0; i < nVertices; i++)
2034+
{
2035+
Vector3Df * vert = &vertices[i];
2036+
SkinVert * sv = &skin.skinVerts[i];
2037+
int j;
2038+
float tw = 0;
2039+
Vector3Df vt { };
2040+
for(j = 0; j < MAX_BONES; j++)
2041+
{
2042+
int b = sv->bones[j];
2043+
if(b != NO_BONE)
2044+
{
2045+
float w = sv->weights[j] / 255.0f;
2046+
Vector3Df v;
2047+
inlineMultMatrix(v, oVertices[i], matBones[b]);
2048+
tw += w;
2049+
vt.x += w * v.x;
2050+
vt.y += w * v.y;
2051+
vt.z += w * v.z;
2052+
}
2053+
else
2054+
break;
2055+
}
2056+
2057+
if(tw)
2058+
{
2059+
tw = 1.0f / tw;
2060+
vert->x = vt.x * tw;
2061+
vert->y = vt.y * tw;
2062+
vert->z = vt.z * tw;
2063+
}
2064+
else
2065+
*vert = oVertices[i];
2066+
}
2067+
2068+
if(mesh.dupVerts)
2069+
{
2070+
int * dv = mesh.dupVerts.array - nVertices;
2071+
int count = nVertices + mesh.dupVerts.count;
2072+
for(i = nVertices; i < count; i++)
2073+
{
2074+
int ix = dv[i];
2075+
vertices[i] = vertices[ix];
2076+
}
2077+
}
2078+
}
2079+
#endif
2080+
20082081
if(rayIntersect != null)
20092082
rayIntersect = { MAXFLOAT, MAXFLOAT, MAXFLOAT };
20102083

@@ -2015,7 +2088,7 @@ private class Display3D : struct
20152088

20162089
for(group = mesh.groups.first; group; group = group.next)
20172090
{
2018-
if(!group.type.hide && PickPrimitivesEx(mesh, (PrimitiveSingle *)&group.type, rayDiff, rayIntersect, groupIX, id))
2091+
if(!group.type.hide && PickPrimitivesEx(mesh, (float *) vertices, (PrimitiveSingle *)&group.type, rayDiff, rayIntersect, groupIX, id))
20192092
{
20202093
result = true;
20212094
if(!intersecting)
@@ -2030,14 +2103,16 @@ private class Display3D : struct
20302103
int c;
20312104
for(c = 0; c < mesh.nPrimitives; c++)
20322105
{
2033-
if(PickPrimitives(mesh, mesh.primitives[c], rayDiff, rayIntersect))
2106+
if(PickPrimitivesEx(mesh, (float *) vertices, mesh.primitives[c], rayDiff, rayIntersect, 0, null))
20342107
{
20352108
result = true;
20362109
if(!intersecting)
20372110
break;
20382111
}
20392112
}
20402113
}
2114+
delete tmpVertices;
2115+
20412116
return result;
20422117
}
20432118
};

0 commit comments

Comments
 (0)