Jump to content

Live reflection on 3D objects


dsman
 Share

Recommended Posts

What I am looking for reflection on 3D objects and not plane like mirror. 

 

I checked advanced texture playground code here : http://www.babylonjs-playground.com/#EKFLA

 

Following line in that example confuses me. 

mirrorMaterial.reflectionTexture.mirrorPlane = new BABYLON.Plane(0, -1.0, 0, -10.0);

It works for plane. But what about 3D mesh for example car body ?

 

Also I don't want to use cubemap . Just want to use live reflection. 

 

 

I have a scene in which I want to make one mesh reflect. I know mesh name . So I did following but obviously it won't work. 

var meshgloss = scene.getMeshByName("front_wall1");meshgloss.material.reflectionTexture = new BABYLON.MirrorTexture("mirror", 512, scene, true);var gloss = new BABYLON.Plane(0, -1.0, 0, -10.0); gloss.transform = meshgloss.transform ; meshgloss.material.reflectionTexture.mirrorPlane =  glossmeshgloss.material.reflectionTexture.renderList =  [commode];meshgloss.material.reflectionTexture.level = 0.5; 

On a separate note , is there a better way to create steel object ? Other than using cubetexture on it ?

Link to comment
Share on other sites

Regarding live reflection for complex meshes - 

A reflection texture renders a list of objects (set in the render list) to a given plane, just like the camera renders all of the visible meshes to your 2d screen. The plane is more than required  ;) . technically, you could create a reflection plane for each plane your mesh has (a box would have 6, a sphere would have... a lot) and use the submeshes and multimaterial support BabylonJS has to set a different reflection texture to all of them. I am pretty sure this will kill performance on high-poly meshes.

You can try doing it here - http://materialeditor.raananweber.com/ . Take the box, divide it to 6 equal submeshes and set each submesh with a reflection mirror texture. You will then have a cool mirroring cube. Try doing that with a different object and you will understand it's a hard task.

 

Regarding calculating a new plane - This was a long discussion as to the meaning of a,b,c,d etc'. I can only say how I calculate planes - 

I use BABYLON.Plane.FromPoints(p1, p2,p3) function, giving it 3 points in space that I know are on the plane . look here - https://github.com/BabylonJS/Extensions/blob/2d439c1806c2d6a74959404be365c23e866310c6/MaterialEditor/MaterialEditor/material/MaterialController.ts#L110

 

About the steel object - the reflection is the best effect I know to achieve that (I guess the other will have different suggestions). You don't have to use cube texture, you could use a single spherical or planar projection and then only need one single image. But it is technically the same, other than the number of images used. A reflection texture must be set.

Link to comment
Share on other sites

Well said, RaananW... and hi to you both, and to all forum users.

 

If you visit our CYOS, you will see a simulated chrome, done via shader, at that site. (I used CYOS' cool GET ZIP feature to do the robbery).  :)

 

I borrowed that sim-chrome technique and made a playground scene with it...  http://www.babylonjs-playground.com/#1IZ4X0

 

I'm not sure if it will be useful to you, but it sure does do a nice reflection-like activity... rather drool-worthy.  :)  It doesn't reflect any objects from the scene... but it reflects an image.

 

Over in the decals topic, deltakosh recently told me something about rendering a camera view as an image. 

 

"This is possible by rendering only the object and its decals to a rendertexture and then use this texture like any texture."

 

This means... you could "take a picture" of your entire scene from some camera view, create the renderTexture... then use IT as the refTexture (line 79 of the above demo) for the shader. 

 

The viewers would see a reflection of your scene... because you took a picture of your scene at a certain angle.  The user would THINK they are seeing the scene reflected in the "metal", but no, its a renderTexture IMAGE of your scene.  Good sneaky fun.

Link to comment
Share on other sites

 @RaananW  Thanks for you answer. 

 

Even if we are limited to doing reflection on plane and not 3D mesh, it is fine. But method of creating reflectionTexture requires "mirrorPlane" in form of BABYLON.Plane() .  To create that plane I need to know normal and distance from world's center if I am not wrong. 

 

Now,  what to do in scenario where we are importing 3D Max model and we don't know position/rotation of mirror present in the model ? 

 

Basically I have mirror in my scene and I want to show live reflection in it. 

Link to comment
Share on other sites

I have to admit I am not the biggest 3D Max expert (I am probably not on the top 100,000 as well ;) ). 

I would simply do it using a bit of javascript after the scene has fully loaded.

Read 3 points from the plane (the actual mesh), convert them to world coordinates and use them to set the mirror plane:

var mesh = thePlaneMeshToBeUsed; //or any other mesh, but you will have to make sure that the 1st 3 points are the ones you are looking for)var subMeshIndex = 0; // in case you want to set the plane to a submesh and not the main meshvar pointsArray: Array<BABYLON.Vector3> = [];var meshWorldMatrix = mesh.computeWorldMatrix();var verticesPosition = mesh.getVerticesData(BABYLON.VertexBuffer.PositionKind);//handle submeshesvar offset = 0;if (this.isMultiMaterial) {    offset = mesh.subMeshes[subMesIndex].indexStart} for (var i = 0; i < 3; i++) {    var v = mesh.getIndices()[offset + i];     pointsArray.push(BABYLON.Vector3.TransformCoordinates(BABYLON.Vector3.FromArray(verticesPosition, v*3), meshWorldMatrix));}var plane = BABYLON.Plane.FromPoints(pointsArray[0], pointsArray[1], pointsArray[2]);

I guess others have different ways of doing that, I found this the most useful one. 

Link to comment
Share on other sites

