I'm working on my first 3d graphics project using Three js and Vite. Every time I run the server, I get a black screen (scene), but none of the objects get rendered. I have tried moving the camera back, rendering the torus object, and messing with the animate function but no luck.
main.js
import './style.css'
import * as THREE from 'three';
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth/window/innerHeight, .1, 1000);
const renderer = new THREE.WebGLRenderer({
canvas: document.querySelector('#bg'),
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
camera.position.setZ(30);
renderer.render( scene, camera );
const geometry = new THREE.TorusGeometry(10,3, 16, 100);
const material = new THREE.MeshNormalMaterial()
const torus = new THREE.Mesh(geometry, material);
scene.add(torus);
const groundGeometry = new THREE.BoxGeometry(24,1,24);
const groundMaterial = new THREE.MeshNormalMaterial();
const groundMesh = new THREE.Mesh(groundGeometry, groundMaterial);
scene.add(groundMesh);
function animate() {
requestAnimationFrame( animate );
renderer.render( scene, camera);
}
animate()
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>3d Portfolio Vite App</title>
</head>
<body>
<canvas id="bg"></canvas>
<script type="module" src="/main.js"></script>
</body>
</html>
Related
I apologize in advance if I'm missing something obvious here.
I'm trying to use the three.js VOXLoader while using Flask.
I'm able to load three.js fine, but when I try and load the VOXLoader, it doesn't seem to work and breaks all three.js functionality on the page.
Here is the code from the page I'm trying to run.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ThreeJS Starter</title>
<link rel="stylesheet" href="/static/style.css">
</head>
<body>
<script src="/static/three/build/three.js"></script>
<script type="module" src="/static/three/examples/jsm/controls/OrbitControls.js"></script>
<script type="module" src="/static/three/examples/jsm/loaders/VOXLoader.js"></script>
<script type="module">
// Canvas
const canvas = document.querySelector('canvas.webgl')
// Scene
const scene = new THREE.Scene()
// Problem Loading Here
const loader = new VOXLoader();
const geometry = new THREE.TorusGeometry( .7, .2, 16, 100 );
// Materials
const material = new THREE.MeshBasicMaterial()
material.color = new THREE.Color(0xff0000)
// Mesh
const sphere = new THREE.Mesh(geometry,material)
scene.add(sphere)
// Lights
const pointLight = new THREE.PointLight(0xffffff, 0.1)
pointLight.position.x = 2
pointLight.position.y = 3
pointLight.position.z = 4
scene.add(pointLight)
/**
* Sizes
*/
const sizes = {
width: window.innerWidth,
height: window.innerHeight
}
window.addEventListener('resize', () =>
{
// Update sizes
sizes.width = window.innerWidth
sizes.height = window.innerHeight
// Update camera
camera.aspect = sizes.width / sizes.height
camera.updateProjectionMatrix()
// Update renderer
renderer.setSize(sizes.width, sizes.height)
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
})
/**
* Camera
*/
// Base camera
const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height, 0.1, 100)
camera.position.x = 0
camera.position.y = 0
camera.position.z = 2
scene.add(camera)
// Controls
// const controls = new OrbitControls(camera, canvas)
// controls.enableDamping = true
/**
* Renderer
*/
const renderer = new THREE.WebGLRenderer({
canvas: canvas
})
renderer.setSize(sizes.width, sizes.height)
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
/**
* Animate
*/
const clock = new THREE.Clock()
const tick = () =>
{
const elapsedTime = clock.getElapsedTime()
// Update objects
sphere.rotation.y = .5 * elapsedTime
// Update Orbital Controls
// controls.update()
// Render
renderer.render(scene, camera)
// Call tick again on the next frame
window.requestAnimationFrame(tick)
}
tick()
</script>
TEST
<canvas class="webgl"></canvas>
Currently, when the page loads correctly it displays a red spinning Torus, but if it doesn't it show a white background with black text saying "TEST".
Ideally, I should be able to create a new instance of the VOXLoader without it breaking the page.
I've tried adding "import { VOXLoader } from '/static/three/examples/jsm/loaders/VOXLoader.js';" too, but the import function alone also seems to break the page.
I also checked the three.js documentation but didn't find anything helpful there yet.
It seems most people using three.js, aren't typically using it with flask, so I'm not sure if this is flask specific?
What's confusing to me is that the three.js file is imported fine and works with no issues, but for some reason, VOXLoader doesn't.
I double-checked the path and directory for VOXLoader and it's 100% correct.
This page is also currently only being used as a template for other pages to extend from, so it doesn't have any python code on it either.
I'm just trying to get the VOXLoader working and any suggestions or advice would be greatly appreciated.
Thank you in advance!
I've been wanting to use Three.js in a project but I can't get anything to render on my screen.
After a while of troubleshooting, I thought I would just ask and see if anyone can help me.
DETAILS:
Hosting on XAMPP,
here's a complete Three.js example that should work, to my knowledge, but evidently does not:
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<canvas id="c"></canvas>
<script type="module">
import {
Camera,
Material,
Texture,
} from "https://cdn.skypack.dev/three#0.132.2";
import { OrbitControls } from "https://cdn.skypack.dev/three#0.132.2/examples/jsm/controls/OrbitControls.js";
function main() {
const canvas = document.getElementById('c');
const renderer = new THREE.WebGLRenderer({canvas});
const fov = 75;
const aspect = 2; // the canvas default
const near = 0.1;
const far = 5;
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.position.z = 2;
const scene = new THREE.Scene();
const boxWidth = 1;
const boxHeight = 1;
const boxDepth = 1;
const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
const material = new THREE.MeshBasicMaterial({color: 0x44aa88});
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.render(scene, camera);
}
</script>
</body>
</html>
I've linked through a cdn here, but other methods such as installing with npm and linking that way have also had the same confounding results.
In any case it's not throwing any errors, so I'm at a loss.
All I end up getting is a blank white page.
The function main() is not gonna call itself. When you declare a function, you have to make sure you execute it, otherwise it'll just sit there, unused.
// First we declare the function
function main() {
// Do a bunch of stuff
}
// Then we call the function
main();
im a bit of a noob when it comes to three.js and html but ive created other js files and they would import into the html page just fine but im confused why my basic box copy pasta code isnt showing up on the page. it works fine when scripting it all in html but not when import the js file in the same folder. could yall help me understand whats going on?
index.js
/*import * as THREE from 'three'
const canvas=document.querySelector('.webgl')
const scene = new THREE.Scene();
const geo = new THREE.BoxGeometry(1,1,1)
const mats = new THREE.MeshBasicMaterial({
color:'red'
})
const boxmesh=new THREE.Mesh(geo,mats)
scene.add(boxmesh)
const camera = new THREE.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,100)
camera.position.set(0,1,2)
scene.add(camera)
const renderer=new THREE.WebGL1Renderer({
canvas:canvas
})
renderer.setSize(window.innerWidth,window.innerHeight)
renderer.setPixelRatio(Math.min(window.devicePixelRatio,2))
renderer.shadowMap.enabled=true
renderer.gammaOutput=true
renderer.render(scene, camera)*/
import * as THREE from 'three';
// init
const camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.01, 10 );
camera.position.z = 1;
const scene = new THREE.Scene();
scene.background= new THREE.Color('black')
const geometry = new THREE.BoxGeometry( 0.2, 0.2, 0.2 );
const material = new THREE.MeshNormalMaterial();
const mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
const renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setAnimationLoop( animation );
document.body.appendChild( renderer.domElement );
// animation
function animation( time ) {
mesh.rotation.x = .1;
mesh.rotation.y = .1;
renderer.render( scene, camera );
}
animation()
index.html
<!DOCTYPE html>
<html>
<head>
<meta name="learning html" content="This is learing making websites">
<title>Learing GLTF</title>
<script src="index.js"></script>
</head>
<body>
<canvas class="webgl"></canvas>
?
</body>
</html>
When using the latest versions of three.js(e.g. r140), then it's important to define an import map in your HTML. Otherwise the import import * as THREE from 'three'; does not work. A import map is required so the bare module specifier three can be resolved in browsers. For testing, try it with:
<script type="importmap">
{
"imports": {
"three": "https://unpkg.com/three#0.140/build/three.module.js"
}
}
</script>
ive been trying to deploy a threejs project that im working on, on either github pages or firebase, but whenever I deploy them, the browser just shows a whitescreen, its weird because when I run the same project through localhost, everything its working perfectly.
here is my index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Waber App</title>
</head>
<body>
<canvas id="bg"></canvas>
<script type="module" src="/main.js"></script>
</body>
</html>
and here is my main.js
import "./style.css";
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
const renderer = new THREE.WebGLRenderer({
canvas: document.querySelector("#bg"),
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
camera.position.setZ(30);
renderer.render(scene, camera);
const geometry = new THREE.TorusGeometry(10, 3, 16, 100);
const material = new THREE.MeshStandardMaterial({
color: 0xff6347,
});
const torus = new THREE.Mesh(geometry, material);
//scene.add(torus);
const pointLight = new THREE.PointLight(0xffffff);
pointLight.position.set(20, 20, 20);
const ambientLight = new THREE.AmbientLight();
scene.add(pointLight, ambientLight);
const lightHelper = new THREE.PointLightHelper(pointLight);
const gridHelper = new THREE.GridHelper(200, 50);
//scene.add(lightHelper, gridHelper);
const controls = new OrbitControls(camera, renderer.domElement);
function addStar() {
const geometry = new THREE.SphereGeometry(0.25, 24, 24);
const material = new THREE.MeshStandardMaterial({ color: 0xffffff });
const star = new THREE.Mesh(geometry, material);
const [x, y, z] = Array(3)
.fill()
.map(() => THREE.MathUtils.randFloatSpread(100));
star.position.set(x, y, z);
scene.add(star);
}
Array(200).fill().forEach(addStar);
const spaceTexture = new THREE.TextureLoader().load("space.jpeg");
scene.background = spaceTexture;
function animate() {
requestAnimationFrame(animate);
moon.rotation.y += 0.005;
torus.rotation.x += 0.01;
torus.rotation.y += 0.005;
torus.rotation.z += 0.01;
controls.update();
renderer.render(scene, camera);
}
const moonTexture = new THREE.TextureLoader().load("moon.jpeg")
const normalTexture = new THREE.TextureLoader().load("normal.jpeg")
const moon = new THREE.Mesh(
new THREE.SphereGeometry(3,32,32),
new THREE.MeshStandardMaterial({
map: moonTexture,
normalMap: normalTexture,
})
)
scene.add(moon)
animate();
LOCALHOST PREVIEW
FIREBASE PREVIEW
I don't know if you've found a solution for your problem yet, but I had the same problem a couple of days ago. I was able to solve it and deploy on Github Pages by putting all my javascript code into my index.html file. I added the link to my CSS file somewhere in the head of the html like you normally would:
<link rel="stylesheet" href="./style.css" />
Then I added the Threejs cdn and all my js code at the bottom of the body. So yours would have to look something like this:
<canvas id="bg"></canvas>
<script type="module">
// Find the latest version by visiting https://unpkg.com/three. The URL will
// redirect to the newest stable release.
import * as THREE from "https://unpkg.com/three/build/three.module.js";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
const scene = new THREE.Scene();
//Followed by all the rest of your code.
</script>
</body>
</html>
This is what worked for me, anyway.
I hope you find this helpful!
Full disclosure, this is my first time answering someone's question on here. If you need anymore info, let me know, and I'll do my best to supply it.
I've been messing around with Threejs trying to get my sea legs, but I've run into a problem long before I expected to and I can't figure out if there's a mistake in my code or a mistake in the framework (I assume it's mine).
I want to replace an object with another when a button is pressed. My test code (below) loads a cube on the initial load, and I was hoping to replace it with a sphere when a button is pressed. However, that's not happening, and instead I'm getting the error:
TypeError: geometry.addEventListener is not a function
geometry.addEventListener( 'dispose', onGeometryDispose );
My html:
<!doctype html>
<html lang="en">
<head>
<title>My test</title>
<meta charset="utf-8">
</head>
<body style="margin: 0;">
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r71/three.js"></script>
<script src="OrbitControls.js"></script>
<script>
var WIDTH = 500,
HEIGHT = 500;
var scene = new THREE.Scene();
var aspect = WIDTH / HEIGHT;
var camera = new THREE.PerspectiveCamera(75, aspect, 0.1, 1000);
camera.position.set(0,0,5);
scene.add(camera);
var renderer = new THREE.WebGLRenderer();
renderer.setSize( WIDTH , HEIGHT );
document.body.appendChild( renderer.domElement );
var geometry = new THREE.BoxGeometry( 1, 1, 1 );
var material = new THREE.MeshNormalMaterial();
var cube = new THREE.Mesh( geometry, material );
scene.add( cube );
controls = new THREE.OrbitControls(camera, renderer.domElement);
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
controls.update();
}
animate();
</script>
<div>
<button onclick="updateThing();">Update Thing</button>
</div>
</body>
<script src="scripts.js" type="text/javascript" charset="utf-8"></script>
</html>
My function for making the change when the button is pressed:
function updateThing() {
scene.remove(cube)
var pos = new THREE.Vector3(0, 0, 0);
var geo = new THREE.Sphere(pos, parseFloat(1.4));
var mat = new THREE.MeshNormalMaterial();
sphere = new THREE.Mesh( geo, mat );
scene.add( sphere );
}
Am I doing something wrong?
Orbit controls can be found here: https://github.com/mrdoob/three.js/blob/master/examples/js/controls/OrbitControls.js
I believe you are looking for THREE.SphereGeometry instead of THREE.Sphere:
var geo = new THREE.SphereGeometry(parseFloat(1.4));
See documentation here and here.