I’m trying to create a 3d rugby ball using ThreeJS and RTF and I’m struggling to create 4 faces on the ball where two subsequent faces on the ball will have two different images. Something similar to this.
I have been able to create the geometry and add one image on one face. But the other 3 images don’t show up on the geometry.
This is the code that I have so far:
import React, { Suspense } from "react";
import { Canvas, useLoader } from "@react-three/fiber";
import {
OrbitControls,
useProgress,
Html,
} from "@react-three/drei";
import { OBJLoader } from "three/examples/jsm/loaders/OBJLoader";
import * as THREE from "three";
const RugbyBall: React.FC = () => {
// Load textures
const one = useLoader(THREE.TextureLoader, "/images/one.jpg");
const two = useLoader(THREE.TextureLoader, "/images/two.jpg");
const texture = useLoader(THREE.TextureLoader, "/images/texture.jpg");
// Create materials
const oneMaterial = new THREE.MeshPhysicalMaterial({
map: one,
bumpMap: texture,
bumpScale: 1,
roughness: 1,
metalness: 0,
// side: THREE.FrontSide,
});
const twoMaterial = new THREE.MeshPhysicalMaterial({
map: two,
bumpMap: texture,
bumpScale: 1,
roughness: 1,
metalness: 0,
// side: THREE.BackSide,
});
// Create the Sphere Geometry (a simple sphere)
const radius = 50; // Size of the ball
const widthSegments = 64; // Number of horizontal segments
const heightSegments = 64; // Number of vertical segments
const sphereGeometry = new THREE.SphereGeometry(
radius,
widthSegments,
heightSegments
);
// Scale the sphere to elongate it into a rugby ball shape
sphereGeometry.scale(1, 1.8, 1);
// Clear any pre-existing groups
sphereGeometry.clearGroups();
if (sphereGeometry.index && sphereGeometry.index.count) {
console.log("sphereGeometry.index.count: ", sphereGeometry.index.count);
// Split the sphere into two hemispheres
const middle = Math.floor(sphereGeometry.index.count / 2);
// Add group for the top hemisphere (one)
for (let i = 0; i < middle; i++) {
sphereGeometry.addGroup(i * 3, 3, 0); // Apply one material to the first half
}
// Add group for the bottom hemisphere (two)
for (let i = middle; i < sphereGeometry.index.count / 3; i++) {
sphereGeometry.addGroup(i * 3, 3, 1); // Apply two material to the second half
}
}
// Create the mesh and apply the materials
const materials = [oneMaterial, twoMaterial]; // Two materials: one and two
const rugbyBall = new THREE.Mesh(sphereGeometry, materials);
return <primitive object={rugbyBall} position={[0, 0, 0]} scale={2.5} rotation={[-(Math.PI / 2), 0, 0]} />;
};
const Loader = () => {
const { progress } = useProgress();
return <Html center>{Math.round(progress)}% loaded</Html>;
};
// Main Scene Component
const Scene = () => {
return (
<Canvas
camera={{ position: [0, 0, 500], fov: 75 }}
style={{
width: "100vw",
height: "30vh",
backgroundColor: "red",
}}
>
<Suspense fallback={<Loader />}>
{/* Lighting */}
<ambientLight intensity={1} />
<directionalLight position={[0, 1, 0]} intensity={2} />
{/* 3D Model */}
<RugbyBall />
{/* Controls */}
<OrbitControls autoRotate autoRotateSpeed={2} enableDamping dampingFactor={0.1} />
</Suspense>
</Canvas>
);
};
export default Scene;