now im learning about Three JS and now im in blocker that my expectation should be like this:
but now my code not shows any view, where my code was like this:
import { useEffect } from "react/cjs/react.development";
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
export default () => {
useEffect(() => {
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
1,
1000
);
const canvas = document.querySelector("canvas.background");
let renderer = new THREE.WebGLRenderer({ canvas, antialias: true });
new OrbitControls(camera, renderer.domElement);
const img = new Image();
let texture = new THREE.Texture(img);
img.onload = () => {
texture.needsUpdate = true;
const material = new THREE.PointsMaterial({
size: 20,
map: texture,
blending: THREE.AdditiveBlending,
transparent: true,
depthTest: false,
});
const particle = new THREE.Sprite(material);
particle.scale.x = particle.scale.y = 1;
scene.add(particle);
};
img.src = "/flower.png";
scene.add(camera);
camera.position.z = 3;
const animate = () => {
const elapsedTime = new THREE.Clock().getElapsedTime();
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.render(scene, camera);
requestAnimationFrame(animate);
};
animate();
}, []);
return <canvas className="background" />;
};
I tried different answers from forum, but seems doesn't works for me
could you guys help? I'll appreciate
You can't use THREE.PointsMaterial with THREE.Sprite. THREE.PointsMaterial is intended for THREE.Points. Use THREE.SpriteMaterial instead.
Related
I want to activate/deactivate the DragControls depending on the value of a flag drag_flag, but my approach doesn't work well!
can you please tell me how can I do that properly? thanks in advance.
var drag_flag = true;
function change_drag_flag(){
drag_flag = !drag_flag;
}
var objects = [];
var scene = new THREE.Scene();
let box_geometry = new THREE.BoxGeometry(1, 1, 1);
var material = new THREE.MeshPhongMaterial();
const box = new THREE.Mesh(box_geometry, material);
objects.push(box);
scene.add(box);
var spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(5, 5, 5);
scene.add(spotLight);
spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(-5, 5, 5);
scene.add(spotLight);
var camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
camera.position.set(0.1, 4, 1);
camera.lookAt(scene.position);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var drag_controls = new THREE.DragControls(objects, camera, renderer.domElement);
if(drag_flag===true){
drag_controls.activate();
drag_controls.enabled = true;
}
else{
drag_controls.deactivate();
drag_controls.enabled = false;
}
renderer.render(scene, camera);
<button type="button" onclick="change_drag_flag()">Change Drag Flag</button>
<script src="https://cdn.jsdelivr.net/npm/three#0.101.1/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three#0.101.1/examples/js/controls/DragControls.js"></script>
You are rendering your scene only once so you don't see the effect of enabling/disabling the controls. I've slightly rewritten your code to make things work:
const objects = [];
const scene = new THREE.Scene();
const box_geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshPhongMaterial();
const box = new THREE.Mesh(box_geometry, material);
objects.push(box);
scene.add(box);
const spotLight1 = new THREE.SpotLight(0xffffff);
spotLight1.position.set(5, 5, 5);
scene.add(spotLight1);
const spotLight2 = new THREE.SpotLight(0xffffff);
spotLight2.position.set(-5, 5, 5);
scene.add(spotLight2);
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
camera.position.set(0.1, 4, 1);
camera.lookAt(scene.position);
const renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
const dragControls = new THREE.DragControls(objects, camera, renderer.domElement);
function toggleDrag() {
dragControls.enabled = !dragControls.enabled;
}
function animate() {
requestAnimationFrame(animate);
if (dragControls.enabled === true) {
dragControls.activate();
} else {
dragControls.deactivate();
}
renderer.render(scene, camera);
}
animate();
body {
margin: 0;
}
<button type="button" onclick="toggleDrag()" style="position:absolute">Change Drag Flag</button>
<script src="https://cdn.jsdelivr.net/npm/three#0.101.1/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three#0.101.1/examples/js/controls/DragControls.js"></script>
The plan is for it to draw borders using GeoJSON coords. Also when I write coordinates directly into the same file it works normally and I've noticed that my fbih variable doesn't get the fbih: THREE.Vector3 when hovered over. I'm using ViteJS + ThreeJS, Here's the code:
import './style.css'
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import { Vector3 } from 'three';
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(20);
renderer.render(scene,camera);
const teksturazemlje = new THREE.TextureLoader().load('slike/zemlja.png')
const zemlja = new THREE.Mesh (
new THREE.SphereGeometry(16, 500, 500 ),
new THREE.MeshStandardMaterial({
map:teksturazemlje,
})
);
scene.add(zemlja)
function koordinate([lon,lat]){
var phi = (90-lat)*(Math.PI/180);
var theta = (lon+180)*(Math.PI/180);
var x = -((16) * Math.sin(phi)*Math.cos(theta));
var z = ((16) * Math.sin(phi)*Math.sin(theta));
var y = ((16) * Math.cos(phi));
return new THREE.Vector3(x,y,z)
}
const boja = new THREE.MeshBasicMaterial({
color: 0xff00cc,
side : THREE.DoubleSide,
});
var fbih = [];
fetch ('granice/bih.json')
.then (res => res.json())
.then (data => {
for (let element of data.features[0].geometry.coordinates[0][0]) {
fbih.push(koordinate(element))
}
});
console.log(fbih)
const linije = new THREE.BufferGeometry().setFromPoints(fbih)
const line = new THREE.Line(linije,boja)
scene.add(line);
const ambientlight= new THREE.AmbientLight(0xffffff);
scene.add(ambientlight)
const controls = new OrbitControls(camera, renderer.domElement);
function animate(){
requestAnimationFrame(animate);
controls.update();
renderer.render (scene, camera);
}
controls.enableDamping = true;
controls.dampingFactor = 0.04;
controls.rotateSpeed = 0.07;
controls.maxDistance = 20;
controls.minDistance = 16.5;
controls.enablePan = false;
controls.zoomSpeed = 0.30;
animate()
It displays Vector3 array in console.log but it isn't displayed through BufferGeometry. Sorry if there are grammatical errors, English isn't my first language.
Im trying to apply Texture to my sphere using Three.js. I'm running a Python server.
Console prints Success! image-size: 1024 x 1024. Can't figure out what the problem is.
Main.js:
const scene = new THREE.Scene()
const geometry = new THREE.BoxGeometry(1, 1, 1)
const texture = texLoader.load('Fabric_Lace_026_height.png',
// On success
function(texture) {
console.log("Success!");
console.log(texture);
},
// Progress (ignored)
undefined,
// On error
function(err) {
console.log("Error");
console.log(err);}
);
const material = new THREE.MeshBasicMaterial({map: texture})
const mesh = new THREE.Mesh(geometry, material)
scene.add(mesh)
const sizes = {width: window.innerWidth,height: window.innerHeight}
const camera = new THREE.PerspectiveCamera(75, sizes.width /sizes.height, 1, 1000)
camera.position.z = 3
const canvas = document.querySelector('canvas.webgl')
const renderer = new THREE.WebGLRenderer({canvas: canvas})
renderer.setSize(sizes.width, sizes.height)
renderer.render(scene, camera)
You are rendering your scene too early. Since you have no animation loop, you have to call render() when the texture is fully loaded. Try it like so:
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.z = 3;
//
const loader = new THREE.TextureLoader();
const texture = loader.load('https://threejs.org/examples/textures/uv_grid_opengl.jpg',
// On success
function(texture) {
renderer.render(scene, camera); // FIX
},
// Progress (ignored)
undefined,
// On error
function(err) {
console.log(err);
}
);
//
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial({map: texture});
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
//
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
body {
margin: 0;
}
<script src="//cdn.rawgit.com/mrdoob/three.js/master/build/three.min.js"></script>
I'm trying to implement WEBGL and CSS3DRenderer. I'm trying to simulate a HTML page on the CSS3DRenderer and "insert" or "position" this CSS into the imported GLB model.
I want to create a "HTML page" and insert it into the curved glb model
This is my code
import './style.css'
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
import { CSS3DRenderer, CSS3DObject } from 'three/examples/jsm/renderers/CSS3DRenderer.js';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js';
const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(200, 120, 300);
// Scene
const scene = new THREE.Scene();
const scene2 = new THREE.Scene();
scene.background = new THREE.Color(0xf0f0f0);
// Renderer
const renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
const renderer2 = new CSS3DRenderer();
renderer2.setSize(window.innerWidth, window.innerHeight);
renderer2.domElement.style.position = 'absolute';
renderer2.domElement.style.top = 0;
renderer2.domElement.style.bottom = 0;
document.body.appendChild(renderer2.domElement);
const controls = new OrbitControls(camera, renderer2.domElement);
window.addEventListener('resize', onWindowResize);
const material = new THREE.MeshBasicMaterial({
color: 0x000000,
wireframe: true,
wireframeLinewidth: 1,
side: THREE.DoubleSide
});
// WEbgl
// const geometry = new THREE.PlaneGeometry(100, 100);
// const mesh = new THREE.Mesh(geometry, material);
// mesh.position.copy(object.position);
// mesh.rotation.x = 0;
// mesh.scale.copy(object.scale);
// mesh.position.x = 9;
// scene.add(mesh);
// CSS3dElement
// const element = document.createElement(`div`);
// element.innerHTML = `Tutorix is the best e-learning platform Tutorix is the best e-learning platform Tutorix is the best e-learning platform`;
// element.style.width = '100px';
// element.style.height = '100px';
// element.style.overflowY = 'auto';
// element.style.background = new THREE.Color(0x00F0FF).getStyle();
// const object = new CSS3DObject(element);
// object.position.copy(mesh.position);
// object.rotation.copy(mesh.rotation);
// object.scale.copy(mesh.scale);
// scene2.add(object);
// scene
const dracoLoader = new DRACOLoader();
dracoLoader.setDecoderPath('/draco/');
const gltfLoader = new GLTFLoader();
gltfLoader.setDRACOLoader(dracoLoader);
gltfLoader.load(
'/models/monitor.glb',
(gltf) => {
gltf.scene.scale.set(100, 100, 100);
scene.add(gltf.scene);
const dd = gltf.scene;
dd.rotation.y = -1;
// CSS3dElement
const element = document.createElement(`div`);
element.innerHTML = `Tutorix is the best e-learning platform Tutorix is the best e-learning platform Tutorix is the best e-learning platform`;
element.style.width = '100px';
element.style.height = '100px';
element.style.overflowY = 'auto';
element.style.background = new THREE.Color(0x00F0FF).getStyle();
const object = new CSS3DObject(element);
object.position.copy(dd.position);
object.rotation.copy(dd.rotation);
object.scale.copy(dd.scale / 2);
scene2.add(object);
}
);
animate();
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer2.setSize(window.innerWidth, window.innerHeight);
}
function animate() {
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
renderer2.render(scene2, camera);
}
The black is the imported GLB and the blue is the CSS3DObject
Maybe using another dependency in which can do the job
I'm trying to load this image as a map of PointsMaterial with TextureLoader but with no success, it throws no errors, but the texture won't show for some reason. Am I doing something wrong or what?
Code:
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
1,
1000
);
const particleBufferGeometry = new THREE.BufferGeometry();
const positionArray = [];
for (let i = 0; i < 10000; i++) {
positionArray.push((Math.random() * 2 - 1) * 200);
positionArray.push((Math.random() * 2 - 1) * 200);
positionArray.push((Math.random() * 2 - 1) * 200);
}
particleBufferGeometry.setAttribute("position", new THREE.Float32BufferAttribute(positionArray, 3));
const particlePointsMaterial = new THREE.PointsMaterial({
size: 0.3,
map: new THREE.TextureLoader().load("./sparkle.png"),
transparent: true,
});
const particlePoints = new THREE.Points(particleBufferGeometry, particlePointsMaterial);
const renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true,
canvas: document.getElementById("three")
});
renderer.setClearColor(0x000000, 0);
renderer.setSize(
window.innerWidth,
window.innerHeight
);
scene.add(particlePoints);
renderer.render(scene, camera);
Another option is to use animation loop:
body{
overflow: hidden;
margin: 0;
}
<canvas id="three"></canvas>
<script type="module">
import * as THREE from "https://cdn.skypack.dev/three#0.135.0";
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
1,
1000
);
const positionArray = [];
for (let i = 0; i < 10000; i++) {
positionArray.push(new THREE.Vector3().random().subScalar(0.5).multiplyScalar(400));
}
const particleBufferGeometry = new THREE.BufferGeometry().setFromPoints(positionArray);
const particlePointsMaterial = new THREE.PointsMaterial({
size: 3,
map: new THREE.TextureLoader().load("https://threejs.org/examples/textures/sprites/spark1.png"),
transparent: true,
});
const particlePoints = new THREE.Points(particleBufferGeometry, particlePointsMaterial);
const renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true,
canvas: document.getElementById("three")
});
renderer.setClearColor(0x000000, 1);
renderer.setSize(
window.innerWidth,
window.innerHeight
);
scene.add(particlePoints);
renderer.setAnimationLoop(() => { // animation loop
renderer.render(scene, camera);
});
</script>
I found why is this happening. I was passing texture as a map before it loaded.
This is wrong.
const particlePointsMaterial = new THREE.PointsMaterial({
size: 0.3,
map: new THREE.TextureLoader().load("./sparkle.png"),
transparent: true,
});
load() function of TextureLoader has second parameter onLoad that executes when texture loads. So solution is:
new THREE.TextureLoader().load("./sparkle.png", (texture) => {
const particlePointsMaterial = new THREE.PointsMaterial({
transparent: true,
map: texture
});
const particlePoints = new THREE.Points(particleBufferGeometry, particlePointsMaterial);
scene.add(particlePoints);
renderer.render(scene, camera);
});