threejs v115 ,line20969:stencil Not working - three.js

///
var stencilWrite = material.stencilWrite;
stencilBuffer.setTest( stencilWrite );
if ( stencilWrite ) {
stencilBuffer.setMask( material.stencilWriteMask );
stencilBuffer.setFunc( material.stencilFunc, material.stencilRef, material.stencilFuncMask );
stencilBuffer.setOp( material.stencilFail, material.stencilZFail, material.stencilZPass
);
}
///
The above is the threejs code. After commenting, the following template function of my code can run normally. I do n’t know why? It seems that the value of material.stencilWrite and state.buffers.stencil.setTest (true) in maskPass are in conflict? When rrenderer.render (this.scene, this.camera); in the pass, run stencilBuffer.setTest (stencilWrite); in the above code again?
///my code
var renderPass = new THREE.RenderPass(this.__scene, this.camera);
renderPass.renderToScreen = true;
renderPass.clearDepth = true;
this.effectComposer.addPass(renderPass);
var renderSelectPass = new THREE.RenderPass(this.selectScene, this.camera);
renderSelectPass.clear = true;
this.effectComposer.addPass(renderSelectPass);
var maskPass = new THREE.MaskPass(this.selectFace, this.camera);
maskPass.clear = true;
maskPass.renderToScreen = true;
this.effectComposer.addPass(maskPass);
///
It can run normally before the v106 version.

Related

THREE.JS Cannot read property 'matrixWorld' of undefined

When I create a sprite, OrbitControls works perfectly.
But when I switch to FirstPersonControls, everything freezes and the console gives this error:
Uncaught TypeError: Cannot read property 'matrixWorld' of undefined
at Sprite.raycast (three.js:26051)
at intersectObject (three.js:44583)
at Raycaster.intersectObjects (three.js:44658)
at animate (mainview.php?project_id=46&tipo=1:936)
Raycasting code:
if (firstorbit) {
if (l % 5 == 0) {
var vector = new THREE.Vector3(0, -1, 0);
vector = camera.localToWorld(vector);
vector.sub(camera.position);
var raycasterGround = new THREE.Raycaster(camera.position, vector);
var intersectsGround = raycasterGround.intersectObjects(scene.children, true);
if (intersectsGround.length > 0) {
if (intersectsGround[0].distance < 1.21) {
camera.position.y = (camera.position.y + (1.21 - intersectsGround[0].distance));
}
if (intersectsGround[0].distance > 1.36 && intersectsGround[0].distance < 1.45) {
camera.position.y = (camera.position.y - (intersectsGround[0].distance - 1.215));
}
}
}
if (l % 3 == 0) {
var vector1 = new THREE.Vector3(0, 0, -1);
vector1 = camera.localToWorld(vector1);
vector1.sub(camera.position);
var raycasterFront = new THREE.Raycaster(camera.position, vector1);
var intersectsFront = raycasterFront.intersectObjects(scene.children, true);
if (intersectsFront.length > 0) {
if (intersectsFront[0].distance < 0.3) {
controls.moveForward = false;
controls.w = false;
} else {
controls.w = true;
}
} else controls.w = true;
}
}
Raycasting code that I use on mouse click to measure something:
function getIntersections( event ) {
var vectorMouse = new THREE.Vector2();
vectorMouse.set(
mouse.x,
mouse.y );
var raycasterClick = new THREE.Raycaster();
raycasterClick.setFromCamera( vectorMouse, camera );
var intersectsClick = raycasterClick.intersectObjects( scene.children,true );
return intersectsClick;
}
I am not sure if the problem is with the sprite or with my raycasting code. But when I remove the sprite, everything works perfectly. And when I remove the Raycasting code, everything also works perfectly.

Updating geometric value

I'm using 'dat.gui' for user input and want the tableBoardGeometry and the tableLegsGeometry to update in my render method with the values from the input.
Geometric declarations
const boxWidth = 2;
const boxHeight = 0.1;
const boxDepth = 1;
const tableBoardGeometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
const tableLegPosition = (boxWidth * 0.45);
const tableLegHeight = 1.6
const tableLegHeightPosition = (tableLegHeight/2)
const tableLegsGeometry = new THREE.BoxGeometry(0.05, tableLegHeight, 0.05);
Dat.Gui
var gui = new dat.GUI();
var controls = function() {
this.TableWidth = 1;
this.TableHeight = 1;
this.LegsWidth = 1;
this.LegsHeight = 1;
this.RotationSpeed = 0.005;
}
var title = new controls();
gui.add(title, 'RotationSpeed', 0.005, 0.1);
Render Method
const render = () => {
requestAnimationFrame(render);
tableBoard.rotation.y -= title.RotationSpeed;
/* I'd like to update the Geomtrics here depending on user input */
renderer.render(scene, camera);
orbitCamera()
}
I've tried using:
tableBoard.scale.x = title.TableWidth;
and it doesnt work properly because of the variable dependencies for getting the right number. The variable that i'd like to update is tableLegHeightPosition
edit:
The issue is that the sub mesh follows the parent mesh on scaling

