receive shadow whit SpotLight three.js - javascript

I want my objects inherit the shadow of other figures. But I have problems if I put:
objMesh.receiveShadow = true;
I get this error:
http://imgur.com/GWU3qJG
in my code this is what I have more or less.
renderer.shadowMapEnabled = true;
spotlight var = new THREE.SpotLight (0xffffff);
spotLight.position.set (2.4457938219139463,0, 17.37913738929295);
scene.add (Spotlight)
material = new THREE.MeshPhongMaterial ({color: 0x7777ff});
objMesh = new THREE.Mesh (extrude_geometry, material);
objMesh.castShadow = true;
objMesh.receiveShadow = true;
if I remove this line:
objMesh.receiveShadow = true;
my error does not appear.
I can do ?, or what would be the solution?

Related

Problems rendering a list of threeJs renderers

I'm attempting to display a list of renderer/scene/camera "groups" on the same html page. I ran into problems when trying to implement a render loop on all of them, using requestAnimationFrame. I am, however, unable to successfully render even a single frame by looping over the list.
calling renderer.render on each of the "groups" in the same function that I instantiate them in works fine. I refactored the code to allow calling render on each of the renderers outside of said function, and my blue spheres disappear;
I have some elements...
<div class="1"></div>
<div class="2"></div>
<div class="3"></div>
<div class="4"></div>
that I add some threeJs things to
$(document).ready(function(){
addResizeandCenterListener(window, $("#container"), 4/3);
addResizeListener($("#container"), $(".playerhalf"), 2/1);
for (let item of [".1", ".2", ".3", ".4", ".5", ".6", ".7", ".8"]) {
var threeDetails = addThreeRendererToElem($(item), item);
var scene = threeDetails["scene"];
addClickListenerToElem($(item), scene);
}
});
threeList = [];
//this adds a renderer/scene/camera to the element "elem"
function addThreeRendererToElem(elem, name){
var width = elem.innerWidth();
var height = elem.innerHeight();
var scene = newScene();
scene.name = name;
addDefaultLight(scene);
addBlueBall(scene);
var camera = addDefaultCamera(scene, width, height);
var renderer = newRenderer(width, height);
elem[0].appendChild(renderer.domElement);
//this works fine regardless of how many renderer/scene/camera groups I have placed in the DOM
//renderer.render(scene, camera);
var threeDict = {"renderer":renderer, "scene":scene, "camera":camera}
threeList.push(threeDict)
//this does not work, even if I only place a single renderer/scene camera group in the DOM
renderList();
}
function renderList() {
var tlist = threeList;
for (var i = 0; i< tlist;i++) {
var threeDict = tlist[i];
threeDict["renderer"].render(threeDict["scene"],
threeDict["camera"]);
}
}
function newScene(){
scene = new THREE.Scene();
return scene;
}
function newCamera(w, h){
camera = new THREE.PerspectiveCamera(45, w / h, 0.1, 100);
return camera;
}
function newRenderer(w, h){
renderer = new THREE.WebGLRenderer({alpha:true, antialias:true});
renderer.setSize(w, h);
return renderer;
}
function addObjectToScene(obj, scene){
scene.add(obj);
}
function ballObj(color){
var ballGeometry = new THREE.SphereGeometry(3, 16, 16);
var ballMaterial = new THREE.MeshPhongMaterial({color: 0x33aaff});
var ball = new THREE.Mesh(ballGeometry, ballMaterial);
return ball;
}
function spotLightObj(){
var spot = new THREE.SpotLight(0xffffff);
return spot;
}
function addDefaultCamera(scene, width, height){
var camera = newCamera(width, height);
camera.position.set(1,1,20);
camera.lookAt(scene.position);
return camera;
}
function addDefaultLight(scene){
var spot = spotLightObj();
spot.position.set(1, 10, 4);
addObjectToScene(spot, scene);
}
function addBlueBall(scene){
var hexcolor = "0x33aaff";
bball = ballObj(hexcolor);
addObjectToScene(bball, scene);
}
I expect to see some blue spheres, like when I am calling render from inside addThreeRendererToElem, but I don't. Instead, the canvases are all blank. The canvases are in the correct places on the web page, inspecting threeList in the console shows that all the objects are indeed there. There are no error messages.
Incorrect ending condition on your for-loop inside the renderList function.
You are missing .length. Should be:
function renderList() {
var tlist = threeList;
for ( var i = 0; i < tlist.length; i++ ) {
var threeDict = tlist[i];
threeDict["renderer"].render( threeDict["scene"], threeDict["camera"] );
}
}

