X
Share
Where do you want to share this website to?

Reddit

Twitter

Linkedin

Facebook

Whatsapp

Pintrest

Email

headblockhead.com
  • Blog
  • Toys
  • Games

Toys

Welcome to the toys page! Here you can find my various web-toys to mess around with.

Phoenix Wright Comic Generator 


Launch the Phoenix Wright Comic Generator

The Phoenix Wright Comic Generator is a web toy that allows you to generate your own Phoenix Wright comic!

An image showing Phoenix Wright saying 'I knew it!'

You can generate a new comic by clicking the “New Seed” button, or by entering a seed into the text box and clicking “Generate”. You can also download the comic panels if you want to by clicking the “Download panel” button.

3D Object Demo using three.js 


Launch the 3D Object Demo

This is a very simple demo of using three.js to render 3D objects in a web browser. It is rendered in the browser using WebGL, and uses the three.js library to do so.

An image showing three wireframe objects, the first being an octahedron, the second being a sphere and the last being a torus knot.

The code has three main parts: Setting up the scene, adding the objects, and animating the objects.

The setup is quite easy, simply creating a scene, a camera, and a renderer. The scene is created, the camera is configured and positioned at (0, 0, 8) and the renderer is added to the DOM.

import * as THREE from 'three';

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, 2, 1, 1000);
camera.position.z = 8;

const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.domElement.style.width = "100%";
renderer.domElement.style.height = "200px";
renderer.domElement.style.margin = "auto";
document.getElementById("3dDemoParent").replaceChildren(renderer.domElement);

Now we add the objects to the scene. We create three objects, an octahedron, a sphere, and a torus knot. We add them all to the scene.

const octageometry = new THREE.OctahedronGeometry(1.5, 1);
const ocatamaterial = new THREE.MeshStandardMaterial({ color: 0xff0000, roughness: 0.5, metalness: 0.5, wireframe: true });
const octa = new THREE.Mesh(octageometry, ocatamaterial);
octa.position.set(-5, 0, 0);
scene.add(octa);

const spheregeometry = new THREE.SphereGeometry(1.5, 25, 13);
const spherematerial = new THREE.MeshStandardMaterial({ color: 0x00ff00, roughness: 0.5, metalness: 0.5, wireframe: true });
const sphere = new THREE.Mesh(spheregeometry, spherematerial);
scene.add(sphere);

const torusknotgeometry = new THREE.TorusKnotGeometry(1, 0.3, 100, 16);
const torusknotmaterial = new THREE.MeshStandardMaterial({ color: 0x0000ff, roughness: 0.5, metalness: 0.5, wireframe: true });
const torusknot = new THREE.Mesh(torusknotgeometry, torusknotmaterial);
torusknot.position.set(5, 0, 0);
scene.add(torusknot);

We also need to add the lights so the objects are visible. We add 2 point lights and an ambient light.

const ambientlight = new THREE.AmbientLight(0x404040);
scene.add(ambientlight);

const lightright = new THREE.PointLight(0xffffff, 1);
lightright.position.set(5, 2, 2);
scene.add(lightright);

const lightleft = new THREE.PointLight(0xffffff, 1);
lightleft.position.set(-5, 2, 2);
scene.add(lightleft);

Finally, we animate the objects. We rotate the objects and move the camera around the scene in a circle around the objects, making sure it is always pointing towards them.

const degsToRads = deg => (deg * Math.PI) / 180.0;
var deg = 0;

function animate() {
    const canvas = renderer.domElement;
    camera.aspect = canvas.clientWidth / canvas.clientHeight;
    camera.updateProjectionMatrix();

    if (resizeRendererToDisplaySize(renderer)) {
        const canvas = renderer.domElement;
        camera.aspect = canvas.clientWidth / canvas.clientHeight;
        camera.updateProjectionMatrix();
    }

    requestAnimationFrame(animate);

    sphere.rotation.x += 0.01;
    sphere.rotation.y += 0.01;

    octa.rotation.x += 0.01;
    octa.rotation.y += 0.01;

    torusknot.rotation.x += 0.01;
    torusknot.rotation.y += 0.01;

    deg -= 0.1;
    if (deg < 1) {
        deg = 360;
    }

    let theta = degsToRads(deg);
    let x = Math.cos(theta) * 8;
    let y = Math.sin(theta) * 8;

    camera.position.x = y;
    camera.position.z = x;

    camera.lookAt(0, 0, 0);

    renderer.render(scene, camera);
};

You may have noticed a function called resizeRendererToDisplaySize() in the code. This is a function that resizes the renderer to the size of the canvas. This is needed because the canvas is responsive, and so the renderer needs to be resized to match the canvas size. This is what it looks like:

function resizeRendererToDisplaySize(renderer) {
    const canvas = renderer.domElement;
    const width = canvas.clientWidth;
    const height = canvas.clientHeight;
    const needResize = canvas.width !== width || canvas.height !== height;
    if (needResize) {
        renderer.setSize(width, height, false);
    }
    return needResize;
}

Now there is one last thing to do, and that is to call the animate function. This is done at the end of the file.

animate();

© Edward Hesketh 2025

Youtube GitHub Bored?

Hi there!
Sorry to interrupt, but I use Google Analytics Cookies to gather data from my site. Is that OK with you?

Accept

Decline