Load & Display Image in ActionScript

I am typing with very green fingers, so, please excuse the question. Learning from examples, I have been trying to load and display an image in ActionScript. This is from the original example that I am working on:
...
...
var bmd2:BitmapData = bmd.clone();
var infoBM:Bitmap = new Bitmap(bmd2);
var back:MovieClip = new MovieClip();
back.name = "back";
back.rotationX = -90;
var bSurface:MovieClip = new MovieClip();
bSurface.y = int(...
bSurface.z = int(...
bSurface.addChild(infoBM);
var overlay:Sprite = new Sprite();
overlay.graphics.beginFill(...);
overlay.graphics.drawRect(0, 0, bSurface.width, bSurface.height);
overlay.graphics.endFill();
bSurface.addChild(overlay);
back.addChild(bSurface);
var tf:TextField = new TextField();
tf...
tf...
tf...
bSurface.addChild(tf);
...
...
I am trying to place an image onto the bSurface instead of the text block, as above. So far, I've come up with:
var iSprite:Sprite = new Sprite();
var iMatrix:Matrix = new Matrix();
var bmData:BitmapData;
bmData = new BitmapData(surface.width, surface.height, true, 123);
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
loader.load(new URLRequest("c:\pixlr.png"));
function onComplete (event:Event):void
{
bmData = Bitmap(LoaderInfo(event.target).content).bitmapData;
}
iMatrix.tx = 0;
iMatrix.ty = 0;
iSprite.graphics.beginBitmapFill(bmData, iMatrix, false, true);
iSprite.graphics.drawRect(0, 0, surface.width, surface.height);
iSprite.graphics.endFill();
surface.addChild(iSprite);
...and:
var bmData:BitmapData;
bmData = new BitmapData(surface.width, surface.height, true, 123);
var loader:Loader = new Loader();
var location:URLRequest = new URLRequest("c:\pixlr.png");
loader.load(location);
bmData = Bitmap(loader.content).bitmapData;
surface.addChild(bmData);
but to no success. I've been failing miserably for days now, and would greatly appreciate some help.
Thanking you in advance,
Sofia
You're making this more complicated than it needs to be. A Loader is a DisplayObject. So when you want to load an image you can simply do this:
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
loader.load(new URLRequest("c:\pixlr.png"));
addChild(loader);
You can use the onComplete event to handle any sizing or positioning, or fading in you might want to do.

Three js camera movement

i dont have the code here so i hope you can understand, i'l edit and add the code when i get home.
I have built a class move that once initialized adds a jquery event (keyDown) to the rendered dom element.
the event checks what key is down in a switch case,
if the key is one of the cases the camera will be moved accordingly.
The camera does move, but for some reason it flickers a bit, like little jumps.
the speed for each camera move is 0.05;
when i did this in anouter app but via a javascript keydown event from the main script (no special class) it worked fine..
any idea why would it do this ?
edit: code
main script :
<script>
var moveMec = null;
var loopProg = null;
var renderer = null;
var scene = null;
var camera = null;
var mesh = null;
var earth = null;
var sun = null;
$(document).ready(
function() {
var container = document.getElementById("container");
renderer = new THREE.WebGLRenderer({ antialias: true } );
renderer.setSize(container.offsetWidth,container.offsetHeight);
container.appendChild(renderer.domElement)
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 45,
container.offsetWidth / container.offsetHeight, 1, 4000 );
earth = new Earth();
sun = new Sun({x:-10,y:0,z:20});
scene.add(earth.getEarth);
scene.add(sun.sunLight);
camera.position.set( 0, 0, 3 );
moveMec = new moveMechanics(camera,renderer.domElement)
loopProg = new loopProgram();
loopProg.add(function(){earth.update()});
//loopProg.add(function(){renderer.render( scene, camera );});
loopProg.solarLoop();
}
);
</script>
move script :
var moveMechanics = function (camera,domElement,speed)
{
moveMechanics.camera = camera;
moveMechanics.speed = speed != undefined ? speed : 0.01;
moveMechanics.domElement = domElement;
$(document).keydown(function(event)
{
switch(event.which)
{
case KeyEvent.DOM_VK_W:
camera.position.z -= moveMechanics.speed;
break;
case KeyEvent.DOM_VK_S:
camera.position.z += moveMechanics.speed;
break;
case KeyEvent.DOM_VK_D:
camera.position.x += moveMechanics.speed;
break;
case KeyEvent.DOM_VK_A:
camera.position.x -= moveMechanics.speed;
break;
}
});
}
loop code :
function loopProgram()
{
this.functionsToRun = new Array();
this.solarLoop= function()
{
jQuery.each(loopProg.functionsToRun, function(index,value)
{
value ? value() : null;
});
requestAnimationFrame(loopProg.solarLoop);
}
this.add = function(func)
{
this.functionsToRun[this.functionsToRun.length] = func;
}
}

Associate loaded JSON files with a name for later access

I would like to load multiple JSON files and control the visibility of their meshes. To achieve this, I associated them with their JSON file names. I got it working, but the solutions doesn't please me.
I modified the THREE.JSONLoader and passed a new parameter to the callback function. So with every new release of three.js, I would have to patch the three.js file again.
Here is my working solution (client side). See the new third parameter of loader.load(filename, callback, meshname).
Is there a better solution, which doesn't need a patched three.js library?
Thanks
// Load the JSON files
var meshes = new Object();
var jsonFileNames = ['assembly/part1.json', 'assembly/part2.json', 'assembly/part3.json'];
for(var i = 0; i < jsonFileNames.length; i++){
var loader = new THREE.JSONLoader();
var meshName = jsonFileNames[i].split("/")[1].split(".")[0];
loader.load(jsonFileNames[i], function(geometry, meshName){
mesh = new THREE.Mesh(geometry, new THREE.MeshPhongMaterial({vertexColors: THREE.FaceColors}));
mesh.scale.set(0.2, 0.2, 0.2);
mesh.doubleSided = true;
scene.add(mesh);
meshes[meshName] = mesh;
}, meshName);
}
// ....
// Access their meshes
meshes[meshName].visible = true;
You could create a callback factory like below. It will work around the problem with closures when created inside loops.
function makeHandler(meshName) {
return function(geometry) {
mesh = new THREE.Mesh(geometry, new THREE.MeshPhongMaterial({vertexColors: THREE.FaceColors}));
mesh.scale.set(0.2, 0.2, 0.2);
mesh.doubleSided = true;
scene.add(mesh);
meshes[meshName] = mesh;
};
}
// Load the JSON files
var meshes = new Object();
var jsonFileNames = ['assembly/part1.json', 'assembly/part2.json', 'assembly/part3.json'];
for(var i = 0; i < jsonFileNames.length; i++){
var loader = new THREE.JSONLoader();
var meshName = jsonFileNames[i].split("/")[1].split(".")[0];
loader.load(jsonFileNames[i], makeHandler(meshName));
}
// ....
// Access their meshes
meshes[meshName].visible = true;
A variant of Tapio's great answer. This variant avoids the need to create and manage the meshes object. It does this by creating each new mesh object with the desired object name directly in the made handler function. As before the desired name meshName for each mesh is defined by the user and passed to the handler. But then the new mesh is created with the desired name by using the javascript eval function.
function makeHandler(meshName) {
return function(geometry) {
material = new THREE.MeshPhongMaterial({vertexColors: THREE.FaceColors})
eval (meshName + "= new THREE.Mesh(geometry, material);" ); //***NEW ***
eval ( "var mesh = " + meshName +";" ); //*** NEW ***
mesh.scale.set(0.2, 0.2, 0.2);
mesh.doubleSided = true;
scene.add(mesh);
//*** NOT REQUIRED *** meshes[meshName] = mesh;
};
}
// Load the JSON files
var meshes = new Object();
var jsonFileNames = ['assembly/part1.json', 'assembly/part2.json', 'assembly/part3.json'];
for(var i = 0; i < jsonFileNames.length; i++){
var loader = new THREE.JSONLoader();
var meshName = jsonFileNames[i].split("/")[1].split(".")[0];
loader.load(jsonFileNames[i], makeHandler(meshName));
}
// ....
The various meshes can subsequently (when loading is completed) be referenced by their object names:-
// Access the meshes
//*** OLD *** meshes["part1"].visible = true;
//*** OLD *** meshes["part2"].visible = true;
//*** OLD *** meshes["part3"].visible = true;
part1.visible = true;//*** NEW ***
part2.visible = true;//*** NEW ***
part3.visible = true;//*** NEW ***

Resources