I already asked a Question here: Add Thickness to faces
The core question is solved but i ran into another problem.
Before my walls were set on side:THREE.BackSide so that they didnt show when they faced the camera but now when they have a thickness that doesnt work anymore and i dont realy understand why.
Before:
Before
After: After
How can i make the thick walls behave like the Plane walls ?
A very rough concept of controlling the visibility of a wall (I've slightly changed translating and positioning of a geometry):
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(0, 5, 5);
camera.lookAt(scene.position);
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.GridHelper(10, 10));
var points = [
new THREE.Vector3(-2, 0, 2),
new THREE.Vector3(2, 0, 2),
new THREE.Vector3(2, 0, -2),
new THREE.Vector3(-2, 0, -2)
]
var walls = [];
points.forEach((p, idx, points) => {
let nextIdx = idx === points.length - 1 ? 0 : idx + 1;
buildWall(p, points[nextIdx], 2, 0.1);
});
function buildWall(pointStart, pointEnd, height, thickness) {
var boxW = pointEnd.clone().sub(pointStart).length();
var boxH = height;
var boxD = thickness;
var boxGeometry = new THREE.BoxGeometry(boxW, boxH, boxD);
boxGeometry.translate(0, boxH * 0.5, 0);
boxGeometry.rotateY(-Math.PI * 0.5);
var wall = new THREE.Mesh(boxGeometry, new THREE.MeshBasicMaterial({
color: "aqua",
wireframe: true
}));
wall.position.copy(pointStart).add(pointEnd).multiplyScalar(0.5);
wall.lookAt(pointEnd);
scene.add(wall);
walls.push(wall);
}
var currentPosition = new THREE.Vector3();
render();
function render() {
requestAnimationFrame(render);
walls.forEach(w => {
w.visible = currentPosition.copy(w.position).sub(camera.position).lengthSq() > camera.position.lengthSq();
})
renderer.render(scene, camera);
}
body {
overflow: hidden;
margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/91/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
Related
I want to create a cylinder with slanted bottom shape in three.js.
I don't see any direct way to create such geometry in three.js. I tried to see if I can cut the cylinder by a slanted plane, but could not find such operation in the documentation. Can anybody suggest a way to create this?
You can operate with vertices as you want.
Just a simple concept:
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(0, 0, 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);
var light = new THREE.DirectionalLight(0xffffff, 0.5);
light.position.setScalar(10);
scene.add(light);
scene.add(new THREE.AmbientLight(0xffffff, 0.5));
var cylGeom = new THREE.CylinderBufferGeometry(1, 1, 5, 16);
var vertices = cylGeom.attributes.position;
// change upper vertices
var v3 = new THREE.Vector3(); // temp vector
for (let i = 0; i < vertices.count; i++) {
v3.fromBufferAttribute(vertices, i); // set the temp vector
v3.y = v3.y > 0 ? (v3.x * 0.5) + 2.5 : v3.y; // change position by condition and equation
vertices.setY(i, v3.y); // set Y-component of a vertex
}
var cylMat = new THREE.MeshLambertMaterial({
color: "aqua"
});
var cyl = new THREE.Mesh(cylGeom, cylMat);
scene.add(cyl);
renderer.setAnimationLoop(() => {
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>
QUESTION:
So I came across this:
https://skin-tracker.com/pubg/outfit?no=000000000000000000000000000&set=1&char=1
I have the central ground area which is textured already in my code. But I have no idea how to make it extend up to the horizon like seen in the link.
It seems the person who coded what you see in the link hit some kind of limitation and had to use a single color for what extends beyond the central floor area.
How can I make my floor extend to the horizon/ create a skyline ?
CODE:
var floorTexture = new THREE.ImageUtils.loadTexture( '../../public/assets/grassTile.jpg' );
floorTexture.wrapS = floorTexture.wrapT = THREE.RepeatWrapping;
floorTexture.repeat.set( 10, 10 );
var floorMaterial = new THREE.MeshBasicMaterial({ map: floorTexture, side: THREE.DoubleSide });
var floorGeometry = new THREE.PlaneGeometry(1000, 1000, 10, 10);
var mesh = new THREE.Mesh(floorGeometry, floorMaterial);
mesh.rotation.x = - Math.PI / 2;
mesh.receiveShadow = true;
scene.add( mesh );
You can simply create an enormous textured plane. I found no limitations with the example below. If you implement something like this and encounter errors/problems, update your question with the errors you're seeing.
// prepare the renderer
let WIDTH
let HEIGHT
let aspectRatio = function() {
return WIDTH / HEIGHT
}
const renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true
})
document.body.appendChild(renderer.domElement)
const camera = new THREE.PerspectiveCamera(32, aspectRatio(), 1, 1000)
camera.position.set(0, 10, 50)
function resize() {
WIDTH = window.innerWidth
HEIGHT = window.innerHeight
renderer.setSize(WIDTH, HEIGHT)
camera.aspect = aspectRatio()
camera.updateProjectionMatrix()
}
resize()
window.addEventListener("resize", resize)
const scene = new THREE.Scene()
const light = new THREE.DirectionalLight(0xffffff, 1, Infinity)
light.position.set(0, 0, 1)
camera.add(light)
scene.add(camera)
const sun = new THREE.DirectionalLight(0xffffcc)
sun.position.set(0, 1, 0)
scene.add(sun)
// populate the scene
let geo = new THREE.BoxBufferGeometry(10, 10, 10)
let mat = new THREE.MeshLambertMaterial({
color: "red"
})
let mesh = new THREE.Mesh(geo, mat)
scene.add(mesh)
let tex = new THREE.TextureLoader().load("https://upload.wikimedia.org/wikipedia/commons/4/4c/Grass_Texture.png")
tex.anisotropy = 32
tex.repeat.set(100, 100)
tex.wrapT = THREE.RepeatWrapping
tex.wrapS = THREE.RepeatWrapping
geo = new THREE.PlaneBufferGeometry(10000, 10000)
mat = new THREE.MeshLambertMaterial({
map: tex
})
mesh = new THREE.Mesh(geo, mat)
mesh.position.set(0, -5, 0)
mesh.rotation.set(Math.PI / -2, 0, 0)
scene.add(mesh)
let axis = new THREE.Vector3(0, 1, 0)
function updateCamera() {
camera.position.applyAxisAngle(axis, 0.01)
}
// rendering functions
function render() {
renderer.render(scene, camera)
camera.lookAt(scene.position)
}
let animationLoopId = null
function animationLoop() {
animationLoopId = requestAnimationFrame(animationLoop)
updateCamera()
render()
}
animationLoop()
html,
body {
padding: 0;
margin: 0;
overflow: hidden;
background: skyBLue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/97/three.js"></script>
I'm new in three.js, and my first feature was to create a box geometry which can increased from only one side.
Problem : When you increase width or height of an object the two sides automatically increased.
jsFiddle Example
So i lost 1 hour, to find the good algorythm :
geometry = new THREE.BoxGeometry(strength, 200, 200);
material = new THREE.MeshBasicMaterial({
color: 0xff0000
});
mesh = new THREE.Mesh(geometry, material);
mesh.applyMatrix( new THREE.Matrix4().makeTranslation( - strength + strength / 2, 0, 0 ) );
Someone can explain me: - strength + strength / 2 (If i increase the strength by 1 the translation is only -0.5 not -1 ?)
What is the name of this sort of algorythm, where i can find good ressources to learn this purpose (beginner)?
Also, you can shift the geometry with .translate() method, thus you won't have a container object in the scene graph:
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(2, 3, 5);
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.GridHelper(10, 10));
var boxGeom = new THREE.BoxGeometry();
boxGeom.translate(0.5, 0.5, 0); // pivot point is shifted
var box = new THREE.Mesh(boxGeom, new THREE.MeshNormalMaterial());
scene.add(box);
var clock = new THREE.Clock();
var delta = 0;
var time = 0;
render();
function render() {
requestAnimationFrame(render);
delta = clock.getDelta();
time += delta;
box.scale.set(2.5 + Math.sin(time) * 2, 1.5, 1.5);
renderer.render(scene, camera);
}
body {
overflow: hidden;
margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/95/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
Another option:
var container = new THREE.Object3D()
var boxMesh = new THREE.Mesh(new THREE.BoxGeometry(1,1,1));
boxMesh.position.set(0.5,0.5,0.5)
container.add(boxMesh)
scene.add(container)
container.scale.set(strength,200,200);
https://en.wikipedia.org/wiki/Scene_graph
I am loading in an STL file with the STLLoader() in Three.js and am transforming it into a mesh. Now, I would like to color each cube of my mesh based on its height, as in the image attached here screenshot-color-by-height. Is this possible within Three.js and if so, what would be the best approach? The actual model is here:
https://casagroupproject.github.io/subpage1.html
Just a concept of how you can make it with colors of vertices:
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(2, 5, 10);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var controls = new THREE.OrbitControls(camera, renderer.domElement);
var light = new THREE.DirectionalLight(0xffffff, 0.5);
light.position.setScalar(10);
scene.add(light);
scene.add(new THREE.AmbientLight(0xffffff, 0.5));
var planeGeom = new THREE.PlaneBufferGeometry(10, 10, 10, 10);
planeGeom.rotateX(-Math.PI * 0.5);
var yMin = 0;
var yMax = 2;
var colors = [];
for (let i = 0; i < planeGeom.attributes.position.count; i++) {
let yVal = THREE.Math.randInt(yMin, yMax);
let yNorm = (yVal - yMin) / (yMax - yMin);
planeGeom.attributes.position.setY(i, yVal);
colors.push(yNorm, yNorm, 1);
}
planeGeom.addAttribute('color', new THREE.BufferAttribute(new Float32Array(colors), 3));
planeGeom.computeVertexNormals();
var mesh = new THREE.Mesh(planeGeom, new THREE.MeshStandardMaterial({
vertexColors: THREE.VertexColors
}));
scene.add(mesh)
render();
function render() {
requestAnimationFrame(render);
renderer.render(scene, camera);
}
body {
overflow: hidden;
margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/92/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
Is there any way to use the ExtrudeGeometry with the ParametricGeometry?
Like this:
function exampleGeometryF(u,v){
var x = -(width/2) + width * u;
var y = -(height/2) + height *v;
var z = (Math.sin(u*Math.PI))* -20;
return new THREE.Vector3(x,y,z);
}
let parametricGeometry = new THREE.ParametricGeometry(exampleGeometryF, 100, 100);
let extrudedGeometry = new THREE.ExtrudeGeometry(parametricGeometry, {amount:10, ...});
So the parametricGeometry in this Example describes a plane like Geometry. Now I want to give this Geometry a depth.
Workarounds are welcome!
Specifically for a plane-like geometry with some "depth", you can deform a box geometry:
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.setScalar(3);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var controls = new THREE.OrbitControls(camera, renderer.domElement);
var boxGeom = new THREE.BoxGeometry(2, 2, 3, 10, 10, 1);
boxGeom.vertices.forEach(v => {
v.z += Math.cos(v.x * 2) * Math.sin(v.y * 2) * 0.125;
});
var deformed = new THREE.Mesh(boxGeom, new THREE.MeshBasicMaterial({
color: "aqua",
wireframe: true
}));
scene.add(deformed);
render();
function render() {
requestAnimationFrame(render);
renderer.render(scene, camera);
}
body {
overflow: hidden;
margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/90/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>