how to reset opengl modelview matrix? - opengl-es

Although I am using opengl es 1.1,but I want to try to work with my own matrix stuff,
I built a fps camera matrix function called : fpsmatrixupdate();
then I call it like this:
fpsmatrixupdate(); //this function generated a matrix called mat
drawbox(min,max)
everything works great,until I am trying to draw another box:
fpsmatrixupdate(); //this function generated a matrix called mat
drawbox(min,max);
glLoadIdentity(); // I tried to call this before drawbox2 but box2 doesn't show
drawbox2(min,max);
questions: why this works?
fpsmatrixupdate(); //this function generated a matrix called mat
drawbox(min,max);
glLoadMatrixf(mat); // mat is fps camera update function generated matrix,
drawbox2(min,max);
if I want to draw 200 boxes with different location, do I have to call glLoadMatrixf(mat) 200 times? if I don't call glLoadMatrixf(mat) to reset matrix ,the second box's transform is based on first box..
if anybody want to see the code, they are almost 99% copied from this demo:
http://www.codesampler.com/oglsrc/oglsrc_5.htm#ogl_fps_controls

Yes, if you want to base your objects' placement on a per-object transformation, you've to do a glLoadMatrix each time. It makes sense to calculate the transformation matrices once and store them in each object's scene data for easy access.

Related

Changing parents of a 3D model while keeping the same position

