Manipulate gltf model children - three.js

I'VE loaded a GLTF file with 2 mesh object in it (cube1, cube2) and rendered it, looks OK.
The problem is this :
I'm trying to manipulate the opacity / scale of those objects separately.
Tried to address them with:
Var cube1 = gltf.Scene.GetObjectByName('Cube1');
But when I try to define cube1.opacity, I get an "undefined" error.
Any help is appreciated!
Thanks

Well... even tho' the question is simple, the answer not so much.
First you are using a loader, usually this implies that your cube model will be a bit more complicated. You will go something like this:
3D Object > Children > Mesh [x] > material > Opacity
I have a live example here:
https://boxelizer.com/renderer.php?mid=7740369e824e4eadbd83e6f01fa96caa
In which you can go into the console and change that property like this:
model.children[1].material.transparent = true;
model.children[1].material.opacity = .5;
model.children[1].material.needsUpdate = true;
Your model may be a bit different but I hope this example helps you figure out yours.

Related

Getting global normal from hitTest.face.normal

I am doing a hitTest to create a section plane on a face normal. To get the global normal I have to do some reworking of the hitTest.face.normal. It seems to almost work, but my result seems to be slightly off from the actual normal, so I am thinking I am doing something wrong:
const normalMatrix = new THREE.Matrix3().getNormalMatrix( this.hitTest.object.matrixWorld );
const normal = this.hitTest.face.normal.clone().applyMatrix3( normalMatrix )
this.SectionExtension.tool.setSectionPlane(normal, this.hitTest.point)
As seen on the picture, my ending cut plane is slightly off the actual plane
Can anyone see what might be off in that way of getting the plane, or do anyone have a better way of finding the global normal?
Thank you in advance!
Could you share more details on what the face normal should be? Here is the code snippet how the viewer's context menu Section Plane creates the section plane based on the face hit point. It might help.
const selected = viewer.getSelection();
const intersection = viewer.impl.hitTest(status.canvasX, status.canvasY, false, selected);
// Ensure that the selected object is the on that recieved the context click.
if (intersection && intersection.face && selected.indexOf(intersection.dbId) !== -1) {
sectionExtension.tool.setSectionPlane(section, intersection.face.normal, intersection.point);
}
If anyone should be interested, then i found a solution to my problem
For some reason, when running
const currentFragId = this.hitTest.fragId;
const renderProxy = this.viewer.impl.getRenderProxy(this.viewer.model,currentFragId);
Before using the normal helped me to get the correct normal. I do not use the 'renderProxy' for anything - but i assume that it helps the viewer in some way. Anyway - this works for me!

Raycasting in threeJs, when target is over object

I'm fairly new to three.js and trying to get a better understanding of ray casting. I have used it so far in a game to show when an object collides with another on the page which works perfectly. In the game I'm building this is to take health from the hero as it crashes into walls.
I am now trying to implement a target which when hovered over some objects it will auto shoot. However the target only registers a target hit once the object passes through the target mesh rather than when its ray is cast through it.
to further detail this, the ray is cast from the camera through the target, if the target is on a mesh (stored as an object array) then I want it to trigger a function.
within my update function I have this:
var ray = new THREE.Raycaster();
var crossHairClone = crossHair.position.clone();
var coards = {};
coards.x = crossHairClone.x
coards.y = crossHairClone.y
ray.setFromCamera(coards, camera);
var collisionResults = ray.intersectObjects( collidableMeshList );
if ( collisionResults.length > 0 ) {
console.log('Target Hit!', collisionResults)
}
The console log is only triggered when the collidableMeshList actually touches the target mesh rather than when it is aiming at it.
How do I extend the ray to pass through the target (which I thought it was already doing) so that if anything hits the ray then it triggers my console log.
Edit
I've added a URL to the game in progress. There are other wider issues with the game, my current focus is just the target ray casting.
Game Link
Many thanks to everyone who helped me along the way on this one but I finally solved it, only not through the means that I had expected to. Upon reading into the setFromCamera() function it looks like it is mainly used around mouse coards which in my instance was not what I wanted. I wanted a target on the page and the ray to pass through this. For some reason my Ray was shooting vertically up from the centre of the whole scene.
In the end I tried a different approach and set the Rays position and direction directly rather rely on setting it from the cameras position.
var vector = new THREE.Vector3(crossHair.position.x, crossHair.position.y, crossHair.position.z);
var targetRay = new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize());
var enemyHit = targetRay.intersectObject( enemy );
if ( enemyHit.length > 0 ) {
console.log('Target Hit!', targetRay)
}
I'll leave this up for a while before accepting this answer in case anyone has a better approach than this or has any corrections over what I have said in regards to setFromCamera().