Imported mesh to BABYLON.Mesh

I have a problem to use CSG on imported meshes, here's my code:
var a;
var b;
BABYLON.SceneLoader.ImportMesh("", "./public/Models/", "model1.stl", scene, function (newMeshes) {
// Set the target of the camera to the first imported mesh
camera.target = newMeshes[0];
a = newMeshes[0];
});
BABYLON.SceneLoader.ImportMesh("", "./public/Models/", "model2.stl", scene, function (newMeshes) {
// Set the target of the camera to the first imported mesh
//camera.target = newMeshes[0];
b = newMeshes[0];
});
var aCSG = BABYLON.CSG.FromMesh(a);
var bCSG = BABYLON.CSG.FromMesh(b);
"var a" and "var b" are undefined and Debug told me that
 "BABYLON.CSG: Wrong Mesh type, must be BABYLON.Mesh"
Is there any method to convert imported mesh to BABYLON.MESH?
Thank you very much
This is because the ImportMesh is async, you have to move your code in the callbacks section:
BABYLON.SceneLoader.ImportMesh("", "./public/Models/", "model1.stl", scene, function (newMeshes) {
// Set the target of the camera to the first imported mesh
camera.target = newMeshes[0];
a = newMeshes[0];
BABYLON.SceneLoader.ImportMesh("", "./public/Models/", "model2.stl", scene, function (newMeshes) {
// Set the target of the camera to the first imported mesh
//camera.target = newMeshes[0];
b = newMeshes[0];
var aCSG = BABYLON.CSG.FromMesh(a);
var bCSG = BABYLON.CSG.FromMesh(b);
});
});

Three.js pick object after remove

