592 tris3.42 × 2.14 × 1.89 m
Use it in code
Remix in the editorsolar-panel.js · 213 lines
Self-contained ES module — only depends on three. Call the factory and add the group to your scene.
/**
* Solar Panel Array — Codels 3D model library
* License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
* Triangles: 592 · Size (W × H × D): 3.42 × 2.14 × 1.89 m
*
* Usage:
* import { createSolarPanel } from './solar-panel.js';
*
* const model = createSolarPanel();
* model.position.set(0, 0, 0);
* scene.add(model);
*/
import * as THREE from 'three';
const deg = THREE.MathUtils.degToRad;
// 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 createSolarPanel() {
const root = new THREE.Group();
root.name = 'SolarPanel';
// Materials
const cellsMat = new THREE.MeshStandardMaterial({ name: 'cells', color: 0x21427e, roughness: 0.22, metalness: 0.45, flatShading: true });
const frameMat = new THREE.MeshStandardMaterial({ name: 'frame', color: 0xc9ced5, roughness: 0.35, metalness: 0.6, flatShading: true });
const steelMat = new THREE.MeshStandardMaterial({ name: 'steel', color: 0x6f7780, roughness: 0.5, metalness: 0.55, flatShading: true });
const concreteMat = new THREE.MeshStandardMaterial({ name: 'concrete', color: 0xa7a299, roughness: 0.95, flatShading: true });
const ledMat = new THREE.MeshStandardMaterial({ name: 'led', color: 0x5dff7a, roughness: 0.4, emissive: 0x3dff5f, emissiveIntensity: 1.6, flatShading: true });
// Shared geometries
const boxGeo = new THREE.BoxGeometry(0.5, 0.25, 0.5);
const boxGeo2 = new THREE.BoxGeometry(0.13, 1.12, 0.13);
const boxGeo3 = new THREE.BoxGeometry(0.2, 0.16, 0.2);
const boxGeo4 = new THREE.BoxGeometry(0.06, 0.08, 1.932);
const boxGeo5 = new THREE.BoxGeometry(1.62, 0.05, 2.1);
const boxGeo6 = new THREE.BoxGeometry(1.54, 0.04, 2.02);
const boxGeo7 = new THREE.BoxGeometry(0.014, 0.012, 2.02);
const boxGeo8 = new THREE.BoxGeometry(1.54, 0.012, 0.014);
const boxGeo9 = new THREE.BoxGeometry(0.04, 0.035, 2.1);
const boxGeo10 = new THREE.BoxGeometry(1.62, 0.035, 0.04);
// Parts
const stand = new THREE.Group();
stand.name = 'stand';
root.add(stand);
const footing1 = new THREE.Mesh(boxGeo, concreteMat);
footing1.name = 'footing1';
footing1.position.set(-1.36, 0.125, 0);
stand.add(footing1);
const post1 = new THREE.Mesh(boxGeo2, steelMat);
post1.name = 'post1';
post1.position.set(-1.36, 0.81, 0);
stand.add(post1);
const bearing1 = new THREE.Mesh(boxGeo3, steelMat);
bearing1.name = 'bearing1';
bearing1.position.set(-1.36, 1.39, 0);
stand.add(bearing1);
const footing2 = new THREE.Mesh(boxGeo, concreteMat);
footing2.name = 'footing2';
footing2.position.set(1.36, 0.125, 0);
stand.add(footing2);
const post2 = new THREE.Mesh(boxGeo2, steelMat);
post2.name = 'post2';
post2.position.set(1.36, 0.81, 0);
stand.add(post2);
const bearing2 = new THREE.Mesh(boxGeo3, steelMat);
bearing2.name = 'bearing2';
bearing2.position.set(1.36, 1.39, 0);
stand.add(bearing2);
const junctionBox = new THREE.Mesh(new THREE.BoxGeometry(0.26, 0.32, 0.12), frameMat);
junctionBox.name = 'junctionBox';
junctionBox.position.set(-1.36, 0.85, 0.13);
stand.add(junctionBox);
const statusLight = new THREE.Mesh(new THREE.BoxGeometry(0.05, 0.05, 0.02), ledMat);
statusLight.name = 'statusLight';
statusLight.position.set(-1.29, 0.94, 0.195);
stand.add(statusLight);
const cable = new THREE.Mesh(tube([[-1.42, 0.69, 0.13], [-1.48, 0.45, 0.2], [-1.56, 0.26, 0.3], [-1.66, 0.02, 0.38]], 0.022, 8, 5), steelMat);
cable.name = 'cable';
stand.add(cable);
const panelArray = new THREE.Group();
panelArray.name = 'panelArray';
panelArray.position.set(0, 1.45, 0);
panelArray.rotation.set(deg(28), 0, 0);
root.add(panelArray);
const torqueTube = new THREE.Mesh(new THREE.CylinderGeometry(0.07, 0.07, 3.42, 8), steelMat);
torqueTube.name = 'torqueTube';
torqueTube.rotation.set(0, 0, deg(90));
panelArray.add(torqueTube);
const panel1 = new THREE.Group();
panel1.name = 'panel1';
panel1.position.set(-0.85, 0, 0);
panelArray.add(panel1);
const box14 = new THREE.Mesh(boxGeo4, steelMat);
box14.position.set(-0.486, 0.1, 0);
panel1.add(box14);
const box15 = new THREE.Mesh(boxGeo4, steelMat);
box15.position.set(0.486, 0.1, 0);
panel1.add(box15);
const frame = new THREE.Mesh(boxGeo5, frameMat);
frame.name = 'frame';
frame.position.set(0, 0.165, 0);
panel1.add(frame);
const cells = new THREE.Mesh(boxGeo6, cellsMat);
cells.name = 'cells';
cells.position.set(0, 0.19, 0);
panel1.add(cells);
const box18 = new THREE.Mesh(boxGeo7, frameMat);
box18.position.set(-0.385, 0.214, 0);
panel1.add(box18);
const box19 = new THREE.Mesh(boxGeo7, frameMat);
box19.position.set(0, 0.214, 0);
panel1.add(box19);
const box20 = new THREE.Mesh(boxGeo7, frameMat);
box20.position.set(0.385, 0.214, 0);
panel1.add(box20);
const box21 = new THREE.Mesh(boxGeo8, frameMat);
box21.position.set(0, 0.214, -0.6733);
panel1.add(box21);
const box22 = new THREE.Mesh(boxGeo8, frameMat);
box22.position.set(0, 0.214, -0.3367);
panel1.add(box22);
const box23 = new THREE.Mesh(boxGeo8, frameMat);
box23.position.set(0, 0.214, 0);
panel1.add(box23);
const box24 = new THREE.Mesh(boxGeo8, frameMat);
box24.position.set(0, 0.214, 0.3367);
panel1.add(box24);
const box25 = new THREE.Mesh(boxGeo8, frameMat);
box25.position.set(0, 0.214, 0.6733);
panel1.add(box25);
const box26 = new THREE.Mesh(boxGeo9, frameMat);
box26.position.set(-0.79, 0.205, 0);
panel1.add(box26);
const box27 = new THREE.Mesh(boxGeo10, frameMat);
box27.position.set(0, 0.205, -1.03);
panel1.add(box27);
const box28 = new THREE.Mesh(boxGeo9, frameMat);
box28.position.set(0.79, 0.205, 0);
panel1.add(box28);
const box29 = new THREE.Mesh(boxGeo10, frameMat);
box29.position.set(0, 0.205, 1.03);
panel1.add(box29);
const panel2 = new THREE.Group();
panel2.name = 'panel2';
panel2.position.set(0.85, 0, 0);
panelArray.add(panel2);
const box31 = new THREE.Mesh(boxGeo4, steelMat);
box31.position.set(-0.486, 0.1, 0);
panel2.add(box31);
const box32 = new THREE.Mesh(boxGeo4, steelMat);
box32.position.set(0.486, 0.1, 0);
panel2.add(box32);
const frame2 = new THREE.Mesh(boxGeo5, frameMat);
frame2.name = 'frame';
frame2.position.set(0, 0.165, 0);
panel2.add(frame2);
const cells2 = new THREE.Mesh(boxGeo6, cellsMat);
cells2.name = 'cells';
cells2.position.set(0, 0.19, 0);
panel2.add(cells2);
const box35 = new THREE.Mesh(boxGeo7, frameMat);
box35.position.set(-0.385, 0.214, 0);
panel2.add(box35);
const box36 = new THREE.Mesh(boxGeo7, frameMat);
box36.position.set(0, 0.214, 0);
panel2.add(box36);
const box37 = new THREE.Mesh(boxGeo7, frameMat);
box37.position.set(0.385, 0.214, 0);
panel2.add(box37);
const box38 = new THREE.Mesh(boxGeo8, frameMat);
box38.position.set(0, 0.214, -0.6733);
panel2.add(box38);
const box39 = new THREE.Mesh(boxGeo8, frameMat);
box39.position.set(0, 0.214, -0.3367);
panel2.add(box39);
const box40 = new THREE.Mesh(boxGeo8, frameMat);
box40.position.set(0, 0.214, 0);
panel2.add(box40);
const box41 = new THREE.Mesh(boxGeo8, frameMat);
box41.position.set(0, 0.214, 0.3367);
panel2.add(box41);
const box42 = new THREE.Mesh(boxGeo8, frameMat);
box42.position.set(0, 0.214, 0.6733);
panel2.add(box42);
const box43 = new THREE.Mesh(boxGeo9, frameMat);
box43.position.set(-0.79, 0.205, 0);
panel2.add(box43);
const box44 = new THREE.Mesh(boxGeo10, frameMat);
box44.position.set(0, 0.205, -1.03);
panel2.add(box44);
const box45 = new THREE.Mesh(boxGeo9, frameMat);
box45.position.set(0.79, 0.205, 0);
panel2.add(box45);
const box46 = new THREE.Mesh(boxGeo10, frameMat);
box46.position.set(0, 0.205, 1.03);
panel2.add(box46);
root.traverse((o) => {
if (o.isMesh) {
o.castShadow = true;
o.receiveShadow = true;
}
});
return root;
}
export default createSolarPanel;
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