How to implement a morphtargets human demo use gltf?

Just like https://threejs.org/examples/?q=morph#webgl_morphtargets_human,
but I want to implement a glTF based demo .
I had tried glTF models such as https://github.com/HowardWolosky/glTF-Sample-Models/tree/morphAnimation/2.0/AnimatedMorphCube and https://github.com/HowardWolosky/glTF-Sample-Models/tree/morphAnimation/2.0/AnimatedMorphSphere, but they use animations, I want to control the morph weights manually, like:
mesh.morphTargetInfluences[0] = 0.5;
mesh.morphTargetInfluences[1] = 0;
mesh.morphTargetInfluences[2] = 1;
Thanks
I had solve this question myself by changing code in gltfloader.js.
see https://github.com/mrdoob/three.js/pull/11786#issuecomment-316423788

EffectComposer second pass "overwrites" first pass

i want to render a texture on the background and the 3dscene in the foreground. i used the effectcomposer to do this.
how ever my first pass (the background) seems to be "overwritten" with the 2nd pass (the scene) the result only the scene gets drawn with a black background. it looks like the background of the second pass isnt drawn transparent or the transparancy is lost.
http://jsfiddle.net/mdwzx1f8/8/
var renderTex = new THREE.TexturePass(myTex);
var renderScene = new THREE.RenderPass(scene, camera);
composer.addPass(renderTex);
composer.addPass(renderScene);
var effectCopy = new THREE.ShaderPass(THREE.CopyShader);
effectCopy.renderToScreen = true;
composer.addPass(effectCopy);
i hope someone can take a quick look at it and point me in the right direction
thanks in advance
Updates:
07/07/2015
I tried clearing the zbuffer with renderer.clear(false, true, false);
Found a post on masking which i looked at but it wasnt added to
threejs as far as i can tell
https://github.com/mrdoob/three.js/issues/2448
08/07/2015
Found another interesting page https://github.com/mrdoob/three.js/issues/5979 not sure if this is related yet
Updated the fiddle if you comment line 53 you will see the 1st pass which should be visible if the scene background is drawn transparent
Bobafett in the threejs irc channel helped me out and he found my issue, it turns out that i called:
renderer.autoClear = false;
instead onrenderer.autoClearColor = false;
Here is the modified and working fiddle:
http://jsfiddle.net/mdwzx1f8/9/
I would like to thank all who have helped me in the search for the solution

Outline object (normal scale + stencil mask) three.js

For some time, I've been trying to figure out how to do an object selection outline in my game. (So the player can see the object over everything else, on mouse-over)
This is how the result should look:
The solution I would like to use goes like this:
Layer 1: Draw model in regular shading.
Layer 2: Draw a copy in red color, scaled along normals using vertex shader.
Mask: Draw a black/white flat color of the model to use it as a stencil mask for the second layer, to hide insides and show layer 1.
And here comes the problem. I can't really find any good learning materials about masks. Can I subtract the insides from the outline shape? What am I doing wrong?
I can't figure out how to stack my render passes to make the mask work. :(
Here's a jsfiddle demo
renderTarget = new THREE.WebGLRenderTarget(window.innerWidth, window.innerHeight, renderTargetParameters)
composer = new THREE.EffectComposer(renderer, renderTarget)
// composer = new THREE.EffectComposer(renderer)
normal = new THREE.RenderPass(scene, camera)
outline = new THREE.RenderPass(outScene, camera)
mask = new THREE.MaskPass(maskScene, camera)
// mask.inverse = true
clearMask = new THREE.ClearMaskPass
copyPass = new THREE.ShaderPass(THREE.CopyShader)
copyPass.renderToScreen = true
composer.addPass(normal)
composer.addPass(outline)
composer.addPass(mask)
composer.addPass(clearMask)
composer.addPass(copyPass)
Also I have no idea whether to use render target or renderer for the source of the composer. :( Should I have the first pass in the composer at all? Why do I need the copy pass? So many questions, I know. But there are just not enough resources to learn from, I've been googling for days.
Thanks for any advice!
Here's a js fiddle with working solution. You're welcome. :)
http://jsfiddle.net/Eskel/g593q/6/
Update with only two render passes (credit to WestLangley):
http://jsfiddle.net/Eskel/g593q/9/
The pieces missing were these:
composer.renderTarget1.stencilBuffer = true
composer.renderTarget2.stencilBuffer = true
outline.clear = false
Now I think I've found a bit simpler solution, from the THREEx library. It pre-scales the mesh so you dont need a realtime shader for it.
http://jeromeetienne.github.io/threex.geometricglow/examples/geometricglowmesh.html

Resources