diff --git a/src/components/GenericShape.tsx b/src/components/GenericShape.tsx
index d040fff2..73e7953c 100644
--- a/src/components/GenericShape.tsx
+++ b/src/components/GenericShape.tsx
@@ -2,6 +2,8 @@ import { Suspense } from "react";
import { useGLTF, useTexture } from "@react-three/drei";
import { BASE_URL, shapeTextureToUrl, shapeToUrl } from "../loaders";
import { setupColor } from "../textureUtils";
+import { filterGeometryByVertexGroups, getHullBoneIndices } from "../meshUtils";
+import { MeshStandardMaterial } from "three";
const FALLBACK_URL = `${BASE_URL}/black.png`;
@@ -13,45 +15,74 @@ export function useStaticShape(shapeName: string) {
return useGLTF(url);
}
-export function ShapeTexture({ materialName }: { materialName: string }) {
- // console.log({ materialName });
- const url = shapeTextureToUrl(materialName, FALLBACK_URL);
+export function ShapeTexture({
+ material,
+}: {
+ material?: MeshStandardMaterial;
+}) {
+ const url = shapeTextureToUrl(material.name, FALLBACK_URL);
const texture = useTexture(url, (texture) => setupColor(texture));
-
- return ;
+ material.map = texture;
+ material.side = 2;
+ material.transparent = true;
+ return ;
}
export function ShapeModel({ shapeName }: { shapeName: string }) {
const { nodes } = useStaticShape(shapeName);
+ let hullBoneIndices = new Set();
+ const skeletonsFound = Object.values(nodes).filter(
+ (node: any) => node.skeleton
+ );
+
+ if (skeletonsFound.length > 0) {
+ const skeleton = (skeletonsFound[0] as any).skeleton;
+ hullBoneIndices = getHullBoneIndices(skeleton);
+ }
+
return (
<>
{Object.entries(nodes)
.filter(
([name, node]: [string, any]) =>
- !node.material || !node.material.name.match(/\.\d+$/)
+ node.material &&
+ node.material.name !== "Unassigned" &&
+ !node.name.match(/^Hulk/i)
)
- .map(([name, node]: [string, any]) => (
-
- {node.material ? (
-
- }
- >
- {Array.isArray(node.material) ? (
- node.material.map((mat, index) => (
-
- ))
- ) : (
-
- )}
-
- ) : null}
-
- ))}
+ .map(([name, node]: [string, any]) => {
+ const geometry = filterGeometryByVertexGroups(
+ node.geometry,
+ hullBoneIndices
+ );
+
+ return (
+
+ {node.material ? (
+
+ }
+ >
+ {Array.isArray(node.material) ? (
+ node.material.map((mat, index) => (
+
+ ))
+ ) : (
+
+ )}
+
+ ) : null}
+
+ );
+ })}
>
);
}
diff --git a/src/meshUtils.ts b/src/meshUtils.ts
new file mode 100644
index 00000000..ea4109ab
--- /dev/null
+++ b/src/meshUtils.ts
@@ -0,0 +1,81 @@
+/**
+ * Extract hull bone indices from a skeleton
+ * @param skeleton - The Three.js skeleton to scan
+ * @returns Set of bone indices for bones matching the hull pattern (starts with "Hulk")
+ */
+export function getHullBoneIndices(skeleton: any): Set {
+ const hullBoneIndices = new Set();
+
+ skeleton.bones.forEach((bone: any, index: number) => {
+ if (bone.name.match(/^Hulk/i)) {
+ hullBoneIndices.add(index);
+ }
+ });
+
+ return hullBoneIndices;
+}
+
+/**
+ * Filter geometry by removing faces influenced by hull bones
+ * @param geometry - The Three.js geometry to filter
+ * @param hullBoneIndices - Set of bone indices that represent hull (collision) geometry
+ * @returns Filtered geometry with hull-influenced faces removed
+ */
+export function filterGeometryByVertexGroups(
+ geometry: any,
+ hullBoneIndices: Set
+): any {
+ // If no hull bones or no skinning data, return original geometry
+ if (hullBoneIndices.size === 0 || !geometry.attributes.skinIndex) {
+ return geometry;
+ }
+
+ const skinIndex = geometry.attributes.skinIndex;
+ const skinWeight = geometry.attributes.skinWeight;
+ const index = geometry.index;
+
+ // Track which vertices are influenced by hull bones
+ const vertexHasHullInfluence = new Array(skinIndex.count).fill(false);
+
+ // Check each vertex's bone influences
+ for (let i = 0; i < skinIndex.count; i++) {
+ for (let j = 0; j < 4; j++) {
+ const boneIndex = skinIndex.array[i * 4 + j];
+ const weight = skinWeight.array[i * 4 + j];
+
+ // If this vertex has significant weight to a hull bone, mark it
+ if (weight > 0.01 && hullBoneIndices.has(boneIndex)) {
+ vertexHasHullInfluence[i] = true;
+ break;
+ }
+ }
+ }
+
+ // Build new index array excluding faces that use hull-influenced vertices
+ if (index) {
+ const newIndices: number[] = [];
+ const indexArray = index.array;
+
+ for (let i = 0; i < indexArray.length; i += 3) {
+ const i0 = indexArray[i];
+ const i1 = indexArray[i + 1];
+ const i2 = indexArray[i + 2];
+
+ // Only keep face if all vertices don't have hull influence
+ if (
+ !vertexHasHullInfluence[i0] &&
+ !vertexHasHullInfluence[i1] &&
+ !vertexHasHullInfluence[i2]
+ ) {
+ newIndices.push(i0, i1, i2);
+ }
+ }
+
+ // Create new geometry with filtered indices
+ const filteredGeometry = geometry.clone();
+ filteredGeometry.setIndex(newIndices);
+ return filteredGeometry;
+ }
+
+ return geometry;
+}