Picking and objects code is one of the most popular:
function Picking(event) {
var raycaster = new THREE.Raycaster();
event.preventDefault();
mouse.x = (event.clientX / renderer.domElement.clientWidth) * 2 - 1;
mouse.y = -(event.clientY / renderer.domElement.clientHeight) * 2 + 1;
raycaster.setFromCamera(mouse, camera);
var intersects = raycaster.intersectObjects(objects);
if (intersects.length > 0) {
if (INTERSECTED != intersects[0].object) {
}
} else {
INTERSECTED = null;
}
}
The description: in scene are two objects - cube and sphere. Sphere is first to camera and cube is second. The Sphere has ID1 and cube ID2. Picking is working.
The problem: after deleting the sphere (scene.remove(sphere)); Picking is giving the ID1, so, it seems like sphere is invisible. What is the problam?
The picture of the example: Picture
This code is not giving the result:
for (i = sphere.children.length - 1; i >= 0 ; i--) {
object = sphere.children[i];
object.geometry.remove;
object.material.remove;
object.geometry.dispose();
object.material.dispose();
scene.remove(object);
sphere.remove(object);
}
or
recur(sphere);
for (var i in objects) {
objects[i].geometry.remove;
objects[i].material.remove;
objects[i].geometry.dispose();
objects[i].material.dispose();
scene.remove(objects[i]);
sphere.remove(objects[i]);
}
function recur(obj) {
if (obj instanceof THREE.Mesh) {
objects.push(obj);
}
for (var i in obj.children) {
recur(obj.children[i]);
}
}
The code that add objects:
var ObjLoader = new THREE.ObjectLoader();
var ii;
var group = new THREE.Object3D();
var oldModel = scene.getObjectByName('group');
if (oldModel !== undefined) { scene.remove(oldModel); }
ObjLoader.load("path/model.json", addModelToScene);
group.name = "group";
scene.add(group);
function addModelToScene(model) {
recur(model);
for (var i in objects) {
objects[i].castShadow = true;
objects[i].receiveShadow = true;
}
model.name = "ModelName";
group.add(model)
}
So, The .json model consists of some objects (1..n);
This .json model is added into group.
With picking the side of the cube (may be material) is selectable, but not removable. but the position can be changed.
Thank you.
Change your picking logic a little, store all your objects into array when creating them:
/*var objects = [];
var group = new THREE.Object3D();
create your mesh add to array*/
objects.push(MyMesh);
/*now we have a reference all the time in objects[0] , objects[1]*/
objects[0].displose(); check syntax been a while*/
customMaterial = new THREE.ShaderMaterial(
{
uniforms: customUniforms,
vertexShader: document.getElementById( 'vertexShader' ).textContent,
fragmentShader: document.getElementById( 'fragmentShader' ).textContent,
//wireframe: true,
side: THREE.FrontSide
} );
function ground (){
var map = new THREE.PlaneGeometry(1024,1024, 128, 128);//Use planebufferGeo
map.dynamic = true;
_terrain = new THREE.Mesh( map, customMaterial );
_terrain.material.needsUpdate = true;
_terrain.geometry.dynamic = true;
_terrain.geometry.vertexColors = true;
_terrain.material.uvsNeedUpdate = true;
_terrain.geometry.normalsNeedUpdate = true;
_terrain.rotation.x = -Math.PI / 2;
objects.push(_terrain);
scene.add(_terrain );
}
So I used this in a situation where it was a picking game type, I used an array to store the mesh and i could manipulate the vertices / faces etc edit the array to make changes.
It was an easier way to compare things and check data.
function animate() {
var raycaster = new THREE.Raycaster();
raycaster.setFromCamera(mouse, camera);
var intersects = raycaster.intersectObjects(objects);
if ( intersects.length > 0 ) {
var faceIndex = intersects[0].faceIndex;
var obj = intersects[0].object;
var geom = obj.geometry;
//etc

Textgeometry facing user when camera turns

I am creating this 3d graph that represents a network of people. The nodes in the network are the names of people and between them lines are drawn whi9ch represents a connection. The purpose of this network is that people can turn it around and look through it to see what their network looks like, however, when I turn the camera around the network, the 3d text that I creat3ed with textgeometry is stuck to the same position and unformtunately therefore unreadable for the user when they want to look at the network from a different side. I know that this question has been asked several times before and I have read most of the answers on here, but I still cannot get it to work.
The problem that I encounter mostly is that when I try to do something like this:
nodeRenderer.lookAt(camera.position);
I get a problem that the camera is not defined. The camera is added to the scene, however this happens in a different .js document. This is where the scene gets created and the camera gets added (/ngraph.three/index.js):
var THREE = require('./lib/three');
module.exports = function (graph, settings) {
var merge = require('ngraph.merge');
settings = merge(settings, {
interactive: true
});
var beforeFrameRender;
var isStable = false;
var disposed = false;
var layout = createLayout(settings);
var renderer = createRenderer(settings);
var camera = createCamera(settings);
var scene = settings.scene || new THREE.Scene();
(...)
function renderNode(nodeId) {
nodeRenderer(nodeUI[nodeId]);
}
(...)
function initNode(node) {
var ui = nodeUIBuilder(node);
if (!ui) return;
// augment it with position data:
ui.pos = layout.getNodePosition(node.id);
// and store for subsequent use:
nodeUI[node.id] = ui;
scene.add(ui);
}
(...)
function createCamera(settings) {
if (settings.camera) {
return settings.camera;
}
var container = renderer.domElement;
var camera = new THREE.PerspectiveCamera(75, container.clientWidth/container.clientHeight, 0.1, 3000);
camera.position.z = 400;
return camera;
}
And this is where the nodes get created (ngraph.three/lib/defaults.js):
var THREE = require('./three');
module.exports.createNodeUI = createNodeUI;
module.exports.createLinkUI = createLinkUI;
module.exports.nodeRenderer = nodeRenderer;
module.exports.linkRenderer = linkRenderer;
function createNodeUI(node) {
var nodeMaterial = new THREE.MeshFaceMaterial( [
new THREE.MeshPhongMaterial( { color: 0x00cccc, shading: THREE.FlatShading } ), // front
new THREE.MeshPhongMaterial( { color: 0xffffff, shading: THREE.SmoothShading } ) // side
] );
var nodeGeometry = new THREE.TextGeometry( node.data, { size: 5, height: 2, curveSegments: 6, font: "helvetiker", weight: "normal", style: "normal" });
var nodeDirection = new THREE.Quaternion (THREE.Camera.Quaternion);
return new THREE.Mesh(nodeGeometry, nodeMaterial);
}
function createLinkUI(link) {
var linkGeometry = new THREE.Geometry();
linkGeometry.vertices.push(new THREE.Vector3(0, 0, 0));
linkGeometry.vertices.push(new THREE.Vector3(0, 0, 0));
var linkMaterial = new THREE.LineBasicMaterial({ color: 0x00cccc });
return new THREE.Line(linkGeometry, linkMaterial);
}
(...)
function nodeRenderer(node) {
node.position.x = node.pos.x;
node.position.y = node.pos.y;
node.position.z = node.pos.z;
}
(...)
I tried ui.quaternion = camera.quaternion; in /ngraph.three/index.js, but this didn't do anything, and I've tried nodeUI.lookAt(camera.position); but this gave an error: TypeError: nodeUI.lookAt is not a function.
PS: I'm using Three.js Rev. 68, Ngraph and node.js.
I can only guess since a lot of code is missing but your createNodeUI returns a THREE.Mesh which is a subclass of Object3D which has the function .lookAt(vector) to align its local z-axis to the given vector.
And you said you receive this Error : TypeError: nodeUI.lookAt is not a function that looks like you re trying to call .lookAt of the array and not of the node itself.
so try nodeUI[node.id].lookAt(camera.position)

Three.js set object opacity/transparent

I am creating a scene with some parts which are loaded from a JSON file.
I can hide and show every single object. But now I want to set the opacity/transparent for a single object.
I creating the objects with this code.
geometryArray = new Object();
var loader = new THREE.JSONLoader();
for(var i = 0; i < jsonFileNames.length; i++){
var layerName = jsonFileNames[i].split("/")[1].slice(0, -5);
loader.load(layerName, jsonFileNames[i], function(geometry, materials, layerName){
mesh = new THREE.Mesh(geometry, new THREE.MeshLambertMaterial({vertexColors: THREE.FaceColors, side:THREE.DoubleSide, transparent: true}));
mesh.scale.set(scaleFactor, scaleFactor, scaleFactor);
mesh.name = layerName;
scene.add(mesh);
geometryArray[layerName] = mesh;
}, layerName);
}
And I can show/hide the objects with this code
geometryArray[layerName].visible = true;
But how can I set the opacity/transparent for an object?
I have tried to work with this code but this doesnt work.
geometryArray[layerName].materials[0].opacity
You have to also set
geometryArray[layerName].materials[0].transparent = true
on the material for it to use the opacity.
material.transparent only accepts Boolean value not number value
WRONG !!!!! material.transparent = 0 or material.transparent = 1
RIGHT ------> material.transparent = true or material.transparent = false

Categories

Resources