Jump to content

Problems with mirror texture


JCPalmer
 Share

Recommended Posts

I was making a scene, so I could take a picture for the Doc site.  I added a mirror to emphasize the direction a mesh facing, but it does not show up in it.

 

I made scene by taking a .blend file & generating an inline source file.  No problem there, but remember a mirror has to be added post Blender.  Added this to my html:

var mirrorMaterial = new BABYLON.StandardMaterial("mirrorMat", scene);mirrorMaterial.reflectionTexture = new BABYLON.MirrorTexture("mirrorTex", 1024, scene, true);mirrorMaterial.reflectionTexture.mirrorPlane = scene.getMeshByID("Mirror");mirrorMaterial.reflectionTexture.renderList = [scene.getMeshByID("Gus")];

I verified that Meshes "Mirror" & "Gus", exist from console.log messages.  Any thoughts?  Light issues, maybe?

 

Here is scene with arc rotate camera.  You can see mesh for mirror is a plane.  With no backside culling left on, it disappears when behind it.

https://googledrive.com/host/0B6-s6ZjHyEwUflhfdFFnNGJQXzc1U3I4YjZ5b1FMWW16ZHNWd2JVbE9abTRDN2tEWWgwclk

Link to comment
Share on other sites

Thanks, both were problems.  dbawel also got my values for the plane working

 

Here is the final html code, for future searches

// get the render list for the Mirrorvar gus = scene.getMeshByID("Gus");var renderList = gus.getChildren();renderList.push(gus);var mirrorMaterial = new BABYLON.StandardMaterial("mirrorMat", scene);mirrorMaterial.diffuseColor  = new BABYLON.Color3(0.1,0.1,0.1);mirrorMaterial.emissiveColor = new BABYLON.Color3(0.1,0.1,0.1);mirrorMaterial.reflectionTexture = new BABYLON.MirrorTexture("mirrorTex", 4096, scene, true);mirrorMaterial.reflectionTexture.mirrorPlane = new BABYLON.Plane(0,0,-1,-6);mirrorMaterial.reflectionTexture.renderList = renderList;scene.getMeshByID("Mirror").material = mirrorMaterial;
Link to comment
Share on other sites

The 4th value for the mirrorPlane is the distance from the reflected object where the reflection appears to occur.  Also, I would change the 3rd value for your mirrorPlane from 1 to -1, as this should correct your reflection angle so that your objects appear to be reflected correctly.  I'll look at the documentation pages and see if there is a page yet created to post all 4 of these parameters, as it took me quite a while to guess (figure out by trial) what all 4 of these values represented before I got it right.

Link to comment
Share on other sites

I had hard time with planes as well, and eventually ended up using this code (modified from a few sources I found here in the forum)

var pointsArray: Array<BABYLON.Vector3> = [];var meshWorldMatrix = mesh.computeWorldMatrix();var verticesPosition = mesh.getVerticesData(BABYLON.VertexBuffer.PositionKind);var offset = 0for (var i = 0; i < 3; i++) {    var v = this._object.getIndices()[i + offset];    pointsArray.push(BABYLON.Vector3.TransformCoordinates(BABYLON.Vector3.FromArray(verticesPosition, v*3), meshWorldMatrix));}var plane = BABYLON.Plane.FromPoints(pointsArray[0], pointsArray[1], pointsArray[2]);

This will take the first two vertices of the mesh and calculate the plane for them. works great for Ground and normal Planes. If you know the vertices you want to use or their offset you can set the offset parameter.

Link to comment
Share on other sites

The 4th value for the mirrorPlane is the distance from the reflected object where the reflection appears to occur.  Also, I would change the 3rd value for your mirrorPlane from 1 to -1, as this should correct your reflection angle so that your objects appear to be reflected correctly.  I'll look at the documentation pages and see if there is a page yet created to post all 4 of these parameters, as it took me quite a while to guess (figure out by trial) what all 4 of these values represented before I got it right.

Thanks,  very usable now with the sign change on 3rd arg.  Just need to clean up:

  • put back the ground, & reduce the size of the mirror
  • move the mirror back more, so the "Forward" sign has more room,
  • change lighting maybe to give mirror a more shiny appearance.
  • Enhance reflection by putting the text "Eat Me" across the gingerbread man’s chest.

As far as the distance being the fourth arg, I noticed changing it made the size of the reflection change.  The minus sign is a little perplexing.  Is that because the reflection is "into" the mirror?  (Rhetorical,  I'll just guess till I like it)

 

RaananW,  that sounds like it would be a good method for BABYLON.Mesh:  public getPlane() : Plane.  Would give strange results from non-plane meshes unfortunately.  I am kind of a OO zealot.  I would have created sub-classes of all those static Mesh.createXXX() methods.  Then you could add methods like this which made sense to them, but not all meshes.  That's just me though.

 

Will "reflect" this in the best answer & update scene when done.

Link to comment
Share on other sites

Yep, that would be 

getTransformedPlaneOfFirstTwoVertices()  :)

