Skip to content

Instantly share code, notes, and snippets.

@AndrewKhassapov
Created April 15, 2023 01:13
Show Gist options
  • Save AndrewKhassapov/4ab2c83dbe618816e5ef1b79ea10e6c7 to your computer and use it in GitHub Desktop.
Save AndrewKhassapov/4ab2c83dbe618816e5ef1b79ea10e6c7 to your computer and use it in GitHub Desktop.
Three Rocket, you're Three now! With controls.
<!--Recreated stivaliserna's rocket cartoon with Three.js geometric shapes. See: https://codepen.io/stivaliserna/pen/rNMwpaG-->
<script src="https://unpkg.com/three@0.112/examples/jsm/controls/OrbitControls.js"></script>
<div class="rain rain1"></div>
<div class="rain rain2">
<div class="drop drop2"></div>
</div>
<div class="rain rain3"></div>
<div class="rain rain4"></div>
<div class="rain rain5">
<div class="drop drop5"></div>
</div>
<div class="rain rain6"></div>
<div class="rain rain7"></div>
<div class="rain rain8">
<div class="drop drop8"></div>
</div>
<div class="rain rain9"></div>
<div class="rain rain10"></div>
<div class="drop drop11"></div>
<div class="drop drop12"></div>
<div id="canvas"></div> <!-- Main canvas //-->
import { OrbitControls } from "https://unpkg.com/three@0.112/examples/jsm/controls/OrbitControls.js";
let scene,
camera,
fieldOfView,
aspectRatio,
nearPlane,
farPlane,
renderer,
controls,
container,
rocket,
rocket_fire,
HEIGHT,
WIDTH;
const createScene = () => {
HEIGHT = window.innerHeight;
WIDTH = window.innerWidth;
scene = new THREE.Scene();
scene.fog = new THREE.Fog(0x8aabff, 10, 1500);
aspectRatio = WIDTH / HEIGHT;
fieldOfView = 60;
nearPlane = 1;
farPlane = 10000;
camera = new THREE.PerspectiveCamera(
fieldOfView,
aspectRatio,
nearPlane,
farPlane
);
camera.position.x = 0;
camera.position.z = 200;
camera.position.y = 0;
renderer = new THREE.WebGLRenderer({
alpha: true,
antialias: true
});
renderer.setSize(WIDTH, HEIGHT);
renderer.shadowMap.enabled = true;
container = document.getElementById("canvas");
container.appendChild(renderer.domElement);
window.addEventListener("resize", handleWindowResize, false);
// Add OrbitControls
controls = new OrbitControls(camera, renderer.domElement);
controls.target.z = 0;
// Create rocket group
const rocketParts = {};
rocketParts.topc = new THREE.Mesh(
new THREE.ConeGeometry(6, 4, 64),
new THREE.MeshStandardMaterial({ color: 0xff0000 })
);
scene.add(rocketParts.topc);
rocketParts.topc.position.y = 60;
rocketParts.topa = new THREE.Mesh(
new THREE.CylinderGeometry(6, 12, 8, 64),
new THREE.MeshStandardMaterial({ color: 0xff0000 })
);
scene.add(rocketParts.topa);
rocketParts.topa.position.y = 54;
rocketParts.topb = new THREE.Mesh(
new THREE.CylinderGeometry(12, 18, 20, 64),
new THREE.MeshStandardMaterial({ color: 0xff0000 })
);
scene.add(rocketParts.topb);
rocketParts.topb.position.y = 40;
rocketParts.mida = new THREE.Mesh(
new THREE.CylinderGeometry(18, 20, 16, 64),
new THREE.MeshStandardMaterial({ color: 0xffffff })
);
scene.add(rocketParts.mida);
rocketParts.mida.position.y = 22;
rocketParts.midc = new THREE.Mesh(
new THREE.CylinderGeometry(20, 20, 8, 64),
new THREE.MeshStandardMaterial({ color: 0xffffff })
);
scene.add(rocketParts.midc);
rocketParts.midc.position.y = 10;
rocketParts.midb = new THREE.Mesh(
new THREE.CylinderGeometry(20, 18, 16, 64),
new THREE.MeshStandardMaterial({ color: 0xffffff, receiveShadow: false })
);
scene.add(rocketParts.midb);
rocketParts.midb.position.y = -2;
rocketParts.bota = new THREE.Mesh(
new THREE.CylinderGeometry(18, 14, 10, 64),
new THREE.MeshStandardMaterial({ color: 0xffffff })
);
scene.add(rocketParts.bota);
rocketParts.bota.position.y = -15;
rocketParts.botb = new THREE.Mesh(
new THREE.CylinderGeometry(14, 12, 6, 64),
new THREE.MeshStandardMaterial({
color: 0xeeeeee,
roughness: 0.5,
metalness: 1,
side: THREE.DoubleSide
})
);
scene.add(rocketParts.botb);
rocketParts.botb.position.y = -20;
rocketParts.botc = new THREE.Mesh(
new THREE.CylinderGeometry(10, 8, 4, 64),
new THREE.MeshStandardMaterial({
color: 0x333333,
roughness: 0,
metalness: 1,
side: THREE.DoubleSide
})
);
scene.add(rocketParts.botc);
rocketParts.botc.position.y = -22;
rocketParts.wina = new THREE.Mesh(
new THREE.CylinderGeometry(12, 12, 23, 64),
new THREE.MeshStandardMaterial({
color: 0xeeeeee,
roughness: 0.5,
metalness: 1,
side: THREE.DoubleSide
})
);
scene.add(rocketParts.wina);
rocketParts.wina.position.set(0, 20, 10);
rocketParts.wina.rotation.set(Math.PI / 2, 0, 0);
// Rocket window
rocketParts.winb = new THREE.Mesh(
new THREE.CylinderGeometry(9, 9, 8, 64),
new THREE.MeshPhysicalMaterial({
color: 0x0077ff,
roughness: 0.1,
transmission: 1,
thickness: 0.9,
side: THREE.DoubleSide
})
);
scene.add(rocketParts.winb);
rocketParts.winb.position.set(0, 20, 18);
rocketParts.winb.rotation.set(Math.PI / 2, 0, 0);
rocketParts.fina = new THREE.Mesh(
new THREE.BoxBufferGeometry(40, 8, 18),
new THREE.MeshStandardMaterial({
color: 0xff0000
})
);
scene.add(rocketParts.fina);
rocketParts.fina.position.set(16, -10, 0);
rocketParts.fina.rotation.set(Math.PI / 2, 0.7 * Math.PI, 0);
rocketParts.finb = new THREE.Mesh(
new THREE.BoxBufferGeometry(40, 8, 18),
new THREE.MeshStandardMaterial({
color: 0xff0000
})
);
scene.add(rocketParts.finb);
rocketParts.finb.position.set(-16, -10, 0);
rocketParts.finb.rotation.set(-Math.PI / 2, 0.7 * Math.PI, 0);
var flame_material = new THREE.ShaderMaterial({
uniforms: {
color1: {
value: new THREE.Color("yellow")
},
color2: {
value: new THREE.Color("red")
}
},
vertexShader: `
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
}
`,
fragmentShader: `
uniform vec3 color1;
uniform vec3 color2;
varying vec2 vUv;
void main() {
gl_FragColor = vec4(mix(color1, color2, vUv.y), 1.0);
}
`,
wireframe: true
});
rocket_fire = new THREE.Mesh(
new THREE.CylinderGeometry(6, 0, 20, 64),
flame_material
);
scene.add(rocket_fire);
rocket_fire.position.y = -30;
rocket = new THREE.Group();
rocket.add(
rocketParts.midb,
rocketParts.mida,
rocketParts.midc,
rocketParts.topa,
rocketParts.topb,
rocketParts.bota,
rocketParts.botb,
rocketParts.botc,
rocketParts.topc,
rocketParts.wina,
rocketParts.winb,
rocketParts.fina,
rocketParts.finb,
rocket_fire
);
rocket.position.y = 0;
scene.add(rocket);
};
const handleWindowResize = () => {
HEIGHT = window.innerHeight;
WIDTH = window.innerWidth;
renderer.setSize(WIDTH, HEIGHT);
camera.aspect = WIDTH / HEIGHT;
camera.updateProjectionMatrix();
};
const createLights = () => {
const ambientLight = new THREE.HemisphereLight(0xffffff, 0xffffff, 0.25);
const directionalLight = new THREE.DirectionalLight(0xffcb87, 1);
directionalLight.position.set(-300, 300, 600);
const pointLight = new THREE.PointLight(0xff4f4f, 2, 1000, 2);
pointLight.position.set(-200, 100, 50);
scene.add(ambientLight, directionalLight, pointLight);
};
const targetRocketPosition = 40;
const animationDuration = 2000;
const loop = () => {
const t = (Date.now() % animationDuration) / animationDuration;
renderer.render(scene, camera);
const delta = targetRocketPosition * Math.sin(Math.PI * 2 * t);
if (rocket) {
rocket.rotation.y += 0.01;
rocket.rotation.x += 0.01;
rocket.rotation.z += 0.01;
rocket.position.y = delta;
}
if (rocket_fire) {
rocket_fire.scale.set(
1 + delta / 100,
1 + Math.abs(delta / 100),
1 + delta / 100
);
}
requestAnimationFrame(loop);
};
const main = () => {
createScene();
createLights();
renderer.render(scene, camera);
loop();
};
main();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/0.151.3/three.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three-js-csg/72.0.0/index.js"></script>
<script src="https://unpkg.com/three@0.151.3/examples/jsm/controls/OrbitControls.js"></script>
html,
body {
margin: 0;
height: 100%;
background: #010308;
overflow: hidden;
perspective: 10rem;
}
#canvas {
position: absolute;
width: 100%;
height: 100%;
overflow: hidden;
}
.rain {
position: absolute;
width: 1rem;
height: 10rem;
background: #ffffff;
border-radius: 20%;
opacity: 0.4;
z-index: -1;
}
.drop {
width: 1rem;
height: 7rem;
background: #ffffff;
position: absolute;
border-radius: 20%;
opacity: 0.2;
}
.rain1 {
left: 5rem;
top: 2rem;
animation: raining 2s linear infinite both;
}
.rain2 {
left: 15rem;
top: 10rem;
animation: raining 3s linear infinite both;
}
.drop2 {
top: 12rem;
animation: raining 4s linear infinite both -2s;
}
.rain3 {
left: 5rem;
top: 35rem;
animation: raining 3s linear infinite both;
}
.rain4 {
right: 23rem;
top: 6rem;
animation: raining 4s linear infinite both;
}
.rain5 {
left: 25rem;
top: 47rem;
animation: raining 3s linear infinite both -3s;
}
.drop5 {
top: -6rem;
animation: raining 2s linear infinite both;
}
.rain6 {
right: 10rem;
top: 34rem;
animation: raining 3s linear infinite both;
}
.rain7 {
left: 34rem;
top: 10rem;
animation: raining 2s linear infinite both -5s;
}
.rain8 {
right: 25rem;
top: 40rem;
animation: raining 3s linear infinite both;
}
.drop8 {
top: -7rem;
animation: raining 4s linear infinite both -6s;
}
.rain9 {
right: 5rem;
top: 15.5rem;
animation: raining 3s linear infinite both;
}
.rain10 {
left: 24rem;
top: -4rem;
animation: raining 2s linear infinite both -3s;
}
.drop11 {
right: 17rem;
top: 20rem;
animation: raining 3s linear infinite both;
}
.drop12 {
right: 15rem;
top: 50rem;
animation: raining 4s linear infinite both -1s;
}
@keyframes raining {
from {
transform: translateY(-1200px);
}
to {
transform: translateY(869px);
}
}

Three Rocket, you're Three now! With controls.

A Three.js rocket ship made from basic geometric shapes. With orbit controls added for pointer to rotate rocket.

A Pen by Andrew Khassapov on CodePen.

License.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment