I'm building a live placement and rotation system in JSFiddle to preview artwork positions before deployment to the Arynwood 3D gallery. This log documents the Three.js loader, wall coordinates, rotation math, and editor functionality.
Today I built a working prototype of an artwork loader using THREE.TextureLoader()
with a mesh assignment that only paints the front face. I’m now actively using JSFiddle as a sandbox to test coordinate placements, rotations, and multi-wall positioning. I also wrote a guide below for replicating this gallery positioning system.
Only the front-facing panel is textured. Remaining sides are solid dark gray.
const loader = new THREE.TextureLoader();
loader.load(
'https://cdn.jsdelivr.net/gh/SkyeVault/Main@main/rainkeep/public/Arynwood/Untitled_Artwork%201.png',
function (texture) {
const artMaterial = new THREE.MeshBasicMaterial({ map: texture });
const artwork = new THREE.Mesh(
new THREE.BoxGeometry(4, 5, 0.2),
[
new THREE.MeshBasicMaterial({ color: '#111' }), // left
new THREE.MeshBasicMaterial({ color: '#111' }), // right
new THREE.MeshBasicMaterial({ color: '#111' }), // top
new THREE.MeshBasicMaterial({ color: '#111' }), // bottom
artMaterial, // front
new THREE.MeshBasicMaterial({ color: '#111' }) // back
]
);
artwork.position.set(0, 5, -24.5); // back wall center
scene.add(artwork);
},
undefined,
function (err) {
console.error('Error loading artwork texture:', err);
}
);
To make rapid adjustments, I’m prototyping positioning logic directly in JSFiddle with live output. This lets me rotate objects visually before exporting to production builds.
// Load THREE + OrbitControls via ESM
import * as THREE from 'https://esm.sh/three@0.158.0';
import { OrbitControls } from 'https://esm.sh/three@0.158.0/examples/jsm/controls/OrbitControls.js';
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(70, window.innerWidth/window.innerHeight, 0.1, 1000);
camera.position.set(0, 5, 35);
const renderer = new THREE.WebGLRenderer({ canvas: document.querySelector('canvas') });
renderer.setSize(window.innerWidth, window.innerHeight);
// Lighting
const ambient = new THREE.AmbientLight(0xffffff, 0.6);
scene.add(ambient);
// Controls
const controls = new OrbitControls(camera, renderer.domElement);
controls.target.set(0, 5, 0);
controls.update();
// Animation loop
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
animate();
All walls in the gallery use a bounding coordinate value of ±24.5. This creates predictable placements for any piece in the 3D space. Rotation is always applied using radians.
artwork.position.set(x, y, z);
artwork.rotation.y = THREE.MathUtils.degToRad(degrees);
// Back wall
artwork.position.set(0, 5, -24.5);
artwork.rotation.y = 0;
// Front wall
artwork.position.set(0, 5, 24.5);
artwork.rotation.y = Math.PI;
// Left wall
artwork.position.set(-24.5, 5, 0);
artwork.rotation.y = THREE.MathUtils.degToRad(90);
// Right wall
artwork.position.set(24.5, 5, 0);
artwork.rotation.y = THREE.MathUtils.degToRad(-90);
y = 5
works for center-aligned display at eye level (5 unit tall artwork). Adjust as needed.
Three.js uses radians — convert degrees using:
THREE.MathUtils.degToRad(45); // => 0.7854
Use .rotation.y
for turning left/right.
Use .rotation.x
or .rotation.z
for floor/table displays.
Open-source under the MIT License.
Created by Lorelei Noble for the Arynwood 3D Gallery project.
Live preview at: arynwood.com/gallery3d