620 tris0.82 × 1.89 × 0.71 m
Use it in code
Remix in the editorsunflower.js · 300 lines
Self-contained ES module — only depends on three. Call the factory and add the group to your scene.
/**
* Sunflower — Codels 3D model library
* License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
* Triangles: 620 · Size (W × H × D): 0.82 × 1.89 × 0.70 m
*
* Usage:
* import { createSunflower } from './sunflower.js';
*
* const model = createSunflower();
* model.position.set(0, 0, 0);
* scene.add(model);
*/
import * as THREE from 'three';
const deg = THREE.MathUtils.degToRad;
// Extrude a 2D outline along Z (centered). bevel = [thickness, size, segments].
function extrude(outline, depth, holes = [], bevel = null) {
const shape = new THREE.Shape(outline.map(([x, y]) => new THREE.Vector2(x, y)));
for (const hole of holes) shape.holes.push(new THREE.Path(hole.map(([x, y]) => new THREE.Vector2(x, y))));
const options = bevel
? { depth, bevelEnabled: true, bevelThickness: bevel[0], bevelSize: bevel[1], bevelSegments: bevel[2] }
: { depth, bevelEnabled: false };
return new THREE.ExtrudeGeometry(shape, options).translate(0, 0, -depth / 2);
}
// 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 createSunflower() {
const root = new THREE.Group();
root.name = 'Sunflower';
// Materials
const stemMat = new THREE.MeshStandardMaterial({ name: 'stem', color: 0x4f8a35, roughness: 0.85, flatShading: true });
const leafMat = new THREE.MeshStandardMaterial({ name: 'leaf', color: 0x4f9136, roughness: 0.85, flatShading: true });
const petalMat = new THREE.MeshStandardMaterial({ name: 'petal', color: 0xf6c22b, roughness: 0.7, flatShading: true });
const petalDeepMat = new THREE.MeshStandardMaterial({ name: 'petalDeep', color: 0xe28d28, roughness: 0.7, flatShading: true });
const discMat = new THREE.MeshStandardMaterial({ name: 'disc', color: 0x5b3a1e, roughness: 0.9, flatShading: true });
const seedsMat = new THREE.MeshStandardMaterial({ name: 'seeds', color: 0x3b2614, roughness: 0.95, flatShading: true });
// Shared geometries
const octahedronGeo = new THREE.OctahedronGeometry(1, 0);
// Parts
const stem = new THREE.Mesh(tube([[0, 0, 0], [0.01, 0.63, -0.01], [-0.005, 1.26, 0], [0, 1.4895, 0.0594], [0, 1.557, 0.1485]], 0.0246, 12, 5), stemMat);
stem.name = 'stem';
root.add(stem);
const leaf1 = new THREE.Mesh(extrude([[0, 0], [0.0895, 0.1295], [0.2486, 0.1541], [0.4077, 0.0925], [0.4972, 0], [0.4077, -0.0925], [0.2486, -0.1541], [0.0895, -0.1295]], 0.01), leafMat);
leaf1.name = 'leaf1';
leaf1.position.set(0, 0.34, 0);
leaf1.rotation.set(deg(94.7281), deg(-23.647), deg(11.6513));
root.add(leaf1);
const leaf2 = new THREE.Mesh(extrude([[0, 0], [0.0827, 0.1197], [0.2298, 0.1425], [0.3768, 0.0855], [0.4595, 0], [0.3768, -0.0855], [0.2298, -0.1425], [0.0827, -0.1197]], 0.01), leafMat);
leaf2.name = 'leaf2';
leaf2.position.set(0, 0.5467, 0);
leaf2.rotation.set(deg(78.138), deg(23.4358), deg(-152.1611));
root.add(leaf2);
const leaf3 = new THREE.Mesh(extrude([[0, 0], [0.0759, 0.1099], [0.2109, 0.1308], [0.3459, 0.0785], [0.4219, 0], [0.3459, -0.0785], [0.2109, -0.1308], [0.0759, -0.1099]], 0.01), leafMat);
leaf3.name = 'leaf3';
leaf3.position.set(0, 0.7533, 0);
leaf3.rotation.set(deg(109.6158), deg(-5.3579), deg(75.3182));
root.add(leaf3);
const leaf4 = new THREE.Mesh(extrude([[0, 0], [0.0692, 0.1], [0.1921, 0.1191], [0.315, 0.0715], [0.3842, 0], [0.315, -0.0715], [0.1921, -0.1191], [0.0692, -0.1]], 0.01), leafMat);
leaf4.name = 'leaf4';
leaf4.position.set(0, 0.96, 0);
leaf4.rotation.set(deg(58.3634), deg(5.7108), deg(-99.1749));
root.add(leaf4);
const leaf5 = new THREE.Mesh(extrude([[0, 0], [0.0624, 0.0902], [0.1733, 0.1074], [0.2842, 0.0645], [0.3465, 0], [0.2842, -0.0645], [0.1733, -0.1074], [0.0624, -0.0902]], 0.01), leafMat);
leaf5.name = 'leaf5';
leaf5.position.set(0, 1.1667, 0);
leaf5.rotation.set(deg(114.8541), deg(13.7648), deg(117.1882));
root.add(leaf5);
const head = new THREE.Group();
head.name = 'head';
head.position.set(0, 1.5894, 0.1809);
head.rotation.set(deg(22), 0, 0);
root.add(head);
const calyx = new THREE.Mesh(new THREE.ConeGeometry(0.2106, 0.1485, 10), stemMat);
calyx.name = 'calyx';
calyx.position.set(0, 0, -0.081);
calyx.rotation.set(deg(-90), 0, 0);
head.add(calyx);
const disc = new THREE.Mesh(new THREE.CylinderGeometry(0.1674, 0.1836, 0.0486, 12), discMat);
disc.name = 'disc';
disc.rotation.set(deg(90), 0, 0);
head.add(disc);
const seeds = new THREE.Mesh(new THREE.SphereGeometry(0.1512, 12, 2, 0, Math.PI * 2, 0, Math.PI / 2), seedsMat);
seeds.name = 'seeds';
seeds.position.set(0, 0, 0.0216);
seeds.rotation.set(deg(90), 0, 0);
seeds.scale.set(1, 0.32, 1);
head.add(seeds);
const petalA1 = new THREE.Mesh(octahedronGeo, petalMat);
petalA1.name = 'petalA1';
petalA1.position.set(0.2543, 0.0109, 0.0296);
petalA1.rotation.set(deg(0.7817), deg(-17.728), deg(2.5658));
petalA1.scale.set(0.0972, 0.0351, 0.0095);
head.add(petalA1);
const petalA2 = new THREE.Mesh(octahedronGeo, petalMat);
petalA2.name = 'petalA2';
petalA2.position.set(0.2375, 0.0917, 0.0296);
petalA2.rotation.set(deg(6.5757), deg(-16.5178), deg(22.0701));
petalA2.scale.set(0.0972, 0.0351, 0.0095);
head.add(petalA2);
const petalA3 = new THREE.Mesh(octahedronGeo, petalMat);
petalA3.name = 'petalA3';
petalA3.position.set(0.1798, 0.1802, 0.0296);
petalA3.rotation.set(deg(12.7616), deg(-12.4333), deg(46.4505));
petalA3.scale.set(0.0972, 0.0351, 0.0095);
head.add(petalA3);
const petalA4 = new THREE.Mesh(octahedronGeo, petalMat);
petalA4.name = 'petalA4';
petalA4.position.set(0.0903, 0.238, 0.0296);
petalA4.rotation.set(deg(16.6556), deg(-6.2094), deg(70.123));
petalA4.scale.set(0.0972, 0.0351, 0.0095);
head.add(petalA4);
const petalA5 = new THREE.Mesh(octahedronGeo, petalMat);
petalA5.name = 'petalA5';
petalA5.position.set(0.0031, 0.2546, 0.0296);
petalA5.rotation.set(deg(17.7434), deg(-0.2134), deg(89.333));
petalA5.scale.set(0.0972, 0.0351, 0.0095);
head.add(petalA5);
const petalA6 = new THREE.Mesh(octahedronGeo, petalMat);
petalA6.name = 'petalA6';
petalA6.position.set(-0.1073, 0.2308, 0.0296);
petalA6.rotation.set(deg(16.1812), deg(7.3824), deg(113.8842));
petalA6.scale.set(0.0972, 0.0351, 0.0095);
head.add(petalA6);
const petalA7 = new THREE.Mesh(octahedronGeo, petalMat);
petalA7.name = 'petalA7';
petalA7.position.set(-0.1775, 0.1825, 0.0296);
petalA7.rotation.set(deg(12.9221), deg(12.2662), deg(132.799));
petalA7.scale.set(0.0972, 0.0351, 0.0095);
head.add(petalA7);
const petalA8 = new THREE.Mesh(octahedronGeo, petalMat);
petalA8.name = 'petalA8';
petalA8.position.set(-0.2361, 0.0952, 0.0296);
petalA8.rotation.set(deg(6.8237), deg(16.4193), deg(157.0551));
petalA8.scale.set(0.0972, 0.0351, 0.0095);
head.add(petalA8);
const petalA9 = new THREE.Mesh(octahedronGeo, petalMat);
petalA9.name = 'petalA9';
petalA9.position.set(-0.2544, -0.0088, 0.0296);
petalA9.rotation.set(deg(-0.6363), deg(17.7336), deg(-177.9119));
petalA9.scale.set(0.0972, 0.0351, 0.0095);
head.add(petalA9);
const petalA10 = new THREE.Mesh(octahedronGeo, petalMat);
petalA10.name = 'petalA10';
petalA10.position.set(-0.2339, -0.1005, 0.0296);
petalA10.rotation.set(deg(-7.2002), deg(16.2614), deg(-155.7172));
petalA10.scale.set(0.0972, 0.0351, 0.0095);
head.add(petalA10);
const petalA11 = new THREE.Mesh(octahedronGeo, petalMat);
petalA11.name = 'petalA11';
petalA11.position.set(-0.1782, -0.1818, 0.0296);
petalA11.rotation.set(deg(-12.8757), deg(12.315), deg(-133.0173));
petalA11.scale.set(0.0972, 0.0351, 0.0095);
head.add(petalA11);
const petalA12 = new THREE.Mesh(octahedronGeo, petalMat);
petalA12.name = 'petalA12';
petalA12.position.set(-0.102, -0.2332, 0.0296);
petalA12.rotation.set(deg(-16.3401), deg(7.0156), deg(-112.6168));
petalA12.scale.set(0.0972, 0.0351, 0.0095);
head.add(petalA12);
const petalA13 = new THREE.Mesh(octahedronGeo, petalMat);
petalA13.name = 'petalA13';
petalA13.position.set(0.0064, -0.2545, 0.0296);
petalA13.rotation.set(deg(-17.7393), deg(-0.4422), deg(-88.6178));
petalA13.scale.set(0.0972, 0.0351, 0.0095);
head.add(petalA13);
const petalA14 = new THREE.Mesh(octahedronGeo, petalMat);
petalA14.name = 'petalA14';
petalA14.position.set(0.0996, -0.2343, 0.0296);
petalA14.rotation.set(deg(-16.4085), deg(-6.8502), deg(-67.9501));
petalA14.scale.set(0.0972, 0.0351, 0.0095);
head.add(petalA14);
const petalA15 = new THREE.Mesh(octahedronGeo, petalMat);
petalA15.name = 'petalA15';
petalA15.position.set(0.1807, -0.1793, 0.0296);
petalA15.rotation.set(deg(-12.7), deg(-12.4963), deg(-46.1648));
petalA15.scale.set(0.0972, 0.0351, 0.0095);
head.add(petalA15);
const petalA16 = new THREE.Mesh(octahedronGeo, petalMat);
petalA16.name = 'petalA16';
petalA16.position.set(0.2378, -0.0909, 0.0296);
petalA16.rotation.set(deg(-6.5184), deg(-16.54), deg(-21.8684));
petalA16.scale.set(0.0972, 0.0351, 0.0095);
head.add(petalA16);
const petalB1 = new THREE.Mesh(octahedronGeo, petalDeepMat);
petalB1.name = 'petalB1';
petalB1.position.set(0.238, 0.0571, -0.0038);
petalB1.rotation.set(deg(2.0032), deg(-8.2939), deg(13.6292));
petalB1.scale.set(0.0837, 0.0405, 0.0095);
head.add(petalB1);
const petalB2 = new THREE.Mesh(octahedronGeo, petalDeepMat);
petalB2.name = 'petalB2';
petalB2.position.set(0.2077, 0.1295, -0.0038);
petalB2.rotation.set(deg(4.5372), deg(-7.2317), deg(32.2268));
petalB2.scale.set(0.0837, 0.0405, 0.0095);
head.add(petalB2);
const petalB3 = new THREE.Mesh(octahedronGeo, petalDeepMat);
petalB3.name = 'petalB3';
petalB3.position.set(0.1392, 0.2013, -0.0038);
petalB3.rotation.set(deg(7.0327), deg(-4.8408), deg(55.6261));
petalB3.scale.set(0.0837, 0.0405, 0.0095);
head.add(petalB3);
const petalB4 = new THREE.Mesh(octahedronGeo, petalDeepMat);
petalB4.name = 'petalB4';
petalB4.position.set(0.0571, 0.238, -0.0038);
petalB4.rotation.set(deg(8.299), deg(-1.982), deg(76.6614));
petalB4.scale.set(0.0837, 0.0405, 0.0095);
head.add(petalB4);
const petalB5 = new THREE.Mesh(octahedronGeo, petalDeepMat);
petalB5.name = 'petalB5';
petalB5.position.set(-0.0452, 0.2406, -0.0038);
petalB5.rotation.set(deg(8.3863), deg(1.5689), deg(100.5208));
petalB5.scale.set(0.0837, 0.0405, 0.0095);
head.add(petalB5);
const petalB6 = new THREE.Mesh(octahedronGeo, petalDeepMat);
petalB6.name = 'petalB6';
petalB6.position.set(-0.1325, 0.2058, -0.0038);
petalB6.rotation.set(deg(7.1885), deg(4.6055), deg(122.4821));
petalB6.scale.set(0.0837, 0.0405, 0.0095);
head.add(petalB6);
const petalB7 = new THREE.Mesh(octahedronGeo, petalDeepMat);
petalB7.name = 'petalB7';
petalB7.position.set(-0.1977, 0.1443, -0.0038);
petalB7.rotation.set(deg(5.0531), deg(6.8821), deg(143.5752));
petalB7.scale.set(0.0837, 0.0405, 0.0095);
head.add(petalB7);
const petalB8 = new THREE.Mesh(octahedronGeo, petalDeepMat);
petalB8.name = 'petalB8';
petalB8.position.set(-0.2381, 0.0569, -0.0038);
petalB8.rotation.set(deg(1.9962), deg(8.2956), deg(166.419));
petalB8.scale.set(0.0837, 0.0405, 0.0095);
head.add(petalB8);
const petalB9 = new THREE.Mesh(octahedronGeo, petalDeepMat);
petalB9.name = 'petalB9';
petalB9.position.set(-0.2375, -0.0591, -0.0038);
petalB9.rotation.set(deg(-2.075), deg(8.2764), deg(-165.8724));
petalB9.scale.set(0.0837, 0.0405, 0.0095);
head.add(petalB9);
const petalB10 = new THREE.Mesh(octahedronGeo, petalDeepMat);
petalB10.name = 'petalB10';
petalB10.position.set(-0.2081, -0.1289, -0.0038);
petalB10.rotation.set(deg(-4.5168), deg(7.2444), deg(-147.935));
petalB10.scale.set(0.0837, 0.0405, 0.0095);
head.add(petalB10);
const petalB11 = new THREE.Mesh(octahedronGeo, petalDeepMat);
petalB11.name = 'petalB11';
petalB11.position.set(-0.1328, -0.2056, -0.0038);
petalB11.rotation.set(deg(-7.1819), deg(4.6158), deg(-122.5637));
petalB11.scale.set(0.0837, 0.0405, 0.0095);
head.add(petalB11);
const petalB12 = new THREE.Mesh(octahedronGeo, petalDeepMat);
petalB12.name = 'petalB12';
petalB12.position.set(-0.0596, -0.2374, -0.0038);
petalB12.rotation.set(deg(-8.2779), deg(2.0687), deg(-103.9343));
petalB12.scale.set(0.0837, 0.0405, 0.0095);
head.add(petalB12);
const petalB13 = new THREE.Mesh(octahedronGeo, petalDeepMat);
petalB13.name = 'petalB13';
petalB13.position.set(0.0584, -0.2377, -0.0038);
petalB13.rotation.set(deg(-8.2878), deg(-2.0288), deg(-76.3402));
petalB13.scale.set(0.0837, 0.0405, 0.0095);
head.add(petalB13);
const petalB14 = new THREE.Mesh(octahedronGeo, petalDeepMat);
petalB14.name = 'petalB14';
petalB14.position.set(0.1354, -0.2039, -0.0038);
petalB14.rotation.set(deg(-7.1235), deg(-4.7058), deg(-56.7169));
petalB14.scale.set(0.0837, 0.0405, 0.0095);
head.add(petalB14);
const petalB15 = new THREE.Mesh(octahedronGeo, petalDeepMat);
petalB15.name = 'petalB15';
petalB15.position.set(0.2072, -0.1303, -0.0038);
petalB15.rotation.set(deg(-4.5651), deg(-7.2141), deg(-32.4492));
petalB15.scale.set(0.0837, 0.0405, 0.0095);
head.add(petalB15);
const petalB16 = new THREE.Mesh(octahedronGeo, petalDeepMat);
petalB16.name = 'petalB16';
petalB16.position.set(0.2416, -0.0394, -0.0038);
petalB16.rotation.set(deg(-1.3847), deg(-8.4185), deg(-9.3756));
petalB16.scale.set(0.0837, 0.0405, 0.0095);
head.add(petalB16);
root.traverse((o) => {
if (o.isMesh) {
o.castShadow = true;
o.receiveShadow = true;
}
});
return root;
}
export default createSunflower;
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









