696 tris1.57 × 1.58 × 1.58 m
Use it in code
Remix in the editorspiked-ball.js · 178 lines
Self-contained ES module — only depends on three. Call the factory and add the group to your scene.
/**
* Spiked Ball — Codels 3D model library
* License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the model (it floats — pickups, planets)
* Triangles: 696 · Size (W × H × D): 1.57 × 1.58 × 1.57 m
*
* Usage:
* import { createSpikedBall } from './spiked-ball.js';
*
* const model = createSpikedBall();
* model.position.set(0, 0, 0);
* scene.add(model);
*/
import * as THREE from 'three';
const deg = THREE.MathUtils.degToRad;
export function createSpikedBall() {
const root = new THREE.Group();
root.name = 'SpikedBall';
// Materials
const ballMat = new THREE.MeshStandardMaterial({ name: 'ball', color: 0x3c414d, roughness: 0.55, metalness: 0.45, flatShading: true });
const bandMat = new THREE.MeshStandardMaterial({ name: 'band', color: 0x262a32, roughness: 0.6, metalness: 0.5, flatShading: true });
const spikeMat = new THREE.MeshStandardMaterial({ name: 'spike', color: 0xd9dde4, roughness: 0.25, metalness: 0.8, flatShading: true });
// Shared geometries
const coneGeo = new THREE.ConeGeometry(0.11, 0.35, 6);
// Parts
const ball = new THREE.Mesh(new THREE.SphereGeometry(0.5, 12, 9), ballMat);
ball.name = 'ball';
root.add(ball);
const band = new THREE.Mesh(new THREE.TorusGeometry(0.495, 0.03, 4, 24), bandMat);
band.name = 'band';
band.rotation.set(deg(90), 0, 0);
root.add(band);
const spike1 = new THREE.Mesh(coneGeo, spikeMat);
spike1.name = 'spike1';
spike1.position.set(0.1772, 0.6202, 0);
spike1.rotation.set(0, 0, deg(-15.9424));
root.add(spike1);
const spike2 = new THREE.Mesh(coneGeo, spikeMat);
spike2.name = 'spike2';
spike2.position.set(-0.2218, 0.5706, 0.2032);
spike2.rotation.set(deg(19.5999), 0, deg(20.1117));
root.add(spike2);
const spike3 = new THREE.Mesh(coneGeo, spikeMat);
spike3.name = 'spike3';
spike3.position.set(0.0332, 0.521, -0.3788);
spike3.rotation.set(deg(-36.0243), 0, deg(-2.9547));
root.add(spike3);
const spike4 = new THREE.Mesh(coneGeo, spikeMat);
spike4.name = 'spike4';
spike4.position.set(0.2679, 0.4713, 0.3494);
spike4.rotation.set(deg(36.5502), 0, deg(-24.5404));
root.add(spike4);
const spike5 = new THREE.Mesh(coneGeo, spikeMat);
spike5.name = 'spike5';
spike5.position.set(-0.4806, 0.4217, -0.085);
spike5.rotation.set(deg(-11.396), 0, deg(48.1644));
root.add(spike5);
const spike6 = new THREE.Mesh(coneGeo, spikeMat);
spike6.name = 'spike6';
spike6.position.set(0.4445, 0.3721, -0.2828);
spike6.rotation.set(deg(-37.2309), 0, deg(-43.5651));
root.add(spike6);
const spike7 = new THREE.Mesh(coneGeo, spikeMat);
spike7.name = 'spike7';
spike7.position.set(-0.145, 0.3225, 0.5394);
spike7.rotation.set(deg(59.127), 0, deg(12.9925));
root.add(spike7);
const spike8 = new THREE.Mesh(coneGeo, spikeMat);
spike8.name = 'spike8';
spike8.position.set(-0.2694, 0.2729, -0.5187);
spike8.rotation.set(deg(-62.2493), 0, deg(24.6847));
root.add(spike8);
const spike9 = new THREE.Mesh(coneGeo, spikeMat);
spike9.name = 'spike9';
spike9.position.set(0.5684, 0.2233, 0.2076);
spike9.rotation.set(deg(42.9147), 0, deg(-61.7936));
root.add(spike9);
const spike10 = new THREE.Mesh(coneGeo, spikeMat);
spike10.name = 'spike10';
spike10.position.set(-0.5742, 0.1737, 0.237);
spike10.rotation.set(deg(53.7711), 0, deg(62.9002));
root.add(spike10);
const spike11 = new THREE.Mesh(coneGeo, spikeMat);
spike11.name = 'spike11';
spike11.position.set(0.2683, 0.124, -0.5733);
spike11.rotation.set(deg(-77.7916), 0, deg(-24.5782));
root.add(spike11);
const spike12 = new THREE.Mesh(coneGeo, spikeMat);
spike12.name = 'spike12';
spike12.position.set(0.1917, 0.0744, 0.6113);
spike12.rotation.set(deg(83.0589), 0, deg(-17.2946));
root.add(spike12);
const spike13 = new THREE.Mesh(coneGeo, spikeMat);
spike13.name = 'spike13';
spike13.position.set(-0.5576, 0.0248, -0.3232);
spike13.rotation.set(deg(-85.6104), 0, deg(59.8338));
root.add(spike13);
const spike14 = new THREE.Mesh(coneGeo, spikeMat);
spike14.name = 'spike14';
spike14.position.set(0.6295, -0.0248, -0.1384);
spike14.rotation.set(deg(-100.1627), 0, deg(-77.4096));
root.add(spike14);
const spike15 = new THREE.Mesh(coneGeo, spikeMat);
spike15.name = 'spike15';
spike15.position.set(-0.3685, -0.0744, 0.5241);
spike15.rotation.set(deg(98.0817), 0, deg(34.8401));
root.add(spike15);
const spike16 = new THREE.Mesh(coneGeo, spikeMat);
spike16.name = 'spike16';
spike16.position.set(-0.0813, -0.124, -0.6277);
spike16.rotation.set(deg(-101.1779), 0, deg(7.245));
root.add(spike16);
const spike17 = new THREE.Mesh(coneGeo, spikeMat);
spike17.name = 'spike17';
spike17.position.set(0.475, -0.1737, 0.4003);
spike17.rotation.set(deg(113.4506), 0, deg(-47.4269));
root.add(spike17);
const spike18 = new THREE.Mesh(coneGeo, spikeMat);
spike18.name = 'spike18';
spike18.position.set(-0.6046, -0.2233, 0.025);
spike18.rotation.set(deg(173.6104), 0, deg(69.6156));
root.add(spike18);
const spike19 = new THREE.Mesh(coneGeo, spikeMat);
spike19.name = 'spike19';
spike19.position.set(0.4143, -0.2729, -0.4122);
spike19.rotation.set(deg(-123.5024), 0, deg(-39.961));
root.add(spike19);
const spike20 = new THREE.Mesh(coneGeo, spikeMat);
spike20.name = 'spike20';
spike20.position.set(-0.0258, -0.3225, 0.558);
spike20.rotation.set(deg(120.0265), 0, deg(2.2926));
root.add(spike20);
const spike21 = new THREE.Mesh(coneGeo, spikeMat);
spike21.name = 'spike21';
spike21.position.set(-0.3375, -0.3721, -0.4045);
spike21.rotation.set(deg(-132.6125), 0, deg(31.5559));
root.add(spike21);
const spike22 = new THREE.Mesh(coneGeo, spikeMat);
spike22.name = 'spike22';
spike22.position.set(0.4837, -0.4217, 0.0651);
spike22.rotation.set(deg(171.228), 0, deg(-48.5792));
root.add(spike22);
const spike23 = new THREE.Mesh(coneGeo, spikeMat);
spike23.name = 'spike23';
spike23.position.set(-0.3614, -0.4713, 0.2515);
spike23.rotation.set(deg(151.9199), 0, deg(34.0792));
root.add(spike23);
const spike24 = new THREE.Mesh(coneGeo, spikeMat);
spike24.name = 'spike24';
spike24.position.set(0.0835, -0.521, -0.371);
spike24.rotation.set(deg(-144.542), 0, deg(-7.4353));
root.add(spike24);
const spike25 = new THREE.Mesh(coneGeo, spikeMat);
spike25.name = 'spike25';
spike25.position.set(0.1495, -0.5706, 0.261);
spike25.rotation.set(deg(155.4218), 0, deg(-13.4058));
root.add(spike25);
const spike26 = new THREE.Mesh(coneGeo, spikeMat);
spike26.name = 'spike26';
spike26.position.set(-0.1688, -0.6202, -0.0538);
spike26.rotation.set(deg(-175.038), 0, deg(15.1696));
root.add(spike26);
root.traverse((o) => {
if (o.isMesh) {
o.castShadow = true;
o.receiveShadow = true;
}
});
return root;
}
export default createSpikedBall;
Ratings & comments
0 comments
No comments yet. Share how you used this model or what could be better.
Related models
Same category or similar tags









