Jump to content

Texture's source image aspect ratio


dabrorius
 Share

Recommended Posts

Hi,

I'm trying to load a photo as a texture on to a piece of a (square) mesh. The problem is that original photo is not square so I need to somehow figure out aspect ratio of it so I can modify the mesh to fit it. 

What's the best way to do it? I can fetch the image via url using pure JS but that does not seem right and introduces some problems because that request is asynchronous. Any suggestion?

Link to comment
Share on other sites

Hi dabrorius... welcome to the forum.  I am not an expert on this at all... but... I have an idea.  I am going to assume that you do not know what the dimensions of the picture are, and you would like to use Babylon.js to help ascertain the picture size, so you can make a plane/rectangle which has the same proportions as the image.

 

First, in our Playpen Tutorials, take note of the Materials tutorial and the Discover Basic Elements tutorial.  In basic elements, in the "Grounds' section, you will find the command CreateGround.  It just makes a plane (square) that you can easily set width and height upon.  We won't make one yet, but just keep that in mind.

 

Now, in the Materials tutorial, you will find this line...

 

materialSphere1.diffuseTexture = new BABYLON.Texture("grass.png", scene);

 

Lets change that line to...

var mypicture = new BABYLON.Texture("picture_url", scene);  // rem about CORS rules for cross-domain

Adjust 'picture_url' to a working picture URL, of course. Now you've got a variable (mypicture) that is the picture (if the load was successful).

 

Next, look at the API for the BABYLON.Texture class object... http://doc.babylonjs.com/page.php?p=24708 .  Scroll down until you see the .getSize() method.  "Return the size of the texture in an array"

 

So...  maybe next you can try...

var sizearray = mypicture.getSize();console.log(sizearray); // examine the array's format & compare values to test pic sizes.

Let's pretend the sizearray returns:  [1024, 768]

 

I bet you know what's coming next.  That's right... our friend the ground plane (from basic elements) and its material.

var ground = BABYLON.Mesh.CreateGround("gnd", sizearray[0]/100, sizearray[1]/100, 1, scene);

That makes a plane that is 10.24 (units) wide and 7.68 (units) deep/high (because we divided both values by 100).

 

Note:  You are not 'required' to divide by 100.  You could make the ground plane be 1024 units wide and 768 units high... if you prefer.  Or divide by 10, so the ground plane is 102.4 units by 76.8 units.  Just place the camera far enough away from the picture so that you can see it completely.

 

Continue with applying the picture to the ground plane?  Ok. 

Now you create a new BABYLON StandardMaterial for the ground, and apply it...

var gndmat = new BABYLON.StandardMaterial("gmat", scene);ground.material = gndmat;

Now that you have a standard material applied on the ground, make the picture be its diffuseTexture...

gndmat.diffuseTexture = mypicture;

In theory, you are done... if I understand the issue correctly.  :)

 

Summary: 

   - Make a babylon texture-class object that does an image load

   - Call the getSize() function on it... to get its size (into an array)

   - Use the values in that array (divided by identical values - we used 100)... to make a ground plane (that is proportionally identical to the picture, ratio-wise).

 

Disclaimer:  I could be completely wrong and/or be misunderstanding.  I'm not responsible for any computer damage caused by using this idea.  hehe.  There are VERY smart people here who will likely have more and better ideas.  I am not very experienced on this subject AT ALL.  You have been warned, dabrorius.  :D

 

Again, welcome to the forum!  Keep us posted on your progress and discoveries, and troubles... if you have some.

Link to comment
Share on other sites

Hi Wingnut :)

Thanks a lot for a very detailed explanation, I actually understood most of the stuff already but I just missed the getSize() method.

Now the only problem left is that if I call getSize() immediately after creating the texture I get width and height 0. I guess that's because image wasn't loaded yet. Is there's some kind of callback method that I can pass, for example "onTextureLoad" or something?

Link to comment
Share on other sites

Ahh, good, you are not quite as newbie as you COULD have been.  (I never know how experienced the person is, so I over-explain sometimes... sorry.)  :)

 

Read further past the getSize() method.  See the isReady() method?  Again, I don't promise that it works... I've never used it.  But it's worth a try.  :)

Link to comment
Share on other sites

Hi dabrorius,

 

I believe you can leave the plane as you wanted it, and simply change the uScale and vScale of the texture.

Made a small example, I hope this is what you meant : http://www.babylonjs.com/playground/#2JUBQI 

The only downside of wingnut's suggestion (which i believe would work) is that the object will then have to be proportional to the image. 

Link to comment
Share on other sites

Good point, raananw. 

 

Maybe I misunderstood... but I thought dabrorius wanted to make the mesh fit the picture, and not make the picture fit the mesh.  *shrug*  That's why the method I used... measured the picture first, and then created the mesh.  But dabrorius, raananw is absolutely correct.  By scaling the picture, you can make it fit any planar mesh.  But... you will be changing the picture's aspect ratio, unless you use identical values for uScale and vScale. 

Link to comment
Share on other sites

Ahh, good, you are not quite as newbie as you COULD have been.  (I never know how experienced the person is, so I over-explain sometimes... sorry.)  :)

 

Read further past the getSize() method.  See the isReady() method?  Again, I don't promise that it works... I've never used it.  But it's worth a try.  :)

 

Well isReady() method is ok but then I have to poll it every X milliseconds and check if it has loaded, I would expect there to be a callback function since it's javascript after all.

 

Hi dabrorius,

 

I believe you can leave the plane as you wanted it, and simply change the uScale and vScale of the texture.

Made a small example, I hope this is what you meant : http://www.babylonjs.com/playground/#2JUBQI 

The only downside of wingnut's suggestion (which i believe would work) is that the object will then have to be proportional to the image. 

Well this is also an option for sure, but I'm just troubled by finding the width/height of the image currently.

Link to comment
Share on other sites

Hey there, 

 

 

Well isReady() method is ok but then I have to poll it every X milliseconds and check if it has loaded, I would expect there to be a callback function since it's javascript after all.

 

Well this is also an option for sure, but I'm just troubled by finding the width/height of the image currently.

 

 

scene.executeWhenReady is available here  :)

 

Cheers, 

Link to comment
Share on other sites

  • 11 months later...

Thank you everyone for all of the above.

... So in order to create a plane with the same aspect ratio as an image, I actually have to create a "ground" ?

I mean if I create a regular type of BABYLON.plane - it appears that it can only ever be square?

 

What I'm trying to do is create a click button that "hangs in space" ... it is a rectangular button - I already got the graphic.

 

My first thought was use a sprite, which worked perfectly in terms of the graphic, but seems to come a cropper if you want it to respond to mouse-over.

So then I figured I would use a plane, but this seems to have aspect ratio problems.

The problem with using "Ground" in the first instance is that I'm going to have to rotate it.

 

As a newbie, I'm thinking there has got to be an easy way to do this, and I just don't know what it is.

 

Big thanks for help.

Link to comment
Share on other sites

Ok, but BABYLON.Mesh.CreatePlane creates a planar Mesh structure, right?

 

... But one of my EWWBLs is that it will only create a square mesh.

I suppose if I made the PNG into a square with whatever part of it transparent, that would stop the problem of the material getting stretched in one of the dimensions.

 

But then mousing over the transparent portion would register as a mouse-over event which would be wrong.

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