mrdoob / three.js

JavaScript 3D Library.
https://threejs.org/
MIT License
102k stars 35.33k forks source link

Access to the renderer Frustrum or an insersect helper method required. #11894

Closed danrossi closed 7 years ago

danrossi commented 7 years ago

Adding this to the WebGlRenderer seems to work. It means it is not duplicating a second Frustrum instance and projection matrix.

this.isVisible = function(target) {
                console.log("visible", _frustum.intersectsObject( target ));
        };

Is this possible ?

There is an issue with Samsung Internet browser on android. it cannot detect visibility where Chrome works.

WestLangley commented 7 years ago

_frustum is an internal, working variable whose value changes based on the last camera used. After postprocessing, that is typically an orthographic camera. There can be multiple cameras in a scene, too.

danrossi commented 7 years ago

It works for general purpose use including with the vr array camera. Anything else could be external. It saves a whole chunk of duplicated code.

Just being able to get access to it would help alot.

This helps determine if an object is visible or moves off screen to make another object visible. In my case text. my mod is already working fine.

danrossi commented 7 years ago

I was referring to the pull request.

If would be awesome when this project moves to es6 , it would be a standard getter like

get frustrum() {
   return _frustrum;
}

mine looks like this

https://github.com/danrossi/three.js/commit/aa702248ba45ac4866b82c2fb2c931e874ec9445

this.getFrustum = function() {
    return _frustum;
 };
mrdoob commented 7 years ago

Shouldn't that go in the camera instead?

danrossi commented 7 years ago

Here its grabbing the projection matrix for either the standard camera or the array camera when in vr mode.

danrossi commented 7 years ago

I can try and make a fiddle of how it works if needed.

mrdoob commented 7 years ago

Yes please.

WestLangley commented 7 years ago

@danrossi I don't think you understood what I said. You may not be referencing the frustum of the camera that you want.

danrossi commented 7 years ago

There is no Frustum on the camera as far as I can see.

And I would have to duplicate getting the vr camera too while the renderer is also getting that. That code alone could be expensive to get.

Hence why I'm trying to get it from the renderer. ie it does work and duplicating the Frustum code getting the vr camera like this. But prefer not having to duplicate calls like this.

renderer.vr.getCamera(camera);

I'm trying to make something up will let you know.

danrossi commented 7 years ago

Here is initial example. Have to make the fiddle up with my external files.

http://dev.electroteque.org/frustum/

danrossi commented 7 years ago

Here is the fiddle. If there are other ways by all means.

https://jsfiddle.net/tvw9jvbp/

fernandojsg commented 7 years ago

Maybe you're looking for something similar to what I proposed in this PR ? https://github.com/mrdoob/three.js/pull/11523

Basically each camera has a cullingVolume that can be implemented in several ways depending on the type of camera/s. You could do then camera.getCullingVolum() and use that culling volume to test intersects with your objects if you want to do it manually.

danrossi commented 7 years ago

I would still have to make a second call to get vr camera like the renderer is doing , and it's an array camera. The intersect is more important in presentation mode for my purpose. ?

danrossi commented 7 years ago

Let me test that out. How to use ?

danrossi commented 7 years ago

ok so in an animation loop I need to keep this updated correct ?

const frustum = camera.getCullingVolume();

This still seems to be duplicating what is updated in the renderer but ok. I would then want to get access to

_cullingVolume

To do the intersect on that not another call to it.

danrossi commented 7 years ago

I've updated the example with your branch and a similar method to obtain the Frustum its just a name change and it seems instead of keeping the instance and dynamically updating the matrix. It needs to be obtain on each animation loop.

Could a reference be updated like before perhaps ?

https://dev.electroteque.org/frustum/

var visible = renderer.getCullingVolume().intersectsObject( uiObject );
this.getCullingVolume = function() {
        return _cullingVolume;
    }

I tried to update the fiddle but its caching three.js for no reason so broken.

danrossi commented 7 years ago

I'll remove my pull request and concentrate on this feature instead considering it will hopefully be merged. thanks for the input.

danrossi commented 7 years ago

This is using your branch with dev branch merged also. I had to make the getter method to do what I needed however.

https://dev.electroteque.org/frustum/

danrossi commented 7 years ago

Let me know what you think of the mod upon the mod.

Its simply accessing the frustum change still to use it directly. rather the extra unnecessary calls in a loop. It just now has to be done after the render.

If there are other ways to detect the object is out of the render list and flagged as not visible by all means.

The change is working but there is now webvr bugs on Android causing rotating to make the entire render view move. not sure if its related yet.

My purpose is displaying MSDF font rendered text in centre view when a 2D video has rotated out of view like the Youtube app in vr cinema view. I have that added to the camera so it stays on the axis. It's much smoother than normal text rendering and scales better.

I have it on my site working if needed a production example.

mrdoob commented 7 years ago

There is no Frustum on the camera as far as I can see.

No, but you can build one from it.

var frustum = new THREE.Frustum();
var matrix = new THREE.Matrix4();

matrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
frustum.setFromMatrix( matrix );

console.log( frustum.intersectsObject( object ) );
danrossi commented 7 years ago

It's already being built in the renderer especially the culling volume branch.

Hence a reference to that is working in both vr camera and normal camera if the reference is simply made as a getter. It reduces extra unnecessary calls and code.

Hence the purpose of the thread.

Sorry if that wasn't clear.

I've been making tests with the culling volume branch code and is all working fine as per the updated example.

All I would need to do is this

var visible = renderer.getCullingVolume().intersectsObject( uiObject );
mrdoob commented 7 years ago

Hence a reference to that is working in both vr camera and normal camera if the reference is simply made as a getter. It reduces extra unnecessary calls and code.

I don't think this would really be a bottle neck though.

danrossi commented 7 years ago

@fernandojsg is your branch about to be merged at all ?

I am going to have to revert to the external code as maintaining a fork, mod and merging is rough.

According to my tests that branch is working.

fernandojsg commented 7 years ago

@danrossi I didn't get any feedback yet from @mrdoob about that PR but I believe it's ready to merge as the initial point for a combined frustum, this way is the most conservative implementation and then we could evolve it from there to more optimized methods for each specific case.

danrossi commented 7 years ago

Of course thanks for the effort. No problems. I'll come back to that implementation when it's ready.