Fellow developers, I once again call upon thee, to ask for help.
I have a working “Model Cutter” which cuts my Model along the X,Y,Z axes based on the AABB of the model. I simply use a shader where I use the opacityPS chunk to discard the alpha if a point is outside of the boundary.
It all works wonderfully. But my new challenge is to pick the correct MeshInstance with the pc.Picker. I have used Framebuffer Picking because it does not require the model to have Collision. Since some models I load are big (around 70MB) creating Collision for them does lower performance and if a certain complexity exists, ammo ultimately fails due to the RAM Excession.
Anyways the problem is, that the Framebuffer Picker does pick MeshInstances that are “invisible”. What I want to achieve is that you could pick “through” objects if one of their sides is “open”. For demonstration I have prepared the following, where you can see that the outer mesh is picked even tough the frontside is “open”:
Is there any other shader chunk I could add to achieve this ?
How would I dynamically manage the layer-swapping of mesh-instances of one object without it taking a hit on performance on complex models?
For me the simplest solution would be to “clip” the pixels that are not visible just like the camera does. Because when I zoom in with the camera and the front of the cube is clipped by the camera, I can select the cube inside.
I see, you can study how to the pc.Picker overrides the colors on each mesh instance rendered and do something similar in a custom shader chunk (e.g. diffuse, if that is used there) to discard pixels based on your logic.
If that happens when the picker layer is rendered it will work.
@Leonidas Thank you again for your insights and ideas!
I got a solution figured out, but it’s a little different
Instead what I am doing, is I Raymarch from my Cameras-Position up to the far clipping plane and check if I intersect the boundaries of my object. The boundaries are dynamically changed by the sliders. For example with the default cube, the X-Axis the boundaries are -0.5 and 0.5. When I adjust the slider, the boundaries changes to something like -0.5 and 0.2. I then raymarch from my cameras forward direction to the far-clip position and check if I find a position that is within these boundaries. I quickly change the position of my camera to that position and do the framepicking from there, and then switch the position back. With this I was successfully able to create the desired effect.
I thought I’d leave this here, if anyone ever wants to do the same.
var origCameraPosition = this.entity.getPosition().clone();
var stepIncrease = 0.0001; //Resolution of the Raymarches
var cameraEndClipPos = this.camera.screenToWorld(e.x, e.y, this.camera.farClip);
var foundRayMarchPos = cameraEndClipPos.clone();
var foundPos = false;
var upperBoundaries = new pc.Vec3(window.ModelCutterSettings.xMax, window.ModelCutterSettings.curYMax, window.ModelCutterSettings.curZMax);
var lowerBoundaries = new pc.Vec3(window.ModelCutterSettings.curXMin, window.ModelCutterSettings.yMin, window.ModelCutterSettings.zMin);
for(var p = 0; p < 1.0 && !foundPos; p += stepIncrease){
var currentRayMarchPos = new pc.Vec3().lerp(this.entity.getPosition(), cameraEndClipPos, p);
if(currentRayMarchPos.x > lowerBoundaries.x && currentRayMarchPos.x < upperBoundaries.x && currentRayMarchPos.y > lowerBoundaries.y && currentRayMarchPos.y < upperBoundaries.y && currentRayMarchPos.z > lowerBoundaries.z && currentRayMarchPos.z < upperBoundaries.z){
foundRayMarchPos = new pc.Vec3().lerp(this.entity.getPosition(), cameraEndClipPos, pc.math.clamp(p - (stepIncrease), 0 , 1));
foundPos = true;
}
}
if(foundPos){
this.entity.setPosition(foundRayMarchPos);
}
picker.prepare(this.entity.camera,this.app.scene);
var selection = picker.getSelection(e.x, e.y, 1, 1);
this.entity.setPosition(origCameraPosition);
//Handle selection
*
*
I know it’s not the pretties or most practical solution, but it worked for me