@RaananW  I am sorry if I sound dumb . Be will have to set size of plane  that we get by BABYLON.Plane.FromPoints,   No ?  I understood above method of getting mirrorplane. But I didn't get the result in my app. I still check what could be wrong. But I am doubting the size of plane could be the issue. 

 

Also on separate note.  I have another problem of generating parallel planes dynamically to existing plane in the model , which can be positioned and rotated anywhere. Do you think FromPoint method solution can help me there ? I had asked this in seperate thread here : http://www.html5gamedevs.com/topic/13336-how-to-draw-parallel-mesh/

Link to comment
Share on other sites

Hi,

http://en.wikipedia.org/wiki/No_such_thing_as_a_stupid_question

 

The Plane set by the BABYLON.Plane.FromPoint is only the plane definition (in space) required for the mirror reflection. the actual size of the Mesh-Plane (created using BABYLON.Mesh.CreatePlane for example) is the one setting the size of the mirror.

 

http://www.babylonjs-playground.com/#PHNEX is using ths code i pasted with two modifications -  mesh.computeWorldMatrix(true); to force new computation, and the subMeshIndex was a typo...

See if it helps you.

 

BTW, only two meshes were added to the render list, so not all spheres will reflect. Developers are the laziest people in the world...

Link to comment
Share on other sites

I realized that reflectionTExture.mirrorPlane is logical plane and not mesh and hence it doesn't require size after posting question. 

 

In my code if I use following it works fine and here's output - http://prntscr.com/6ndv6i

mirrormesh.material.reflectionTexture.mirrorPlane =   new BABYLON.Plane (0,0, 1, -700.0) ; 

But if I use your method , it shows transparent mirror - http://prntscr.com/6ndwas

var mirrormesh		= scene.getMeshByName("mirror_reflective_material"); // this is mesh from imported model			var pointsArray  = [];			var meshWorldMatrix = mirrormesh.computeWorldMatrix();			var verticesPosition = mirrormesh.getVerticesData(BABYLON.VertexBuffer.PositionKind);			  			for (var i = 0; i < 3; i++) {				var v = mirrormesh.getIndices()[ i];				 pointsArray.push(BABYLON.Vector3.TransformCoordinates(BABYLON.Vector3.FromArray(verticesPosition, v*3), meshWorldMatrix));			}			var mirrorplane = BABYLON.Plane.FromPoints(pointsArray[0], pointsArray[1], pointsArray[2]);			 							mirrormesh.material.reflectionTexture = new BABYLON.MirrorTexture("mirror", 1024, scene, true); //Create a mirror texture			 			mirrormesh.material.reflectionTexture.mirrorPlane =   mirrorplane ; // new BABYLON.Plane (0,0, 1, -700.0) ; 			mirrormesh.material.reflectionTexture.renderList =  scene.meshes;			mirrormesh.material.reflectionTexture.level = 0.9; //Select the level (0.0 > 1.0) of the reflection			mirrormesh.material.diffuseColor  = new BABYLON.Color3(0.2,0.2,0.2);

If I just change "mirroeplane" to "new BABYLON.Plane (0,0,1,-700.0)" for reflectionTexture.mirrorPlane it shows up fine. 

 

What could be wrong here ?

Link to comment
Share on other sites

have you tried forcing the calculation of the world matrix?

line 3 - 

var meshWorldMatrix = mirrormesh.computeWorldMatrix(true);

 

Might be the problem.

 

Another problem might be that the plane that is actually calculated is wrong due to wrong points selected. Is this mesh you selected a complex mesh? or really only a plane?

You need to know the index positions of the correct points you want to use.

Link to comment
Share on other sites

@RaananW  Looks like the mesh is not a plane. It was cube. Sorry for all trouble. Now the question is how do I get plane of the face of cube which is facing the camera ? 

 

The cube where I want to show mirror reflection could be anywhere in the model. But one thing is sure that it will be cube,  And that we will want show reflection on face of cube , which consists of four closest corner point of cube from camera.  

Link to comment
Share on other sites

Finding the right points is the trick here - You need to know the indices of the points you want to use. This is rather complex to explain how to do it. But i can suggest something else - 

 

This is a silly hack, but it is the simplest I could find, without analyzing the vertex data of the mesh itself:

  1. Add a pick trigger to the mesh (example at http://www.babylonjs-playground.com/ , choose picking). Make sure fast checking is on to get the correct points.
  2. Click at three points on the plane you want to create a mirror on and log them.
  3. Use those three points to create your plane  :)  .

 

It might sound silly, and learning how to calculate the plane correctly might be a bit more helpful in other cases, but for a quick result that will work,

Link to comment
Share on other sites

@RaananW  I knew about picking method. But that works only at development time and I will have input static hardcoded values for plane in the code.  In my app , I want this to be done completely dynamically at runtime. 

What at max we can do is to put four markers (invisible cubes or something)  in 3Dmax model at four corner around mirror. So that in babylon runtime we can find those markers and create plane which contains them. 

 

But then I don't know what to use as marker in 3Ds max. Shall I use small cubes or spheres ? 

Link to comment
Share on other sites

You will have to detect the plane by yourself. I believe the plane must be recalculated if the object moves, so I guess you will anyhow have to do this. If the object doesn't move, getting the plane's values once will suffice, this is why I suggested the picking hack.

 

Some good resources to start with would be - http://mathworld.wolfram.com/Plane.html or http://keisan.casio.com/exec/system/1223596129 , the variables you are looking for is a,b,c,d that actually construct the plane's equation.

The first 3 variables (a,b,c) could be taken from a normal of one of the points (or if you know the normal, simply use it). d however must be calculated using a known point on the plane. So you will have to know the position of the mesh points you want to use as a mirror. Or at least their absolute position.

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...