Scale around a center point?

Started by sticksen, October 09, 2011, 03:20:19 PM

Previous topic - Next topic

sticksen

Hi,

is there any way to scale an Object3D around some arbitrary point? As far as I can see, currently it´s always scaling around the object´s origin in (0,0,0) , so I would have to calculate something to translate it afterwards? I´m needing this for correct Pinch-Zooming.

Cheers,
Marc

K24A3

One option would be to move the camera to the location of the initial pinch, or translate/move the object at every frame aligned in ratio to the pinch origin.

Or if you want the object pre-translated, you can load the object, translate it into position, then call rotateMesh to update the meshes translation. Not 100% sure if that would work but I imagine it would.


EgonOlsen

Quote from: K24A3 on October 09, 2011, 04:05:10 PM
Or if you want the object pre-translated, you can load the object, translate it into position, then call rotateMesh to update the meshes translation. Not 100% sure if that would work but I imagine it would.
Swap "rotateMesh" with "translateMesh" and it should make the translation permanent.

EgonOlsen

I'm not sure what "scaling around a point" actually means!?

sticksen

Quote from: EgonOlsen on October 09, 2011, 04:26:26 PM
I'm not sure what "scaling around a point" actually means!?

well, currently the object 'grows' to the right and to the bottom, while the upper left corner stays at the same place. I need to 'grow' it in all 4 directions, while only a certain point (given by e.g. a pinch-zoom event) stays at the same place.

EgonOlsen

#5
The "growing" of the object has to do with it's position in object space and subsequent with it's translation in world space. Scaling is simply done by multiplying the object space vertices with the scale factor. If your model starts at (0,0,0) this point will never change because (0,0,0)*some scalar is still (0,0,0). You can either apply an offset to the world space translation or, and that is what K24A3 suggested, you can translate the object once so that the position in object space fulfills your requirements and make this translation permanent by calling translateMesh() (and clear the translation afterwards).

sticksen

oh ok...so, just to verify if I understood it correctly: if I have 100 objects, all as a child of an Object 'rootNode', I have to get my point to scale around, read out all Objects, translate them, scale, translate them back? It´s not possible to just translate my rootNode and then scale, because the object space of the childs doesn´t change, right?
Maybe then I´m rather going for option 2...

Cheers,
Marc

EgonOlsen

A said, scaling just multiplies the vertices with a scalar. And translation without any rotations being used is just an addition. So if you have two vertices, like (-10,0,0) and (10,0,0) and scale them by 2, you'll get (-20,0,0) and (20,0,0). Translate them by (100,0,0) and you end up with (80,0,0) and (120,0,0) with your virtual center at (100,0,0)...and i guess that is what you expect. However, if your object's center isn't (0,0,0) (which it obviously isn't), then you'll get different results...for example with (0,0,0) and (20,0,0), you'll end up (doing the operations like above) at (100,0,0) and (140,0,0) and your virtual center is at (120,0,0)...and any subsequent scale won't change that vertex at (100,0,0), so it looks like as if the mesh extends to the left only.

sticksen

Ok, I tried to get it working, but somehow I can´t figure it out.


private final static float textureMaxX = 100f;
private final static float textureMaxY = 130f;

//in some init function. this draws a rectangle which is later been filled by a texture
Object3D background = new Object3D(2);
SimpleVector vert1 = new SimpleVector(0, 0, 0);
SimpleVector vert2 = new SimpleVector(textureMaxX, 0, 0);
SimpleVector vert3 = new SimpleVector(textureMaxX, textureMaxY, 0);
SimpleVector vert4 = new SimpleVector(0, textureMaxY, 0);
background.addTriangle(vert3, 1, 1, vert2, 1, 0, vert1, 0, 0);
background.addTriangle(vert3, 1, 1, vert1, 0, 0, vert4, 0, 1);
world.addObject(background);

//in onDrawFrame
background.translate(100, 0, 0);
background.translateMesh();
background.scale(1.01f);
background.translate(-100, 0, 0);
background.translateMesh();


Now whatever values I translate and back-translate the background, it always scales around the center in this example. My first example, which scaled around top left was a 'rootNode', which was instantiated by Object3D.createDummyObj() and is used to group objects. From the above code, I expected to receive a scaling around the right edge of my background rectangle. Am I doing something wrong?

Cheers and thanks for all your efforts!
Marc


EgonOlsen

Doing it that way will have no visual effect, because you simply undo the translation you did before. What i meant was more like


background.translate(100, 0, 0);
background.translateMesh();
background.clearTranslation();
background.scale(1.01f);

sticksen

Still not the wished effect...it still scales around the center. Does it matter when the object is built? I need to modify the object space coordinates after build() was called. Do I need a VertexController then? I read this:


//mesh.setVertexController:
A VertexController is the only way for an application to modify the vertex data of jPCT's meshes after build-time.

Cheers,
Marc

stownshend

I've been following this thread and still don't understand what it means to scale around an arbitrary point? Are you talking about distorting the original model in any way? Or simple scaling it (around the centre) and translating it to accommodate this point?

By distortion I mean something like (see attached image)

[attachment deleted by admin]

EgonOlsen

In that case, you could try the following (untested...):

Compile the object in dynamic mode by yourself:


background.compile(true, true);
background.build();


Then, after doing the translateMesh(), touch the object like so:


background.translate(100, 0, 0);
background.translateMesh();
background.clearTranslation();
background.touch();
background.scale(1.01f);


I've no idea if this will work...if not, a VertexController might be the better option in this case. However, i don't get why you want to do the translateMesh() at runtime. I thought that only the scaling has to happen at runtime, so the idea was to do the translate before calling build() and do only the scale() in onDrawFrame like so:



// At load time
background.translate(100, 0, 0);
background.translateMesh();
background.clearTranslation();
background.build();

// At runtime
background.scale(1.01f);


sticksen

Hi again,

@stownshend: No distortion or anything like that needed.

Sadly that doesn´t work either.
Well, problem is: the 'point to scale around' changes during runtime. As I mentioned, I´m implementing a pinch-zoom gesture, and every time the user puts 2 fingers on the screen, the scalepoint changes. Thus I have to modify the object at runtime...

I stumbled upon something else: I now don´t call createDummyObj() for my rootNode anymore, instead I´m just instantiating the exact same rectangle as for the background. Now when I don´t call build on the rootNode and scale it, all children are scaled around top left. After calling build for the root, all childs scale around the center. So build definitely does something that influences the scaling. Damn closed source, it was easier when one could have a look at what it´s doing...:)

Also, javadoc says there's something like unbuild(), but I guess this function isn´t public anymore?

Cheers,
Marc

EgonOlsen

unbuild() isn't available in jPCT-AE. It's desktop only, because it works only with the hybrid render pipeline that the AE version doesn't feature. But you've finally managed to confuse me...i have a vague idea of what you want, but i'm not really sure how this is supposed to look like. Maybe a rough painting or similar might help to understand this. I'm not sure how the object is supposed to changed if you, for example zoom starting at the lower left corner compared to starting at the upper right. I would think that it doesn't matter as long as you are scaling it around it's center.