[SOLVED] Scale & Attach Camera Issue

Hello Guys,
When loading a big model to the scene and scaling it down a lot (like 100 times smaller) and then attaching a camera node to it, I have a problem:
It seems that in order to see something, I need to translate the camera as if I didn’t scaled down the model. For example let’s say the model size is 100x100x100 meters and I scale it down to 1x1x1, then when attached the camera to the model’s node I need to translate it 100 meters in ordewr to see something.

Is that makes sense or is it a known issue?

Thanks
Adi

can i see how you scale it? some code please :slight_smile:

1 Like

here is part of the loading model function. I can send all the function code if needed. I;m creating a node, attaching the model to it (gltf based), then scale the node:

final Node model = new Node();
    model.attachChild(mm); // add it to the wrapper

    /////////////////////////////////////////////////

    SkeletonControl skeletonCtrl = mm.getControl(SkeletonControl.class);
    if(skeletonCtrl!=null && hostAppType==0) {
        skeletonCtrl.setHardwareSkinningPreferred(false);// for Android 7 bug
    }

    final String modelName = name+"@"+modelInst.thread.threadId;
    AppModel am = new AppModel(model);
    am.resource = resource;
    models.put(modelName,am);

    model.setName(modelName);

    final Vector3f scale;
    if(modelInst.scaleExpr!=null) {
        float sc = Float.parseFloat(modelInst.scaleExpr.evaluate(this).toString());

        model.scale(sc, sc, sc);
        scale = new Vector3f(sc, sc, sc);

    } else {
        model.scale(resource.scaleX, resource.scaleY, resource.scaleZ);
        scale = new Vector3f(resource.scaleX, resource.scaleY, resource.scaleZ);
    }

could you describe what values are under variables? especially “sc” variable.

sc is a float value which is evaluated in run-time, for example in my case 0.1 which I assume scales the model (node) to be 10 times smaller

The easiest way to get help is reproduce the issue in self contained class we just can copy past and run. Then everything is there. This reduces the ping pong question/answer cycle to a minimum.
I do this if I have code or render issues and sometimes I find the bug by myself doing so :smile:

yes, its correct, but i need to know variables to help (see where there might be issue).

IMO you should use debugger and see where it go, and tell us what methods it execute here exactly.

i see 2 lines of scale, both use different variables.

If you scale a node down 100 times then the children of that node will still operate in “child space”. ie: if you have a person that is 100 units tall and add a camera as a CHILD then that camera will be in 100 units tall space.

That’s the way scene graphs work.

If you want the camera to be not in “child space” then don’t put it in child space. Add our model and camera to a parent node and scale the model.

BTW, the scaling is working fine. Just the attached camera is working in an unexpected way…

then like pspeed said, also depends what element in scepe graph you scale exactly.

Also to be sure i would add CameraNode After scale, not before.

“And by ‘unexpected’, I mean…”
https://imgur.com/9zm9BcX.png
“COMPLETELY EXPECTED!”

Heheh.

Think about if you were placing a hat as the child of that model.

Check the frustum dimentions of your Camera, especially the near and far planes.

Order matters not. Only scene graph organization.

https://i.imgur.com/p2Xizki.jpg

1 Like

So many responders missing the point here so I will modify the post a little to make it clearer:

OK, I think I almost got the point :slight_smile:
The thing is I don’t know in advance that my user will want to attach the camera to the model so I cannot add both the model & camera to the node and just then scale it.
It needs to be done dynamically.

You are attaching things to a model(node) rather than a parent node.

https://wiki.jmonkeyengine.org/jme3/the_scene_graph.html#scene-graph-and-rootnode

The model is just a visual object.

Notice the warrior part of the image. Consider one the camera, the other the model. Both attached same parent.

Edit: Paul is telling you to scale the model and do not attach the camera to its node.

No, I have a parent node holding both the model’s spatial and the camera node

That is whats supposed to happen.

https://wiki.jmonkeyengine.org/jme3/advanced/making_the_camera_follow_a_character.html#camera-node

Where the example says camNode.setLocalTranslation(new Vector3f(0, 5, -5)); , you have to supply your own start position for the camera. This depends on the size of your target (the player character) and its position in your particular scene. Optimally, you set this to a spot a bit behind and above the target.

I hacked this stuff together from wiki and the test-data library.

package mygame;

import com.jme3.app.SimpleApplication;
import com.jme3.bounding.BoundingBox;
import com.jme3.light.AmbientLight;
import com.jme3.light.DirectionalLight;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager;
import com.jme3.scene.CameraNode;
import com.jme3.scene.Node;
import com.jme3.scene.control.CameraControl.ControlDirection;
import com.jme3.system.AppSettings;

/**
 * This is the Main Class of your Game. You should only do initialization here.
 * Move your Logic into AppStates or Controls
 * @author normenhansen
 */
public class Main extends SimpleApplication {

    public static void main(String[] args) {
        AppSettings appSettings = new AppSettings(true);
        appSettings.setTitle("Test Model Scale");
        
        Main app = new Main();
        app.setSettings(appSettings);
        app.start();
    }

    @Override
    public void simpleInitApp() {
        // Disable the default flyby cam
        flyCam.setEnabled(false);
        //Set background color
        viewPort.setBackgroundColor(ColorRGBA.LightGray);
        
        /** A white, directional light source */ 
        DirectionalLight sun = new DirectionalLight();
        sun.setDirection((new Vector3f(-0.1f, -0.7f, 1.0f)).normalizeLocal());
        sun.setColor(ColorRGBA.White);
        rootNode.addLight(sun);         
        
        /** A white ambient light source. */ 
        AmbientLight ambient = new AmbientLight();
        ambient.setColor(ColorRGBA.White.mult(.2f));
        rootNode.addLight(ambient); 
    
        Node parent = new Node("Parent Node");        
        
        //Add the model
        Node ninja = (Node) assetManager.loadModel("Models/Ninja/Ninja.mesh.xml");
        parent.attachChild(ninja);

        //Uncomment to scale.
//        ninja.scale(.1f);
        
        //create the camera Node
        CameraNode camNode = new CameraNode("Camera Node", cam);
        //This mode means that camera copies the movements of the parent:
        camNode.setControlDir(ControlDirection.SpatialToCamera);
        //Attach the camNode to the parent:
        parent.attachChild(camNode);
        
        //Move camNode, e.g. ahead and above the parent:
        BoundingBox bounds = (BoundingBox) ninja.getWorldBound();
        camNode.setLocalTranslation(0, bounds.getMax(new Vector3f()).y * 2, bounds.getMax(new Vector3f()).z *-25);        
        System.out.println(camNode.getLocalTranslation());
        //Rotate the camNode to look at the parent:
        camNode.lookAt(parent.getLocalTranslation(), Vector3f.UNIT_Y);
        
        rootNode.attachChild(parent);
    }

    @Override
    public void simpleUpdate(float tpf) {
        //TODO: add update code
    }

    @Override
    public void simpleRender(RenderManager rm) {
        //TODO: add render code
    }
}

Uncomment the scale and take note of the translation of the cam node and see that the model looks the same in both runs even though ninja is scaled.

This is just a hack specific to this model for demo. Others can chime in on a good formula for moving the camNode based on scale and translation.

2 Likes

Then scale the model child and not the parent node.

Yesssss!!! that was my mistake
Thank you so much guys for the instant help

1 Like