I'm using three.js library to work with 3d models (mostly .glb but it shouldn't matter)
The idea is to import a 3d model that contains groups and meshes. I want to be able to move meshes between already existing groups within a model without changing the visual representation of the model.
Piece of my code is below. movedInternal is
movedMesh.matrixWorldNeedsUpdate = true; // not sure if it's needed
let meshPosition = new THREE.Vector3();
movedMesh.getWorldPosition(meshPosition);
oldParent.remove(movedMesh);
newParent.add(movedMesh);
movedMesh.worldToLocal(meshPosition);
movedMesh.position.set(meshPosition.x, meshPosition.y, meshPosition.z);
And this is not working. Mesh changes its global position because new parent’s position is not the same as previous parent position, but I expect it to stay where it was but change its local position considering new parent’s position.
What do I do wrong?
I think you need to update the movedMesh's world matrix after you change its parents. When you .remove() then .add(), it doesn't know that its parents have been updated (Three.js usually does it when you're rendering, but this is happening before the next frame render).
let meshPosition = new THREE.Vector3();
movedMesh.getWorldPosition(meshPosition);
oldParent.remove(movedMesh);
newParent.add(movedMesh);
// Here it needs to re-learn its new coordinates
movedMesh.updateMatrixWorld(true);
movedMesh.worldToLocal(meshPosition);
movedMesh.position.set(meshPosition.x, meshPosition.y, meshPosition.z);
I've been searching for this solution since a week and haven't been able to tackle the exact problem. Though my question is diferent but has same scenario, I would like to give a solution for those, looking for it.
I have a 3D object with different child meshes, and i want to replace one of my child mesh with another 3D model.
Below code snippet:
replacementMesh is a new 3D object, meshToReplace is the child mesh that needs to be replaced.
// Copy the transformation matrix from obj1 to obj2
replacementMesh.matrix.copy(meshToReplace.matrix);
// Update obj2's position, rotation, and scale to match the transformation matrix
replacementMesh.position.setFromMatrixPosition(replacementMesh.matrix);
replacementMesh.rotation.setFromRotationMatrix(replacementMesh.matrix);
replacementMesh.scale.setFromMatrixScale(replacementMesh.matrix);
meshToReplace.parent.add(replacementMesh);
meshToReplace.parent.remove(meshToReplace);

Three.js - is there a simple way to process a texture in a fragment shader and get it back in javascript code using GPUComputationRenderer?

I need to generate proceduraly in a shader a texture and get it back in my javascript code in order to apply it to an object.
As this texture is not meant to change over time, I want to process it only once.
I think that GPUComputationRenderer could do the trick but I don't figure out how and what is the minimal code that can achieve this.
I need to generate proceduraly in a shader a texture and get it back in my javascript code in order to apply it to an object.
Sounds like you just want to perform basic RTT. In this case, I suggest you use THREE.WebGLRenderTarget. The idea is to setup a simple scene with a full-screen quad and a custom instance of THREE.ShaderMaterial containing your shader code that produces the texture. Instead of rendering to the screen (or default framebuffer), you render to the render target. In the next step, you can use this render target as a texture in your actual scene.
Check out the following example that demonstrates this workflow.
https://threejs.org/examples/webgl_rtt
GPUComputationRenderer is actually intended for GPGPU which I don't think is necessary for your use case.

Changing scale of Three.js object after it is loaded

I am developing an augmented reality project using Three.js and aruco-js. I made my code so that all my 3D Objects are added to the scene (empty) at the beginning but the data gets initially loaded on marker detection.
Now I want to create an interface for changing the objects appearance, starting with the possibility of scaling an object.
So I created an updateObject() function to set the new values like this:
function updateObject(object, rotation, translation)
{
...
...
...
// first method
object.scale.x = 200;
object.scale.y = 200;
object.scale.z = 200;
// second attempt
object.scale.set(300, 300, 300);
};
I tried both of the methods shown above to set the scale of my object but it has no effect to the rendered images I get. The interesting thing is that the values of the objects in my scene3d DOM object are the values I set in my function. But why doesn't it have any impact on the output?
I'm not very familiar with 3d programming in WebGL or Three.js, so if you could give me any hint where the problem might has it's origin I would really appreciate an answer.
FIX:
I took a closer look to the 3D objects I was loading and discovered that they have a children called "mesh" inside another children. By trying to change the scale of only the mesh I found out that it works this way. But I think it looks very ugly:
scene3d.children[visibleModels[0][0]+3].children[0].children[0].scale.set(2, 2, 2);
//visibleModels is a list of the markers/models that should be loaded
This is only a test for one single object to change but at least I found a way to solve this. Is this an ordinary way to change the scale of objects? If you have a better solution or anything to add feel free to contribute.
You could also try to scale the object by changing its matrix using the THREE.Matrix4.makeScale method instead:
object.matrix.makeScale( xScale, yScale, zScale );
Or the even simpler THREE.Matrix4.scale method:
object.matrix.scale( scale );

using renderOrder in three.js

I want to have two overlapping objects in a scene but I want to define which object should be drawn first. I have a sample of the code here: http://jsfiddle.net/sg02e5sm/1/
I'm using renderOrder = 1 for the second object to make it appear always on top of the first object (as long as they have the same Z value), but it's not working.
renderOrder does not make something appear "on top". It controls the order in which objects are rendered.
If you want your 2nd plane to be "on top", you can add
mesh.material.depthTest = false;
for the 2nd plane.
Alternatively, you can implement two render passes, as described in this SO answer.
three.js r.142

Three.js Retrieve data from WebGLRenderTarget (water sim)

I am trying to port this (http://madebyevan.com/webgl-water/‎) over to THREE. I think I'm getting close (just want the simulation for now, don't care about caustics/refraction yet). I'd like to get it working with shaders for the GPU boost.
Here's my current THREE setup using shaders: http://jsfiddle.net/EqLL9/2/
(the second smaller plane is for debugging what's currently in the WebGLRenderTarget)
What I'm struggling with is reading data back from the WebGLRenderTarget (rtTexture in my example). In the example you'll see the 4 vertices surrounding the center point are displaced upwards. This is correct (after 1 simulation step) as it starts with the center point being the only point of displacement.
If I could read the data back from the rtTexture and update the data texture (buf1) each frame, then the simulation should properly animate. How does one read the data directly from a WebGLRenderTarget? All the examples demonstrate how to send data TO the target (render to it), not read FROM it. Or am I doing it all wrong? Something's telling me I'll have to work with multiple textures and somehow swap back and forth similar to how Evan did it.
TL;DR: How can I copy data from a WebGLRenderTarget to a DataTexture after a call like this:
// render to rtTexture
renderer.render( sceneRTT, cameraRTT, rtTexture, true );
EDIT: May have found the solution at jsfiddle /gero3/UyGD8/9/
Will investigate and report back.
Ok, I figured out how to read the data using native webgl calls:
// Render first scene into texture
renderer.render( sceneRTT, cameraRTT, rtTexture, true );
// read render texture into buffer
var gl = renderer.getContext();
gl.readPixels( 0, 0, simRes, simRes, gl.RGBA, gl.UNSIGNED_BYTE, buf1.image.data );
buf1.needsUpdate = true;
The simulation now animates. However, it doesn't seem to be functioning properly (probably a dumb error I'm overlooking). It seems that the height values are never being damped and I'm not sure why. The data from buf1 is used in the fragment shader, which calculates the new height (red in RGBA), damps the value (multiplies by 0.99), then renders it to a texture. I then read this updated data from the texture back into buf1.
Here's the latest fiddle: http://jsfiddle.net/EqLL9/3/
I'll keep this updated as I progress along.
EDIT: Works great now. Just got normals implemented, and now working on environment reflection and refraction (again purely though shaders). http://relicweb.com/webgl/rt.html

Resources