I have a scene that has 10 cubes in it.
See this fiddle: https://jsfiddle.net/gilomer88/tcpwez72/47/
When a user taps on one of the cubes, I want a new “details scene” to pop-open on top of the current "main scene" and have it display just that one cube the user tapped on.
When the user is done examining and playing with the cube they can close the “details scene”, thereby revealing the original "main scene" - which was really just sitting underneath it this whole time.
I keep getting the following error:
Uncaught TypeError: scope.domElement.addEventListener is not a function
Can't figure out why that's happening.
Note that the fiddle I made is 95% complete - it's just missing this bit of HTML you see here:
<canvas id="detailsCanvas"></canvas>
<div id="renderingSpot"></div>
(As soon as I added this HTML - and the CSS - everything started breaking up on me, no matter what I did to try fixing it - so I finally just took it out.)
Either way, I'm basically creating a new scene in which to display the "details view", along with a new renderer, OrbitControl, etc. - and the error occurs on this line:
const detailsOrbitController = new OrbitControls(detailsScene.userData.camera, detailsScene.userData.renderingElement);
(That line is in my makeDetailsScene() function - which you'll see in the fiddle.)
For what its worth, I was following this THREE.js example when I was putting this together: https://threejs.org/examples/?q=mul#webgl_multiple_elements
I'm not sure why you need this extra <div id="renderingSpot"></div>. You could also just pass the canvas to the OrbitControls. When I run the following code, I don't get any errors:
detailsScene.userData.renderingElement = document.getElementById("renderingSpot");
const detailsOrbitController = new OrbitControls(detailsScene.userData.camera, detailsScene.userData.renderingElement);
I made some changes to your fiddle: https://jsfiddle.net/xn19qbf7/
(I also made some HTML, CSS, JS additions such that the details view displays on top of the main canvas and that its scene gets rendered.)
I guess your problem was your original assignment with jQuery:
let renderingElement = $("#renderingSpot");
detailsScene.userData.renderingElement = renderingElement;
renderingElement is still a jQuery object. But OrbitControls doesn't accept a jQuery object. So, you should get the real element:
let renderingElement = $("#renderingSpot");
detailsScene.userData.renderingElement = renderingElement.get(0);
// or as above
detailsScene.userData.renderingElement = document.getElementById("renderingSpot");
Related
NOTE: It appears I oversimplified my initial question. See below for the edit.
I'm trying to combine the technique shown in the clipping/stencil example of Three.js, which uses the stencil buffer to render 'caps' when clipping geometry, with an EffectComposer-based rendering pipeline, but I am running into some difficulties. A fiddle demonstrating the problem can be found at https://jsfiddle.net/2vc76ajd/1/.
The EffectComposer has two passes: a RenderPass and a ShaderPass using CopyShader (see code below).
composer = new EffectComposer(renderer);
composer.addPass(new RenderPass(scene, camera));
var shaderPass = new ShaderPass(CopyShader);
shaderPass.enabled = false;
composer.addPass(shaderPass);
The first renders the scene as usual, the latter merely copies the rendertarget onto a fullscreen quad. If I disable the ShaderPass everything works as intended: the geometry is clipped, and cutting planes are drawn in a different color:
When the ShaderPass is enabled by clicking the 'copy pass' checkbox in the upper right, however, the entire cutting plane gets rendered, rather than just the 'caps':
Presumably there is some interaction here between offscreen render targets and stencil buffers. However, I have so far been unable to find a way to have subsequent render passes look the same as the initial render. Can anyone tell me what I am missing?
EDIT: While WestLangley's answer solved my initial problem, it unfortunately doesn't work when you're using an SSAOPass, which is what I was doing before trying to simplify the problem for the question. I have posted an updated fiddle at https://jsfiddle.net/bavL98hf/1/, which includes the proposed fix and now toggles between a RenderPass or an SSAOPass. With SSAO turned on, the result is this:
I have tried setting stencilBuffer to true on all the render targets used in SSAOPass in addition to the ones in EffectComposer, but sadly that doesn't work this time. Can anyone tell me what else I am overlooking?
i'm using three.js version 92 with use of texture.
three.js warn demo
thanks to three.js i've the transformation of image's dimension in power of two automaticly, but i would like to suppress the warn that it show in the console without remove all the other warn from other modules or functions.
i would hide the three.js for my users, but i would like to use the rest of them from other libs.
is there a way to set the texture loader to hide them?
You have a few options.
The first and easiest is to remove the console.warn line from three.js. You've said that's not feasible due to how you acquire three.js, but there are other ways.
The next is to override the code where the warning is occurring. This warning (and there are several places where it can occur) happens in the WebGLRenderer object.
Download the THREE.js source.
Open in threejs/build/three.js in an editor.
Find the WebGLRenderer.
Copy that whole function into a JavaScript file you control.
Edit that new file to remove those console warnings.
Reference the new file in your project.
In the code where you interact with the THREE namespace, but before you create the WebGLRenderer object, replace THREE.WebGLRenderer like this:
THREE.WebGLRenderer = WebGLRenderer;
The reference to WebGLRenderer on the left is to the loaded THREE namespace. The reference to WebGLRenderer on the right is to the one from the new file (with the warnings removed).
Finally, you can just disable warnings entirely. This warning should only appear during the first renderer.render call when the texture is available. I personally don't recommend doing this unless you're comfortable with losing all console warnings in the interim between when you turn warnings off, and whenever the texture finishes loading. That would go something like this:
var originalWarning = console.warn; // back up the original method
console.warn = function(){}; // now warnings do nothing!
var tex = texLoader.load("texture.png", functon(){
renderer.render(scene, camera); // sends the texture to the GPU
console.warn = originalWarning; // turns warnings back on
});
var mat = new THREE.SomeMaterial({
map: tex
});
As an example, I tried to set up an AR scene in three.js.
I use "aruco.js" to do that. When I load obj or any other models everything works great, However when the marker is placed in front of the camera it gets detected and the scene flickers/bumps violently. Any serious reason why this is happening?
As live demo would be hard to set up, I just uploaded a video on YouTube to illustrate my point: https://youtu.be/9jMso7vmw1M
So my exact question is: what is the best way to make AR scene stick to the marker without any flicker?
Code in jsfiddle: https://jsfiddle.net/6cw3ta57/
var markerObject3D = new THREE.Object3D()
scene.add(markerObject3D)
// set the markerObject3D as visible
markerObject3D.visible = false
//////////////////////////////////////////////////////////////////////////////////
// code in jsfiddle
//////////////////////////////////////////////////////////////////////////////////
I am trying to take a 'snapshot' of a babylon3d scene ... in other words: I am trying to clone a babylon3d canvas when a user presses a button, and then append the new <canvas> to the <body> .. Sometimes it works, but other times it does not.
However, if I use a simple canvas (ie. by using fillRect), the cloning/appending always works as expected.
I have set up a test on plunker to demonstrate my problem: plunker: press the button over and over again to see how sporadic it behaves when there is a babylon scene. AND NOTE: You can toggle between the simple canvas and the babylon canvas from within the _jquery(document).ready(...) handler.
thanks, Shannon
This is because from version 2.3.0 of Babylonjs :
Engine now initialize WebGL with preserveDrawingBuffer = false by default.
You need to initialize the Engine by passing a {preserveDrawingBuffer: true} object as third parameter.
Forked plnkr
But this will unfortunately kill your canvas' performances.
See more about it here.
I'm not really a specialist of Babylonjs, and I didn't find a way to make a call from scene.render method where we could use the flag method proposed by
#CapsE. But there is a BABYLON.Tools.CreateScreenshot(engine, camera, size) method, which will make a downloadable png from your scene ; maybe this could help you.
I'm new to ThreeJS and I made this example which shows one of our model.
http://petrie3dtesting.museums.ucl.ac.uk/3DFootCover/index.html
I created a Petrie3Dviewer and in the HTML page created a viewer object which takes as input an .obj and .mtl file. Strangely tho, the objects shows up BLACK and then when I start interacting the texture comes up. I tried everything I think: different browsers, making the texture smaller, different computers, nothing I get a random behaviour all the time.
I tried on FIrefox, Chrome mainly.
It seems that I need to force the rendering once the obj file is loaded but the OBJMTLLoader.js does not provide any event for it.
Really many thanks for the help.
Best,
GC
You should call this.DoRender in your Animate function to render the frame.
this.Animate = function() {
this.orbitControls.update();
this.Animate();
requestAnimationFrame(this.Animate.bind(this));
}
At the moment you call your render function only when the user changes the perspective with the OrbitControls. And because your texture is loaded asynchronously it is not ready the first time when you render the frame.