Codels
500 tris2.84 × 1.38 × 3.94 m

Use it in code

Remix in the editor
Self-contained ES module — only depends on three. Call the factory and add the group to your scene.
/**
 * Camping Tent — Codels 3D model library
 * License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
 * Triangles: 500 · Size (W × H × D): 2.83 × 1.38 × 3.94 m
 *
 * Usage:
 *   import { createTent } from './tent.js';
 *   
 *   const model = createTent();
 *   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);
}

export function createTent() {
  const root = new THREE.Group();
  root.name = 'Tent';

  // Materials
  const fabricMat = new THREE.MeshStandardMaterial({ name: 'fabric', color: 0xe07b2c, roughness: 0.85, flatShading: true });
  const trimMat = new THREE.MeshStandardMaterial({ name: 'trim', color: 0x3c434b, roughness: 0.85, flatShading: true });
  const insideMat = new THREE.MeshStandardMaterial({ name: 'inside', color: 0x2a2622, roughness: 1, flatShading: true });
  const floorMat = new THREE.MeshStandardMaterial({ name: 'floor', color: 0x55634a, roughness: 0.95, flatShading: true });
  const poleMat = new THREE.MeshStandardMaterial({ name: 'pole', color: 0xa9aeb3, roughness: 0.35, metalness: 0.6, flatShading: true });
  const ropeMat = new THREE.MeshStandardMaterial({ name: 'rope', color: 0xe3d6b4, roughness: 0.9, flatShading: true });

  // Shared geometries
  const boxGeo = new THREE.BoxGeometry(1.5005, 0.025, 2.4);
  const boxGeo2 = new THREE.BoxGeometry(0.2, 0.012, 2.41);
  const capsuleGeo = new THREE.CapsuleGeometry(0.05, 0.8508, 2, 6);
  const boxGeo3 = new THREE.BoxGeometry(0.03, 0.03, 0.12);
  const cylinderGeo = new THREE.CylinderGeometry(0.02, 0.02, 1.34, 5);
  const sphereGeo = new THREE.SphereGeometry(0.03, 5, 3);
  const cylinderGeo2 = new THREE.CylinderGeometry(0.008, 0.008, 1.4872, 4);
  const boxGeo4 = new THREE.BoxGeometry(0.035, 0.14, 0.035);
  const cylinderGeo3 = new THREE.CylinderGeometry(0.008, 0.008, 1.1933, 4);

  // Parts
  const groundSheet = new THREE.Mesh(new THREE.BoxGeometry(1.95, 0.02, 2.36), floorMat);
  groundSheet.name = 'groundSheet';
  groundSheet.position.set(0, 0.01, 0);
  root.add(groundSheet);
  const panelLeft = new THREE.Mesh(boxGeo, fabricMat);
  panelLeft.name = 'panelLeft';
  panelLeft.position.set(-0.425, 0.616, 0);
  panelLeft.rotation.set(0, 0, deg(54.6888));
  root.add(panelLeft);
  const band = new THREE.Mesh(boxGeo2, trimMat);
  band.name = 'band';
  band.position.set(-0.8053, 0.1069, 0);
  band.rotation.set(0, 0, deg(54.6888));
  root.add(band);
  const panelRight = new THREE.Mesh(boxGeo, fabricMat);
  panelRight.name = 'panelRight';
  panelRight.position.set(0.425, 0.616, 0);
  panelRight.rotation.set(0, 0, deg(-54.6888));
  root.add(panelRight);
  const band2 = new THREE.Mesh(boxGeo2, trimMat);
  band2.name = 'band';
  band2.position.set(0.8053, 0.1069, 0);
  band2.rotation.set(0, 0, deg(-54.6888));
  root.add(band2);
  const ridgeSeam = new THREE.Mesh(new THREE.BoxGeometry(0.06, 0.05, 2.42), trimMat);
  ridgeSeam.name = 'ridgeSeam';
  ridgeSeam.position.set(0, 1.228, 0);
  ridgeSeam.rotation.set(0, 0, deg(45));
  root.add(ridgeSeam);
  const frontPanel = new THREE.Mesh(extrude([[-0.82, 0], [-0.36, 0], [0, 0.88], [0.36, 0], [0.82, 0], [0, 1.16]], 0.02), fabricMat);
  frontPanel.name = 'frontPanel';
  frontPanel.position.set(0, 0.016, 1.08);
  root.add(frontPanel);
  const backPanel = new THREE.Mesh(extrude([[-0.82, 0], [0.82, 0], [0, 1.16]], 0.02), fabricMat);
  backPanel.name = 'backPanel';
  backPanel.position.set(0, 0.016, -1.08);
  root.add(backPanel);
  const interior = new THREE.Mesh(extrude([[-0.8, 0], [0.8, 0], [0, 1.13]], 0.01), insideMat);
  interior.name = 'interior';
  interior.position.set(0, 0.016, -1.05);
  root.add(interior);
  const rolledFlap = new THREE.Mesh(capsuleGeo, fabricMat);
  rolledFlap.name = 'rolledFlap';
  rolledFlap.position.set(-0.23, 0.44, 1.12);
  rolledFlap.rotation.set(0, 0, deg(-22.249));
  root.add(rolledFlap);
  const tie = new THREE.Mesh(boxGeo3, trimMat);
  tie.name = 'tie';
  tie.position.set(-0.24, 0.44, 1.13);
  root.add(tie);
  const rolledFlap2 = new THREE.Mesh(capsuleGeo, fabricMat);
  rolledFlap2.name = 'rolledFlap';
  rolledFlap2.position.set(0.23, 0.44, 1.12);
  rolledFlap2.rotation.set(0, 0, deg(22.249));
  root.add(rolledFlap2);
  const tie2 = new THREE.Mesh(boxGeo3, trimMat);
  tie2.name = 'tie';
  tie2.position.set(0.24, 0.44, 1.13);
  root.add(tie2);
  const pole = new THREE.Mesh(cylinderGeo, poleMat);
  pole.name = 'pole';
  pole.position.set(0, 0.67, -1.16);
  root.add(pole);
  const poleTip = new THREE.Mesh(sphereGeo, poleMat);
  poleTip.name = 'poleTip';
  poleTip.position.set(0, 1.35, -1.16);
  root.add(poleTip);
  const guyRope = new THREE.Group();
  guyRope.name = 'guyRope';
  guyRope.position.set(0, 0.04, -1.95);
  root.add(guyRope);
  const tilt = new THREE.Group();
  tilt.name = 'tilt';
  tilt.rotation.set(deg(32.0871), 0, 0);
  guyRope.add(tilt);
  const rope = new THREE.Mesh(cylinderGeo2, ropeMat);
  rope.name = 'rope';
  rope.position.set(0, 0.7436, 0);
  tilt.add(rope);
  const stake = new THREE.Mesh(boxGeo4, trimMat);
  stake.name = 'stake';
  stake.position.set(0, 0.07, -1.95);
  root.add(stake);
  const guyRope2 = new THREE.Group();
  guyRope2.name = 'guyRope';
  guyRope2.position.set(-1.4, 0.04, -0.9);
  guyRope2.rotation.set(0, deg(81.8161), 0);
  root.add(guyRope2);
  const tilt2 = new THREE.Group();
  tilt2.name = 'tilt';
  tilt2.rotation.set(deg(62.0118), 0, 0);
  guyRope2.add(tilt2);
  const rope2 = new THREE.Mesh(cylinderGeo3, ropeMat);
  rope2.name = 'rope';
  rope2.position.set(0, 0.5966, 0);
  tilt2.add(rope2);
  const stake2 = new THREE.Mesh(boxGeo4, trimMat);
  stake2.name = 'stake';
  stake2.position.set(-1.4, 0.07, -0.9);
  root.add(stake2);
  const guyRope3 = new THREE.Group();
  guyRope3.name = 'guyRope';
  guyRope3.position.set(1.4, 0.04, -0.9);
  guyRope3.rotation.set(0, deg(-81.8161), 0);
  root.add(guyRope3);
  const tilt3 = new THREE.Group();
  tilt3.name = 'tilt';
  tilt3.rotation.set(deg(62.0118), 0, 0);
  guyRope3.add(tilt3);
  const rope3 = new THREE.Mesh(cylinderGeo3, ropeMat);
  rope3.name = 'rope';
  rope3.position.set(0, 0.5966, 0);
  tilt3.add(rope3);
  const stake3 = new THREE.Mesh(boxGeo4, trimMat);
  stake3.name = 'stake';
  stake3.position.set(1.4, 0.07, -0.9);
  root.add(stake3);
  const pole2 = new THREE.Mesh(cylinderGeo, poleMat);
  pole2.name = 'pole';
  pole2.position.set(0, 0.67, 1.16);
  root.add(pole2);
  const poleTip2 = new THREE.Mesh(sphereGeo, poleMat);
  poleTip2.name = 'poleTip';
  poleTip2.position.set(0, 1.35, 1.16);
  root.add(poleTip2);
  const guyRope4 = new THREE.Group();
  guyRope4.name = 'guyRope';
  guyRope4.position.set(0, 0.04, 1.95);
  guyRope4.rotation.set(0, deg(180), 0);
  root.add(guyRope4);
  const tilt4 = new THREE.Group();
  tilt4.name = 'tilt';
  tilt4.rotation.set(deg(32.0871), 0, 0);
  guyRope4.add(tilt4);
  const rope4 = new THREE.Mesh(cylinderGeo2, ropeMat);
  rope4.name = 'rope';
  rope4.position.set(0, 0.7436, 0);
  tilt4.add(rope4);
  const stake4 = new THREE.Mesh(boxGeo4, trimMat);
  stake4.name = 'stake';
  stake4.position.set(0, 0.07, 1.95);
  root.add(stake4);
  const guyRope5 = new THREE.Group();
  guyRope5.name = 'guyRope';
  guyRope5.position.set(-1.4, 0.04, 0.9);
  guyRope5.rotation.set(0, deg(98.1839), 0);
  root.add(guyRope5);
  const tilt5 = new THREE.Group();
  tilt5.name = 'tilt';
  tilt5.rotation.set(deg(62.0118), 0, 0);
  guyRope5.add(tilt5);
  const rope5 = new THREE.Mesh(cylinderGeo3, ropeMat);
  rope5.name = 'rope';
  rope5.position.set(0, 0.5966, 0);
  tilt5.add(rope5);
  const stake5 = new THREE.Mesh(boxGeo4, trimMat);
  stake5.name = 'stake';
  stake5.position.set(-1.4, 0.07, 0.9);
  root.add(stake5);
  const guyRope6 = new THREE.Group();
  guyRope6.name = 'guyRope';
  guyRope6.position.set(1.4, 0.04, 0.9);
  guyRope6.rotation.set(0, deg(-98.1839), 0);
  root.add(guyRope6);
  const tilt6 = new THREE.Group();
  tilt6.name = 'tilt';
  tilt6.rotation.set(deg(62.0118), 0, 0);
  guyRope6.add(tilt6);
  const rope6 = new THREE.Mesh(cylinderGeo3, ropeMat);
  rope6.name = 'rope';
  rope6.position.set(0, 0.5966, 0);
  tilt6.add(rope6);
  const stake6 = new THREE.Mesh(boxGeo4, trimMat);
  stake6.name = 'stake';
  stake6.position.set(1.4, 0.07, 0.9);
  root.add(stake6);

  root.traverse((o) => {
    if (o.isMesh) {
      o.castShadow = true;
      o.receiveShadow = true;
    }
  });
  return root;
}

export default createTent;

Ratings & comments

—
No ratings yet — be the first.
5
0
4
0
3
0
2
0
1
0

Sign in to rate and comment.

0 comments

No comments yet. Share how you used this model or what could be better.

Related models

Same category or similar tags