1.4K tris0.19 × 1.48 × 0.19 m
Use it in code
Remix in the editormagic-staff.js · 109 lines
Self-contained ES module — only depends on three. Call the factory and add the group to your scene.
/**
* Magic Staff — Codels 3D model library
* License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
* Triangles: 1,388 · Size (W × H × D): 0.18 × 1.48 × 0.19 m
*
* Usage:
* import { createMagicStaff } from './magic-staff.js';
*
* const model = createMagicStaff();
* model.position.set(0, 0, 0);
* scene.add(model);
*/
import * as THREE from 'three';
// Tube along a smooth curve through the given points.
function tube(path, radius, tubularSegments, radialSegments, closed = false) {
const curve = new THREE.CatmullRomCurve3(path.map(([x, y, z]) => new THREE.Vector3(x, y, z)), closed);
return new THREE.TubeGeometry(curve, tubularSegments, radius, radialSegments, closed);
}
export function createMagicStaff() {
const root = new THREE.Group();
root.name = 'MagicStaff';
// Materials
const woodMat = new THREE.MeshStandardMaterial({ name: 'wood', color: 0x6e4a2e, roughness: 0.85, flatShading: true });
const goldMat = new THREE.MeshStandardMaterial({ name: 'gold', color: 0xd4a84a, roughness: 0.35, metalness: 0.75, flatShading: true });
const glowMat = new THREE.MeshStandardMaterial({ name: 'glow', color: 0x53d6ff, roughness: 0.25, emissive: 0x53d6ff, emissiveIntensity: 0.9 });
const crystalMat = new THREE.MeshStandardMaterial({ name: 'crystal', color: 0x53d6ff, roughness: 0.2, emissive: 0x53d6ff, emissiveIntensity: 0.6, flatShading: true });
// Shared geometries
const sphereGeo = new THREE.SphereGeometry(0.016, 6, 4);
const octahedronGeo = new THREE.OctahedronGeometry(0.012, 0);
// Parts
const ferrule = new THREE.Mesh(new THREE.CylinderGeometry(0.027, 0.02, 0.07, 7), goldMat);
ferrule.name = 'ferrule';
ferrule.position.set(0, 0.035, 0);
root.add(ferrule);
const shaft = new THREE.Mesh(tube([[0.0001, 0.03, 0.0007], [0.0025, 0.1444, 0.0036], [0.007, 0.2589, 0.0059], [0.0112, 0.3733, 0.0066], [0.0104, 0.4878, 0.0042], [0.0063, 0.6022, 0.0007], [0.0007, 0.7167, -0.0028], [-0.005, 0.8311, -0.0059], [-0.0096, 0.9456, -0.0084], [-0.0119, 1.06, -0.0097]], 0.025, 20, 6), woodMat);
shaft.name = 'shaft';
root.add(shaft);
const knot1 = new THREE.Mesh(new THREE.SphereGeometry(0.03, 6, 4), woodMat);
knot1.name = 'knot1';
knot1.position.set(0.0196, 0.57, 0.0017);
knot1.scale.set(1, 1.4, 1);
root.add(knot1);
const knot2 = new THREE.Mesh(new THREE.SphereGeometry(0.026, 6, 4), woodMat);
knot2.name = 'knot2';
knot2.position.set(-0.0191, 0.93, -0.0021);
knot2.scale.set(1, 1.3, 1);
root.add(knot2);
const root1 = new THREE.Mesh(tube([[0.003, 1, -0.0092], [0.0066, 1.046, -0.0019], [0.006, 1.092, 0.0078], [0.0001, 1.138, 0.0176], [-0.011, 1.184, 0.0334], [-0.0325, 1.23, 0.0427], [-0.0602, 1.276, 0.0401], [-0.0878, 1.322, 0.0227], [-0.0995, 1.368, -0.0092], [-0.0676, 1.414, -0.0326], [-0.035, 1.46, -0.0332]], 0.014, 22, 5), woodMat);
root1.name = 'root1';
root.add(root1);
const rootTip1 = new THREE.Mesh(sphereGeo, woodMat);
rootTip1.name = 'rootTip1';
rootTip1.position.set(-0.035, 1.46, -0.0332);
root.add(rootTip1);
const root2 = new THREE.Mesh(tube([[-0.018, 1, 0.003], [-0.0261, 1.046, 0.0024], [-0.0342, 1.092, -0.003], [-0.0397, 1.138, -0.0129], [-0.0478, 1.184, -0.0304], [-0.0451, 1.23, -0.0537], [-0.029, 1.276, -0.0764], [-0.0001, 1.322, -0.0916], [0.0333, 1.368, -0.0858], [0.0376, 1.414, -0.0465], [0.0218, 1.46, -0.018]], 0.014, 22, 5), woodMat);
root2.name = 'root2';
root.add(root2);
const rootTip2 = new THREE.Mesh(sphereGeo, woodMat);
rootTip2.name = 'rootTip2';
rootTip2.position.set(0.0218, 1.46, -0.018);
root.add(rootTip2);
const root3 = new THREE.Mesh(tube([[-0.018, 1, -0.0213], [-0.0135, 1.046, -0.028], [-0.0048, 1.092, -0.0323], [0.0067, 1.138, -0.0322], [0.0258, 1.184, -0.0304], [0.0446, 1.23, -0.0165], [0.0563, 1.276, 0.0089], [0.055, 1.322, 0.0415], [0.0333, 1.368, 0.0675], [-0.003, 1.414, 0.0516], [-0.0198, 1.46, 0.0237]], 0.014, 22, 5), woodMat);
root3.name = 'root3';
root.add(root3);
const rootTip3 = new THREE.Mesh(sphereGeo, woodMat);
rootTip3.name = 'rootTip3';
rootTip3.position.set(-0.0198, 1.46, 0.0237);
root.add(rootTip3);
const collar = new THREE.Mesh(new THREE.CylinderGeometry(0.034, 0.034, 0.05, 8), goldMat);
collar.name = 'collar';
collar.position.set(-0.011, 1.01, -0.0092);
root.add(collar);
const collarRing = new THREE.Mesh(new THREE.CylinderGeometry(0.038, 0.038, 0.012, 8), goldMat);
collarRing.name = 'collarRing';
collarRing.position.set(-0.011, 1.05, -0.0092);
root.add(collarRing);
const orb = new THREE.Mesh(new THREE.SphereGeometry(0.075, 12, 9), glowMat);
orb.name = 'orb';
orb.position.set(-0.011, 1.34, -0.0092);
root.add(orb);
const collarGem1 = new THREE.Mesh(octahedronGeo, crystalMat);
collarGem1.name = 'collarGem1';
collarGem1.position.set(0.0185, 1.01, 0.0078);
root.add(collarGem1);
const collarGem2 = new THREE.Mesh(octahedronGeo, crystalMat);
collarGem2.name = 'collarGem2';
collarGem2.position.set(-0.0404, 1.01, 0.0078);
root.add(collarGem2);
const collarGem3 = new THREE.Mesh(octahedronGeo, crystalMat);
collarGem3.name = 'collarGem3';
collarGem3.position.set(-0.011, 1.01, -0.0432);
root.add(collarGem3);
root.traverse((o) => {
if (o.isMesh) {
o.castShadow = true;
o.receiveShadow = true;
}
});
return root;
}
export default createMagicStaff;
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