The problem really is, that a normal user doesn't really know what vertices to choose (I know I wouldn't). For a GroundMesh - there is only one plane. for the box there are 6, but who knows which vertices are which... not even starting to talk about a sphere  :(

I have integrate this function in the material editor. You can divide the box to 6 submeshes and make all 6 planes a mirror. But if i make the box's reflection texture a mirror without sub-meshing it doesn't really work.

Link to comment
Share on other sites

The problem really is, that a normal user doesn't really know what vertices to choose (I know I wouldn't). For a GroundMesh - there is only one plane. for the box there are 6, but who knows which vertices are which... not even starting to talk about a sphere  :(

 

 

This is what I suggested here : http://www.html5gamedevs.com/topic/12118-new-kind-of-submeshes-suggestion-meshparts/?hl=part

Give the user the way to access some logical part of a mesh without dealing with vertex indexes.

 

Maybe I'll do it later as an extension for ribbons and other BJS basic shapes :

cube.getPart(0);                        // returns the first face as a submesh or vertexData (to be thought)sphere.getPart(29);                     // returns the 30th ringcylinder.getPart(2);                    // idem, 3rd ringtorus.getPart(15);                      // returns the 16th radial ringribbon.getPart(5);                      // returns the 6th elementary ribbon

etc

Link to comment
Share on other sites

Sorry, couldn't read this one  :)  My french is a bit rusty...

 

The question is, what can you do with it? And what is the meaning of getPart in a more complex mesh? 

A developer that requires this would be able to create (for example) 6 submeshes, equal in size for the box, and create his own "getPart" function.

This could be very confusing if it will be added to the standard mesh. Maybe to a sub class of a mesh, soemthing like structuredMesh. But I still can't find use cases for it. This mirror thing - I hope no one is planning on creating multiple boxes with mirror textures, as this will be a serious performance killer :-)

Link to comment
Share on other sites

Though Planes are used in other places,  maybe a MirrorTexture method:

setPlaneFromRenderList(targetForMat : Mesh, distance : number) : void;

I do not know how to do this, but given the position of the target mesh for the material, might make it easier to use this texture.  Not sure about when RenderList has more than 1 item, or even if it need be consulted.

Link to comment
Share on other sites

@RaananW

Sorry, I forgot it was written in french.

In my idea, the parts were defined arbitrary by the mesh developer (not the BJS user).

There are here two different roles in the rest of the post :

  • the developer implementing a basic/complex shape in the API,
  • the BJS user, using the API for its own purposes in its own code.

 

Ex : I'm a the developer.

I implement an algo to construct, say, a torus knot as a basic shape for other users.

Only I know how vertices are ordered by my algo, ok ?

So when iterating along my mesh construction, why not refer groups of vertices (parts) which have a logical sense together : faces, rings, etc.

 

Then propose a direct access to these parts to BJS users .

getPart() would be implemented by the developer here.

 

It would be easier to set different material to a given mesh imho for example.

As a BJS user now, I wouldn't have to retrieve what vertices and how many to handle a face, a ring (a type of part predifined by the mesh developer)

 

Sorry for drifting away, it was not about mirrors, but only about the question "how to know what vertices to access" on a given mesh.

 

anyway, forget it, DK prefers good mesh documentation (cube : face1 = vertices[0..5], face2 = vertices[6 ..9], etc)

 

maybe I'll do it as an extension... after having read each basic shape construction code :D

Link to comment
Share on other sites

Yep, would make sense for the MirrorTexture...

I'll think of a way to integrate it and suggest DK a new function.

 

@Jerome - I think this is a great idea, but it is hard to implement it in the general mesh :-)

I wouldn't use "face" though, as this has a difference meaning in many kind of meshes (and .obj file for example uses "faces" to describe the triangles that are created using three vertices/normals/uvs)

Link to comment
Share on other sites

yep

"face" (in general meaning, not 3D design triangles) makes sense only for a cube

"ring" for a cylinder, or anything constructed with... rings. Have the sphere mesh wireframed, you'll see the algo uses kind of rings.

etc

 

My idea was about logical parts (arbitrary chosen by the mesh developer).  ;)

Not mandatory in the general mesh...

Rather a kind of optional interface (an array of submeshes or vertexData or...I don't know  ;) ) each mesh could implement (or not).

Link to comment
Share on other sites

 

On 11 Feb. 2015 6:35am, JCPalmer wrote:

As far as the distance being the fourth arg, I noticed changing it made the size of the reflection change.  The minus sign is a little perplexing.  Is that because the reflection is "into" the mirror?  (Rhetorical,  I'll just guess till I like it)

 

First of all, in your post I like the "Eat Me" element - which is of course essential to your scene. :lol:

 

Yes, the fourth argument is basically a symmetry setting globally for all reflected objects in your relection list, and the size of all reflections on the plane should appear to become larger as the whole number value (in the 4th arg) approaches 0.0, and until each reflection appears in the same position and the same size as their respective reflected object (no reflections displayed at a value of 0.)  Thus reflections will appear smaller as the whole # value moves further away from 0.0 once a reflection is displayed using a positive or negative number value.  A value of 0, and values greater or less than 0.0 will show no reflections at all - depending on the orientation of your reflection plane - and if this isn't fully clear, a positive value used in the 4th argument applied to your specific scene will produce no reflections at all - based wholly on the specific orientation of the relection plane you created.  

 

And if you're not yet or fully familiar with the first 3 arguments in creating the new reflection plane, they represent the position and angle of all object's reflections - depending on the orientation of the reflection plane you've created.  These first 3 arguments need to be dramatically different if you are reflecting on global (x, z) vs. global (x, y) vs. global (y, z).

 

These 4 arguments baffled me for some time, until I experimented in the Playground - but it's far more difficult to explain than I thought.

 

Cheers,

 

DBawel

Link to comment
Share on other sites

My short-cut thought for the 1st 3 was they represent a direction.  Take the normal of a vertex of the Mesh plane it is going to be the material for & multiple by -1 (cause it is a reflection).

 

Your description is likely more accurate, but if mine is always right, a lot easier to deal with.

 

The 4th is a size, no short-cut, other than "it's a f**ked up inverted size with a sign dependent on stuff".

Link to comment
Share on other sites

You are quite correct - the first 3 arguments do represent direction; and the values are also multipliers, as I have used values greater than 1.0, and less than 0.0 and -1.0.  The first 3 arguments for the mirrorPlane attribute represent (x,y,z) locally, and using values greater than 1.0 and less than -1.0 provide additional offset in how the renderer computes normals; beyond the object in which the StandardMaterial is attached.  I have often thought about using all 4 arguments to more "simply" simulate some non-standard, non-uniform lenses and materials, and will put some time into this soon.  Thanks for opening this thread, as I hope no one else will have to spend the time it took me to understand how this works for such an essential "shader" as reflection.

 

I'll soon begin creating Documentation on dimensional space and dimentional math relative to BJS on the documentation site, and I'll certainly add this to that area of the documentation.

 

Thanks  :)

Link to comment
Share on other sites

My conversations turn into code a very high % of the time.  I do not know if the test to flip the sign of the 4th arg negative is right, just a guess.  Should be some multiplier arg to allow normals to be > than 1, in this case?

 

Recommended method to add to MirrorTexture:

        /**         * Build the mirrorPlane for the texture, based on where the texture is going to be applied         * @param {BABYLON.Mesh} intendedMesh - Mesh applying texture (should be a Plane)         * @param {number} projectionDistance - How far meshes should appear to be from the mirror.           * The lower the value, the larger they will appear.  Must be > 0.         */        public defineLense(intendedMesh : BABYLON.Mesh, projectionDistance : number) : void{            var normals = intendedMesh.getVerticesData(VertexBuffer.NormalKind);            // change the sign of the normal, since the image is coming the direction opposite the mesh            this.mirrorPlane.normal.x = -1 * normals[0];            this.mirrorPlane.normal.y = -1 * normals[1];            this.mirrorPlane.normal.z = -1 * normals[2];                                    // need to change the sign of projectionDistance, when normal.z is negative            if (this.mirrorPlane.normal.z < 0) projectionDistance *= -1;                        this.mirrorPlane.d = projectionDistance;        }
Link to comment
Share on other sites

For myself, without additional code I cannot determine an answer to your question.  As for reflection plane normals, any value other than 1.0 or -1.0 will display results as an offset in firing linear z rays from the camera's position and orientation - to fire off of the reflection plane and the object in which it is attached (which also determines camera distance to reflection plane.)  But if you're speaking to the remark in the above code concerning projectionDistance, and setting a value for this arg. (4th arg. in babylon relection planes), you'll find that a reflection will oly be displayed for either a value of >0 or <0 and never both; which is a determination of the orientation of your reflection plane and the postion and orientation of the active scene camera.  I hope I undestood the question.  Cheers.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...