I would like to display the wireframe of a parallelepiped defined by vertexes in a Json format using the following Three.js code
var testCube ={
"metadata":{
"version":json['version'],
"type":json['type'],
"uvs":json['n_uvs'],
"normals":json['n_normals'],
"faces":json['n_faces'],
"generator":"io_three",
"vertices":json['n_vertices'],
},
"faces":json['faces'],
"vertices":json['vertices'],
"normals":json['normals'],
"uvs":[],
"name":json['name']}
var loader = new THREE.JSONLoader();
var model = loader.parse( testCube );
meshBox = new THREE.Mesh( model.geometry, model.materials[ 0 ] );
var geo = new THREE.EdgesGeometry( meshBox.geometry );
var mat = new THREE.LineBasicMaterial( { color: 0xffffff, linewidth: 2 });
var wireframe = new THREE.LineSegments( geo, mat );
scene.add( wireframe );
however, the above code produce this kind of visualization:
while I would like to produce a visualization where also the internal wireframe is visible as the following:
Question: do you know how I can modify the above Three.js code to produce a full wireframe as displayed in the second picture?
Upadate: using the function WireframeGeometry you have the following plot:
Diagonals appear on each face of the mesh. Do yo know a function that does not produce diagonals?
Thank you very much for your help!
The solution is rough and imperfect, and it's a huge field for improvement and optimization.
You create one geometry and share it between two instances of THREE.LineSegments() for opposing sides of a box.
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(-15, 10, 10);
var renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var controls = new THREE.OrbitControls(camera, renderer.domElement);
scene.add(new THREE.AmbientLight(0xffffff, .5));
var light = new THREE.DirectionalLight(0xffffff, .5);
light.position.setScalar(10);
scene.add(light);
var box = new THREE.Mesh(new THREE.BoxGeometry(10, 5, 5, 5, 5, 5), new THREE.MeshLambertMaterial({color:"gray"}));
scene.add(box);
var material = new THREE.LineBasicMaterial({
vertexColors: THREE.VertexColors
});
var params = box.geometry.parameters;
var geometryGridXY = Grid(params.width, params.height, params.widthSegments, params.heightSegments, "yellow");
var gridXYFront = new THREE.LineSegments(geometryGridXY, material);
gridXYFront.position.z = params.depth / 2 + 0.001;
box.add(gridXYFront);
var gridXYBack = new THREE.LineSegments(geometryGridXY, material);
gridXYBack.position.z = -params.depth / 2 - 0.001;
box.add(gridXYBack);
var geometryGridYZ = Grid(params.height, params.depth, params.heightSegments, params.depthSegments, "aqua");
var gridYZLeft = new THREE.LineSegments(geometryGridYZ, material);
gridYZLeft.position.x = -params.width / 2 - 0.001;
gridYZLeft.rotation.y = -Math.PI * .5;
box.add(gridYZLeft);
render();
function render() {
requestAnimationFrame(render);
renderer.render(scene, camera);
}
body {
overflow: hidden;
margin: 0;
}
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script>
function Grid(width, height, widthSegments, heightSegments, color) {
width = width || 1;
height = height || 1;
widthSegments = widthSegments || 1;
heightSegments = heightSegments || 1;
color = new THREE.Color(color !== undefined ? color : 0x444444);
var stepWidth = width / widthSegments;
var stepHeight = height / heightSegments;
var halfWidth = width / 2;
var halfHeight = height / 2;
var vertices = [],
colors = [], j = 0;
for (let i = 0, k = -halfHeight; i <= heightSegments; i++, k += stepHeight) {
vertices.push(-halfWidth, k, 0, halfWidth, k, 0);
color.toArray(colors, j); j += 3;
color.toArray(colors, j); j += 3;
}
for (let i = 0, k = -halfWidth; i <= widthSegments; i++, k += stepWidth) {
vertices.push(k, halfHeight, 0, k, -halfHeight, 0);
color.toArray(colors, j); j += 3;
color.toArray(colors, j); j += 3;
}
var geometry = new THREE.BufferGeometry();
geometry.addAttribute('position', new THREE.BufferAttribute(new Float32Array(vertices), 3));
geometry.addAttribute('color', new THREE.BufferAttribute(new Float32Array(colors), 3));
return geometry;
}
</script>
Related
I've tried debugging this multiple MULTIPLE times but can't find a solution to this. So basically, my Earth model and Sun model are not being rendered properly. They are appearing as a dull filled colour. Despite having a texture added to the sphere, the texture is not loading onto it.
I'd say to look at lines 104 - 141 as that's where I'm creating the Sun and Earth models.
Also, would love some help on my Animate function.
Current code:
// Standard Variables / To be changed later.
var scene, camera, renderer //, container;
var W, H;
var delta = Math.delta;
W = parseInt(window.innerWidth);
H = parseInt(window.innerHeight);
camera = new THREE.PerspectiveCamera(45, W / H, 1, 1000000);
camera.position.z = 36300;
scene = new THREE.Scene();
// renderer
renderer = new THREE.WebGLRenderer();
renderer.setSize(W, H);
document.body.appendChild(renderer.domElement);
// Adding Stars.
var starsGeometry = new THREE.Geometry();
var starsMaterial = new THREE.ParticleBasicMaterial({
color: 0xbbbbbbb,
opacity: 0.6,
size: 1,
sizeAttenuation: false
});
var stars;
// Adding stars to the Scene.
for (var i = 0; i < 45000; i++) {
var vertex = new THREE.Vector3();
vertex.x = Math.random() * 2 - 1;
vertex.y = Math.random() * 2 - 1;
vertex.z = Math.random() * 2 - 1;
vertex.multiplyScalar(7000);
starsGeometry.vertices.push(vertex);
}
stars = new THREE.ParticleSystem(starsGeometry, starsMaterial);
stars.scale.set(50, 50, 50);
scene.add(stars);
// ------------------------------------------------------------
var starsGeometry2 = new THREE.Geometry();
var starsMaterial2 = new THREE.ParticleBasicMaterial({
color: 0xbbbbbbb,
opacity: 1,
size: 1,
sizeAttenuation: false
});
var stars2;
// Adding stars to the Scene.
for (var i = 0; i < 10000; i++) {
var vertex = new THREE.Vector3();
vertex.x = Math.random() * 2 - 1;
vertex.y = Math.random() * 2 - 1;
vertex.z = Math.random() * 2 - 1;
vertex.multiplyScalar(7000);
starsGeometry2.vertices.push(vertex);
}
stars2 = new THREE.ParticleSystem(starsGeometry2, starsMaterial2);
stars2.scale.set(70, 150, 100);
scene.add(stars2);
// Ambient light to the Scene.
var ambient = new THREE.AmbientLight(0x222222);
scene.add(ambient);
// ------------------------------------------------------------
//Sun
var sun, gun_geom, sun_mat;
sun_geom = new THREE.SphereGeometry(2300, 80, 80);
//texture.anisotropy = 8;
sun_mat = new THREE.MeshPhongMaterial();
sun = new THREE.Mesh(sun_geom, sun_mat);
sun_mat = THREE.ImageUtils.loadTexture('images/sunmap.jpg');
//sun_mat.bumpMap = THREE.ImageUtils.loadTexture('images/sunmap.jpg');
//sun_mat.bumpScale = 0.05;
//var texture = THREE.ImageUtils.loadTexture('images/sunmap.jpg');
scene.add(sun);
var geometry = new THREE.SphereGeometry(2300, 80, 80);
var texture2 = THREE.ImageUtils.loadTexture('images/earthmap1k.jpg');
var material = new THREE.MeshPhongMaterial({
map: texture2,
emissive: 0xffffff
});
var earth = new THREE.Mesh(geometry, material);
//earth_mat = new THREE.MeshNormalMaterial();
//earth = new THREE.Mesh(earth_geom, earth_mat);
scene.add(earth);
var t = 0;
document.addEventListener('mousemove', function(event) {
y = parseInt(event.offsetY);
});
// Call Animate function within load function.
animate();
function animate() {
requestAnimationFrame(animate);
sun.rotation.y += 0.001;
earth.rotation.y += 1 / 16 * delta;
//camera.position.y = y * 5;
camera.lookAt(scene.position);
t += Math.PI / 180 * 2;
renderer.render(scene, camera);
}
// everything now within `onload`
body {
background: whitesmoke;
margin: 0px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/109/three.min.js"></script>
What I mean:
When I run your code I get all these errors
THREE.ParticleBasicMaterial has been renamed to THREE.PointsMaterial.
THREE.ParticleSystem has been renamed to THREE.Points.
THREE.ParticleBasicMaterial has been renamed to THREE.PointsMaterial.
THREE.ParticleSystem has been renamed to THREE.Points.
THREE.ImageUtils.loadTexture has been deprecated. Use THREE.TextureLoader() instead.
THREE.ImageUtils.loadTexture has been deprecated. Use THREE.TextureLoader() instead.
You should fix those errors
Otherwise not sure what this code was supposed to do
sun_mat = new THREE.MeshPhongMaterial();
sun = new THREE.Mesh(sun_geom, sun_mat);
sun_mat = THREE.ImageUtils.loadTexture('images/sunmap.jpg');
It makes a material, passes it to THREE.Mesh then tries to make a texture that is not used and it re-assigns sun_mat to that texture but sun_mat is used by nothing else.
I changed the code the code to this
const loader = new THREE.TextureLoader();
//Sun
var sun, gun_geom, sun_mat;
sun_geom = new THREE.SphereGeometry(2300, 80, 80);
sun_mat = new THREE.MeshPhongMaterial({
emissive: 0xffffff,
emissiveMap: loader.load('https://threejs.org/examples/textures/waterdudv.jpg'),
});
sun = new THREE.Mesh(sun_geom, sun_mat);
scene.add(sun);
var geometry = new THREE.SphereGeometry(2300, 80, 80);
var texture2 = loader.load('https://threejs.org/examples/textures/planets/earth_atmos_2048.jpg');
var material = new THREE.MeshPhongMaterial({
emissiveMap: texture2,
emissive: 0xffffff,
});
var earth = new THREE.Mesh(geometry, material);
scene.add(earth);
You'll also notice above I changed from using map to emissiveMap. You need to add some lights other than the AmbientLight if you want map to work.
Then the code has the earth and sun the same size and stacked on top each other. I moved the earth
earth.position.set(5000, 0, 0);
Then in the render loop there's this code
earth.rotation.y += 1 / 16 * delta;
but delta is defined as
var delta = Math.delta;
There is no such thing as Math.detla so delta is undefined which means earth.rotation.y += 1 / 16 * delta; just becomes NaN which means the math for the earth breaks so it disappears.
I just set delta = 1.
You might find this articles helpful with your three.js learning as they are up to date with version 109 (they aren't using the outdated classes the code you posted referenced)
// Standard Variables / To be changed later.
var scene, camera, renderer //, container;
var W, H;
var delta = 1.;//Math.delta;
W = parseInt(window.innerWidth);
H = parseInt(window.innerHeight);
camera = new THREE.PerspectiveCamera(45, W / H, 1, 1000000);
camera.position.z = 36300;
scene = new THREE.Scene();
// renderer
renderer = new THREE.WebGLRenderer();
renderer.setSize(W, H);
document.body.appendChild(renderer.domElement);
// Adding Stars.
var starsGeometry = new THREE.Geometry();
var starsMaterial = new THREE.PointsMaterial({
color: 0xbbbbbbb,
opacity: 0.6,
size: 1,
sizeAttenuation: false
});
var stars;
// Adding stars to the Scene.
for (var i = 0; i < 45000; i++) {
var vertex = new THREE.Vector3();
vertex.x = Math.random() * 2 - 1;
vertex.y = Math.random() * 2 - 1;
vertex.z = Math.random() * 2 - 1;
vertex.multiplyScalar(7000);
starsGeometry.vertices.push(vertex);
}
stars = new THREE.Points(starsGeometry, starsMaterial);
stars.scale.set(50, 50, 50);
scene.add(stars);
// ------------------------------------------------------------
var starsGeometry2 = new THREE.Geometry();
var starsMaterial2 = new THREE.PointsMaterial({
color: 0xbbbbbbb,
opacity: 1,
size: 1,
sizeAttenuation: false
});
var stars2;
// Adding stars to the Scene.
for (var i = 0; i < 10000; i++) {
var vertex = new THREE.Vector3();
vertex.x = Math.random() * 2 - 1;
vertex.y = Math.random() * 2 - 1;
vertex.z = Math.random() * 2 - 1;
vertex.multiplyScalar(7000);
starsGeometry2.vertices.push(vertex);
}
stars2 = new THREE.Points(starsGeometry2, starsMaterial2);
stars2.scale.set(70, 150, 100);
scene.add(stars2);
// Ambient light to the Scene.
var ambient = new THREE.AmbientLight(0x222222);
scene.add(ambient);
// ------------------------------------------------------------
const loader = new THREE.TextureLoader();
//Sun
var sun, gun_geom, sun_mat;
sun_geom = new THREE.SphereGeometry(2300, 80, 80);
sun_mat = new THREE.MeshPhongMaterial({
emissive: 0xffffff,
emissiveMap: loader.load('https://i.imgur.com/gl8zBLI.jpg'),
});
sun = new THREE.Mesh(sun_geom, sun_mat);
scene.add(sun);
var geometry = new THREE.SphereGeometry(2300, 80, 80);
var texture2 = loader.load('https://i.imgur.com/BpldqPj.jpg');
var material = new THREE.MeshPhongMaterial({
emissiveMap: texture2,
emissive: 0xffffff,
});
var earth = new THREE.Mesh(geometry, material);
earth.position.set(5000, 0, 0);
scene.add(earth);
var t = 0;
document.addEventListener('mousemove', function(event) {
y = parseInt(event.offsetY);
});
// Call Animate function within load function.
animate();
function animate() {
requestAnimationFrame(animate);
sun.rotation.y += 0.001;
earth.rotation.y += 1 / 16 * delta;
//camera.position.y = y * 5;
camera.lookAt(scene.position);
t += Math.PI / 180 * 2;
renderer.render(scene, camera);
}
// everything now within `onload`
body {
background: whitesmoke;
margin: 0px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/109/three.min.js"></script>
I'm new to three.js and I'm following this tutorial. I've followed the source code in the tutorial correctly but I'm not getting the same animated results. I'm using three.js 86 whereas the tutorial (https://www.youtube.com/watch?v=_Lz268dlvmE) was from 3 years ago. I realise the problem its most likely stems from outdated syntax but I'm struggling to find the related updates.
I want the vertices in the bottom sphere to drop away as the sphere above rises on the y-axis. Here's my code with the vertex animations detailed under draw() towards the bottom. I've excluded the HTML to just show the JavaScript.
Thanks!
var scene = new THREE.Scene();
var start_breaking=0;
var w = window.innerWidth, h = window.innerHeight;
var camera = new THREE.PerspectiveCamera(45, w/h, 0.1, 10000);
camera.position.set(0,100,400);
var renderer = new THREE.WebGLRenderer();
document.body.appendChild(renderer.domElement);
renderer.setSize(w,h);
var geometry = new THREE.SphereGeometry(70,64,64);
var colors = [];
for (var i = 0; i < geometry.vertices.length; i++) {
colors[i] = new THREE.Color();
colors[i].setRGB(Math.random(),Math.random(),Math.random());
}
geometry.colors = colors;
material = new THREE.PointsMaterial({
size:7,
vertexColors: true
});
particleSystem = new THREE.Points(geometry, material);
particleSystem.position.y = 100;
scene.add(particleSystem);
function create_particles() {
var geomx = new THREE.Geometry();
geomx.colors = colors;
var materiax = new THREE.PointsMaterial({
size: 5,
vertexColors: true
});
var verticex = particleSystem.geometry.vertices;
verticex.forEach(function (p) {
var particle = new THREE.Vector3(
p.x * 1.0,
p.y * 1.0,
p.z * 1.0
);
geomx.vertices.push(particle);
});
particleSystemx = new THREE.Points(geomx, material);
particleSystemx.sortParticles = true;
scene.add(particleSystemx);
}
create_particles();
renderer.render(scene, camera);
setTimeout(draw, 500);
function draw() {
particleSystem.rotation.y += 0.0075;
particleSystem.position.y += 0.275;
if (particleSystem.position.y <= 181 && particleSystem.position >= 180.7) {
create_particles();
//scene.remove(particleSystem);
start_breaking=1;
}
if (start_breaking) {
var vertices = particleSystemx.geometry.vertices;
vertices.forEach(function (v){
v.y -= v.vy;
v.x -= v.vx;
v.z -= v.vz;
});
}
renderer.render(scene, camera);
requestAnimationFrame(function() {draw(); });
}
I am creating a geometry in THREE.js:
var dotGeometry = new THREE.Geometry();
dotGeometry.dynamic = true;
var createDot = function (group, x, y, z){
group.vertices.push(new THREE.Vector3( x, y, z));
}
var width = 300;
var height = 300;
var gap = 0.1;
for(var i = 0; i < width; i++){
for(var j = 0; j < height; j++){
createDot(dotGeometry, i*gap, j*gap, 0);
}
}
as long as I use the points material, everything works fine - I can see my geometry:
var dotMaterial = new THREE.PointsMaterial( { size: 1, color: 0xffffff, sizeAttenuation: false } );
var dot = new THREE.Points( dotGeometry, dotMaterial );
scene.add( dot );
but as soon as I want to use any other material to see something like a "solid" surface, I can't see anything, for example:
var dotMaterial = new THREE.MeshPhongMaterial( { color: 0xffffff } );
var dot = new THREE.Points( dotGeometry, dotMaterial );
scene.add( dot );
does geometry only work together with PointsMaterial or what am I doing wrong?
Example 1: Working
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
var renderer = new THREE.WebGLRenderer();
var light = new THREE.PointLight(0xffffff, 1);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var dotGeometry = new THREE.Geometry();
dotGeometry.dynamic = true;
var createDot = function (group, x, y, z){
group.vertices.push(new THREE.Vector3( x, y, z));
}
var width = 300;
var height = 300;
var gap = 0.1;
for(var i = 0; i < width; i++){
for(var j = 0; j < height; j++){
createDot(dotGeometry, i*gap, j*gap, 0);
}
}
var dotMaterial = new THREE.PointsMaterial( { size: 1, color: 0xffffff, sizeAttenuation: false } );
var dot = new THREE.Points( dotGeometry, dotMaterial );
scene.add( dot );
scene.add(light);
camera.position.z = 5;
light.position.y = 2;
light.position.z = 5;
light.position.x = 0;
var render = function() {
requestAnimationFrame(render);
dot.rotation.x += 0.01;
dot.rotation.y += 0.01;
renderer.render(scene, camera);
};
render();
body {
margin: 0;
}
canvas {
width: 100%;
height: 100%
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/87/three.min.js"></script>
Example 2: Not working
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
var renderer = new THREE.WebGLRenderer();
var light = new THREE.PointLight(0xffffff, 1);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var dotGeometry = new THREE.Geometry();
dotGeometry.dynamic = true;
var createDot = function (group, x, y, z){
group.vertices.push(new THREE.Vector3( x, y, z));
}
var width = 300;
var height = 300;
var gap = 0.1;
for(var i = 0; i < width; i++){
for(var j = 0; j < height; j++){
createDot(dotGeometry, i*gap, j*gap, 0);
}
}
var dotMaterial = new THREE.MeshPhongMaterial( { color: 0xffffff } );
var dot = new THREE.Points( dotGeometry, dotMaterial );
scene.add( dot );
scene.add(light);
camera.position.z = 5;
light.position.y = 2;
light.position.z = 5;
light.position.x = 0;
var render = function() {
requestAnimationFrame(render);
dot.rotation.x += 0.01;
dot.rotation.y += 0.01;
renderer.render(scene, camera);
};
render();
body {
margin: 0;
}
canvas {
width: 100%;
height: 100%
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/87/three.min.js"></script>
Thanks for any help!
Something you could do is use your geometry.vertices to populate a ConvexGeometry (you will need to link to ConvexGeometry.js and QuickHull.js).
You create your geometry as you did before
dotGeometry.vertices.push(new THREE.Vector3(0, 0, 0));
Then you will need to pass that onto your ConvexGeometry like so:
var geometry = new THREE.ConvexGeometry(dotGeometry.vertices);
After that, you apply your material as usual.
var material = new THREE.MeshPhongMaterial({
color: 0xffffff
});
var mesh = new THREE.Mesh(geometry, material);
Here's an example in CodePen;
This is assuming you need a convex shape. If you just need a plane, use a PlaneGeometry.
r87
I have seen voxel js, but it seems to be outdated, and it uses node js, which I do not want to use. I want to generate simple terrain using for loops, and my function to create a block.
Here is my function:
function createBlock(block, x, y, z, top, bottom, front, back, left, right) {
var geometry;
var meshFaceMaterial;
var mesh;
var material;
var blockObj = {};
if (top == true) {
geometry = new THREE.PlaneGeometry(1, 1);
material = new THREE.MeshPhongMaterial({map: THREE.ImageUtils.loadTexture(blocks[block].top)});
meshFaceMaterial = new THREE.MeshFaceMaterial(material);
mesh = new THREE.Mesh(geometry, meshFaceMaterial);
mesh.position.z = z;
mesh.position.x = x;
mesh.position.y = y+5;
mesh.rotation.x = (-90 * Math.PI)/180;
blockObj.top = mesh;
}
if (bottom == true) {
geometry = new THREE.PlaneGeometry(1, 1);
material = new THREE.MeshPhongMaterial({map: THREE.ImageUtils.loadTexture(blocks[block].bottom)});
meshFaceMaterial = new THREE.MeshFaceMaterial(material);
mesh = new THREE.Mesh(geometry, meshFaceMaterial);
mesh.position.z = z;
mesh.position.x = x;
mesh.position.y = y-5;
mesh.rotation.x = (90 * Math.PI)/180;
blockObj.bottom = mesh;
}
if (back == true) {
geometry = new THREE.PlaneGeometry(1, 1);
material = new THREE.MeshPhongMaterial({map: THREE.ImageUtils.loadTexture(blocks[block].side)});
meshFaceMaterial = new THREE.MeshFaceMaterial(material);
mesh = new THREE.Mesh(geometry, meshFaceMaterial);
mesh.position.z = z-5;
mesh.position.x = x;
mesh.position.y = y;
mesh.rotation.y = (180 * Math.PI)/180;
blockObj.back = mesh;
}
if (right == true) {
geometry = new THREE.PlaneGeometry(1, 1);
material = new THREE.MeshPhongMaterial({map: THREE.ImageUtils.loadTexture(blocks[block].side)});
meshFaceMaterial = new THREE.MeshFaceMaterial(material);
mesh = new THREE.Mesh(geometry, meshFaceMaterial);
mesh.position.z = z;
mesh.position.x = x+5;
mesh.position.y = y;
mesh.rotation.y = (90 * Math.PI)/180;
blockObj.right = mesh;
}
if (left == true) {
geometry = new THREE.PlaneGeometry(1, 1);
material = new THREE.MeshPhongMaterial({map: THREE.ImageUtils.loadTexture(blocks[block].side)});
meshFaceMaterial = new THREE.MeshFaceMaterial(material);
mesh = new THREE.Mesh(geometry, meshFaceMaterial);
mesh.position.z = z;
mesh.position.x = x-5;
mesh.position.y = y;
mesh.rotation.y = (-90 * Math.PI)/180;
blockObj.left = mesh;
}
if (front == true) {
geometry = new THREE.PlaneGeometry(1, 1);
material = new THREE.MeshPhongMaterial({map: THREE.ImageUtils.loadTexture(blocks[block].side)});
meshFaceMaterial = new THREE.MeshFaceMaterial(material);
mesh = new THREE.Mesh(geometry, meshFaceMaterial);
mesh.position.z = z+5;
mesh.position.x = x;
mesh.position.y = y;
blockObj.front = mesh;
}
blockObjects.push(blockObj);
return blockObj;
}
Any help would be appreciated.
Here is an algorithm that creates cubes and builds a random terrain with them. In this case I have fixed the terrain height change to be at most one cube height higher than the adjacent cubes. I have randomly generated a green color for each cube but you could obviously apply whatever texture you have in mind.
var camera, scene, renderer;
var mesh;
var cubesize = 30;
var landscape_width = 30;
var landscape_length = 30;
var heights = [];
var camera_offset = cubesize * landscape_width *0.7;
var camera_height = cubesize * landscape_width / 2;
function init() {
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.set(0,camera_offset,camera_height);
camera.up = new THREE.Vector3(0,0,1);
camera.lookAt(new THREE.Vector3(0,0,0));
scene = new THREE.Scene();
geom = new THREE.CubeGeometry( cubesize, cubesize, cubesize );
cubes = new THREE.Object3D();
scene.add( cubes );
var xoff = landscape_width * cubesize / 2;
var yoff = landscape_length * cubesize / 2;
for(var i=0; i<landscape_width; i++) heights[i,0] = 0;
for(var j=0; j<landscape_length; j++) heights[0,j] = 0;
for(var i=1; i<landscape_width; i++) {
var h = heights[i-1,0];
for(var j=1; j< landscape_length; j++ ) {
var rand = Math.random();
if(heights[i-1,j] == heights[i,j-1]) { // level ground, go up dn or stay
if(rand < 0.33)
heights[i,j] = heights[i-1,j] - cubesize;
else if (rand > 0.66)
heights[i,j] = heights[i-1,j] + cubesize;
else
heights[i,j] = heights[i-1,j];
}
else if(Math.abs(heights[i-1,j] - heights[i,j-1]) > cubesize) { // two edges are wide apart, split the difference
heights[i,j] = (heights[i-1,j] +heights[i,j-1])/2;
}
else {
if(rand > 0.5)
heights[i,j] = heights[i-1,j];
else
heights[i,j] = heights[i,j-1];
}
var grayness = Math.random() * 0.5 + 0.25,
mat = new THREE.MeshBasicMaterial(),
cube = new THREE.Mesh( geom, mat );
mat.color.setRGB( 0, grayness, 0 );
cube.position.set( i*cubesize - xoff, j*cubesize - yoff, heights[i,j] );
cubes.add( cube );
}
}
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
//
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
var angle = 0;
function animate() {
angle += 0.5;
var rads = angle * Math.PI /180;
camera.position.set(Math.cos(rads)*camera_offset,Math.sin(rads)*camera_offset,camera_height);
camera.lookAt(scene.position);
requestAnimationFrame( animate );
renderer.render( scene, camera );
}
init();
animate();
body {
margin: 0px;
background-color: #000000;
overflow: hidden;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/85/three.js"></script>
If i understand your question, you're asking for loops that will call you function over 3 axis x, y, z.
You could do something like this:
for (var i = 0; i < SIZEX; i++) {
for (var j = 0; j < SIZEY; j++) {
for (var k = 0; k < SIZEZ; k++) {
createBlock(block, i, j, k, (k == SIZEZ-1), (k == 0), (j == SIZEY-1), (j == 0), (i == SIZEX-1), (i == 0));
}
}
}
This code will navigate in a 3 dimensions.
If (k == SIZEZ-1) is true, then top will be true in your function. Same for all the other.
I don't know what block is.
I hope that what you were looking for.
I'm creating a function createCylinder(n, len, rad) that is called from function createScene(). I have checked that the vertices and faces are added and I get no errors. However, the geometry is not rendered. I suppose this has to do with the timing of returning the geometry or returning the mesh and adding it to the scene. That being said, I have tried everything I could think of and found no solution. Can someone please help me figure this out? Thanks in advance!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Cylinder</title>
</head>
<script type="text/javascript" src="three.js"></script>
<script type="text/javascript" src="OrbitControls.js"></script>
<style>
body {
/* set margin to 0 and overflow to hidden, to go fullscreen */
margin: 0;
overflow: hidden;
}
</style>
<body>
<div id="container">
</div>
<div id="msg">
</div>
<script type="text/javascript">
var camera, scene, renderer;
var cameraControls;
var clock = new THREE.Clock();
var isCappedBottom = false;
var isCappedTop = false;
function createCylinder(n, len, rad) {
var geometry = new THREE.Geometry();
var radius = rad;
var length = len;
var yUp = length / 2;
var yDown = -length / 2;
var theta = (2.0 * Math.PI) / n;
for (var i = 0; i < n ; i++) { //runs n + 2 times if we allow redundant vertices
var x = radius * Math.cos(i * theta);
var z = radius * Math.sin(i * theta);
//Top to bottom
var originUp = new THREE.Vector3(x, yUp, z);
var originDown = new THREE.Vector3(x, yDown, z);
geometry.vertices.push(originUp); //0
geometry.vertices.push(originDown); //1
console.log("Vertices " + geometry.vertices.length);
}//end of first for loop
// Draw faces
for (var j = 0; j < 2*n; j+= 2) {
var face1 = new THREE.Face3(j, j + 1, j + 2);
var face2 = new THREE.Face3(j + 1, j + 3, j + 2);
geometry.faces.push(face1);
geometry.faces.push(face2);
console.log("faces " + geometry.faces.length);
}
// return geometry;
//scene.add(geometry);
var material = new THREE.MeshLambertMaterial({color: 0xFF0000, side: THREE.DoubleSide});
var mesh = new THREE.Mesh(geometry, material);
return mesh;
scene.add(mesh);
// add subtle ambient lighting
var ambientLight = new THREE.AmbientLight(0x222222);
scene.add(ambientLight);
var light = new THREE.PointLight(0xFFFFFF, 1, 1000);
light.position.set(0, 10, 20);
scene.add(light);
var light2 = new THREE.PointLight(0xFFFFFF, 1, 1000);
light2.position.set(0, -10, -10);
scene.add(light2);
} //End of function
function createScene() {
var cyl = createCylinder(10, 10, 2);
return cyl;
scene.add(cyl);
}
function animate() {
window.requestAnimationFrame(animate);
render();
}
function render() {
var delta = clock.getDelta();
cameraControls.update(delta);
renderer.render(scene, camera);
}
function init() {
var canvasWidth = window.innerWidth;
var canvasHeight = window.innerHeight;
var canvasRatio = canvasWidth / canvasHeight;
scene = new THREE.Scene();
renderer = new THREE.WebGLRenderer({antialias: true, preserveDrawingBuffer: true});
renderer.gammaInput = true;
renderer.gammaOutput = true;
renderer.setSize(canvasWidth, canvasHeight);
renderer.setClearColor(0x000000, 1.0);
renderer.shadowMapEnabled = true;
camera = new THREE.PerspectiveCamera( 40, canvasRatio, 1, 1000);
/* camera.position.z = 5;
camera.lookAt(scene.position); */
camera.position.set(0, 0, 12);
camera.lookAt(new THREE.Vector3(0, 0, 0));
cameraControls = new THREE.OrbitControls(camera, renderer.domElement);
}
function addToDOM() {
var container = document.getElementById('container');
var canvas = container.getElementsByTagName('canvas');
if (canvas.length>0) {
container.removeChild(canvas[0]);
}
container.appendChild( renderer.domElement );
}
init();
createScene();
addToDOM();
render();
animate();
</script>
</body>
</html>
In the createCylinder function:
var mesh = new THREE.Mesh(geometry, material);
return mesh; // this line must be the last line in the function
// after return(), the rest of the code is unreacheable
//scene.add(mesh); // this line should be deleted as you add the mesh in the createScene() function
and then the createScene function should be like this:
function createScene() {
var cyl = createCylinder(10, 10, 2);
//return cyl;
scene.add(cyl);
}
jsfiddle example