Strange Mesh position when scale up and down

Hello, every one:

I create a sphere by the following code:

Sphere b = new Sphere(zSamples, radialSamples,raius);
Geometry geom = new Geometry("Sphere",b);
Material mat = new Material(assertManager,"Common/MatDefs/Mics/Unshaded.j3md");
mat.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
mat.setColor("Color",myColor);
geom.setMaterial(mat);
geom.setQueueBucket(Bucket.Transparent);
rootNode.attachChild(geom);

Then, I create many Points by mesh in this way:

  for(....){
  Mesh  mesh = new Mesh();
  mesh.setPointSize(1.0f);
  mesh.setMode(Mesh.Mode.Points);
 mesh.setBuffer(Type.Position,3,BufferUtils.createFloatBuffer(vertex[k]));
 mesh.updateBound();
 mesh.updateCounts();
 Geometry geom = new Geometry("point"+k,mesh);
  Material mat = new Material(assertManager,"Common/MatDefs/Mics/Unshaded.j3md");
mat.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
mat.setColor("Color",colors[k]);
geom.setMaterial(mat);
geom.setQueueBucket(Bucket.Transparent);
rootNode.attachChild(geom);
  }

The sphere and points are presents well by jme3 .
However, when i scale up. Some points disappear, they seems to be from “out” the sphere to “in” the sphere.

Please see the attach pictures.

When i set the sphere to be transparent, all Points are visible when i scale up and down.

That’s a common misconception when scaling in 3D. Your initial reaction would be that the local translation of the points would be adjusted when you scale up … but they are not. Here is an example. Let’s say you have a spear with a radius of 1.0f located at 0.0f, 0.0f, 0.0f. You now place a point at 1.1f, 0.0f, 0.0f … Effectively 0.1f units away from the right edge of the sphere. Now you scale the point and the sphere by 2.0f. The spear’s right most outer edge is now at 2.0f, 0.0f, 0.0f but your point is STILL located at 1.0f, 0.0f, 0.0f … Your sphere just ate up your point because it expanded well past your point’s location.

I your example you would have to move the points away from the center of the sphere in the proportion of your scaling. Or batch your geometry if you can.

…or scale the parent.

1 Like

Thank you so much for the reply. But I am still a little confused.
(1) I scale up or scale down the jme3 scene by mouse, not by geom.scale() or geom.setLocalScale().
(2) I do some modification as follows:
For the sphere, I add geom.setLocalTranslation(Vector3f.ZERO). The center of this sphere is (0,0,0), the radius of it is “raius” as presented in the parameters.
For each Point,

    mesh.setBuffer(Type.Position,3, BufferUtils.createFloatBuffer(Vector3f.ZERO))
    ....
    geom.setLocalTranslation(vertex[k]); // vertex[k] is the position of this point

But this does not work either.
Could you please give more hints? Thanks.
(3) pspeed said that: “scale the parent?”
does it mean that i should use a group node

group.add(sphere)
group.add(each point)

So you are scaling the root node and not the children. That should be all that’s needed to have everything scale together. I only mentioned the parent thing to refute the other post that mentioned that you had to move stuff around and so on.

I can’t really see what the issue is with what you have but a simple single class full test case the exhibits the problem would be helpful. If nothing else, it might surprise you and just work.

Also, it’s hard to tell from your screen shots because they aren’t moving… but do the points seem to be positioned wrong or are they just being rendered under the surface? ie: is it a z-fighting/render-order problem or do the actually slide around underneath the semi-transparent version like they are physically under the surface.

pspeed I suggested that he moves the nodes because scaling the parent does not change the local translation of the children so his points are being swallowed by his sphere.

Local translation is irrelevant because it WILL affect the WORLD translation of the children.

Node
->Geometry(Sphere) 10 radius
->Geometry(Box) at (10, 0, 0)

If you scale the parent by 10 then the sphere in world space is like its 100 radius and the box will be at 100, 0, 0.

Hello, pspeed, thanks for your help.
I try to make my problem reappear by a simple example.

 /**
 * Test sphere and point. When scale the jme scene by mouse, some points will
* disapper when zoom in.
 *
 * @author jw
 */
public class CustomSphere extends SimpleApplication {

public boolean updateState = false;
CustomSphereState state = null;

public static void main(String[] args) {
    CustomSphere app = new CustomSphere();
    AppSettings set = new AppSettings(true);
    set.setSamples(4);
    app.setSettings(set);
    app.start();
}

@Override
public void simpleInitApp() {
    flyCam.setEnabled(false);

    ChaseCamera chaseCam = new ChaseCamera(cam, rootNode, inputManager);
    chaseCam.setDragToRotate(false);
    // chaseCam.setInvertVerticalAxis(true);
    chaseCam.setRotationSpeed(7); //Rubby 默认速度为1很慢,需要更快的。
    chaseCam.setMinDistance(1f);   //camera 与 the target 之间距离。(此值越小,说明越可以放大).否则使用默认值,有时候无法继续缩放,扩大
    chaseCam.setMaxDistance(1000f);   //camera 与 the target 之间距离。(此值越大,说明越可以缩小).否则使用默认值,有时候无法继续缩放,扩大
    chaseCam.setMinVerticalRotation(-FastMath.PI);
    chaseCam.setMaxVerticalRotation(FastMath.PI); //可以旋转的最大角度
    // chaseCam.setDownRotateOnCloseViewOnly(false);

    //light
    AmbientLight ambient = new AmbientLight();
    rootNode.addLight(ambient);
    DirectionalLight sun = new DirectionalLight();
    sun.setDirection(new Vector3f(1.4f, -1.4f, -1.4f));
    rootNode.addLight(sun);

    state = new CustomSphereState(10.0f);
    this.stateManager.attach(state);
}

@Override
public void simpleUpdate(float tpf) {
    if (updateState == true) {
        if (state != null) {
            this.stateManager.detach(state);
        }
        state = new CustomSphereState(10.0f); //TODO 传入新的数据:球半径,XYZ。 色标在CustomSphereState()中处理更新
        this.stateManager.attach(state);
        updateState = false;
    }
}

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

the other java class

public class CustomSphereState extends AbstractAppState {

private SimpleApplication app;
private Camera cam;
private Node rootNode;
private AssetManager assetManager;

//属性值

float radius; //用户传入的半径值,此值太大,会影响显示
float scale;  //需要将用户传入的半径值进行缩放,使之永远位于0~10之间


public float getRadius() {
    return radius * scale;
}

public void setRadius(float inRadius) {
    this.radius = inRadius;
    this.scale = 1.0f;
}

public CustomSphereState(float inRadius) {
    super();
    setRadius(inRadius);
}

@Override
public void initialize(AppStateManager stateManager, Application app) {//将此加入到StateManager才会调用此函数初始化
    super.initialize(stateManager, app); //To change body of generated methods, choose Tools | Templates.
    this.app = (SimpleApplication) app;
    this.cam = this.app.getCamera();
    this.rootNode = this.app.getRootNode();
    this.assetManager = this.app.getAssetManager();
 
    //创建模型
    this.createColoredSphere(16, 32, radius);//半径为5
    this.createPoints(radius);
}

public void createPoints(float radius) {
    int size = 500;
    Vector3f[] vertex = new Vector3f[size];
    for (int i = 0; i < size; i++) {
        float x = radius / 2.0f - i * 0.02f;
        float y = radius / 2.0f;
        float z = (float) Math.sqrt(radius * radius - x * x - y * y - 0.4);
        vertex[i] = new Vector3f(x, y, z);
        Mesh mesh = new Mesh();
        mesh.setPointSize(2.0f);
        mesh.setMode(Mesh.Mode.Points);
        mesh.setBuffer(Type.Position, 3, BufferUtils.createFloatBuffer(Vector3f.ZERO));
        mesh.updateBound();
        mesh.updateCounts();
        Geometry geom = new Geometry("point " + i, mesh);
        Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
        mat.setColor("Color", ColorRGBA.Red);
        geom.setMaterial(mat);
        geom.setLocalTranslation(vertex[i]);
        geom.setQueueBucket(RenderQueue.Bucket.Translucent);
        rootNode.attachChild(geom);

    }
}

@Override
public void update(float tpf) {
    super.update(tpf); //To change body of generated methods, choose Tools | Templates.

}

@Override
public void cleanup() {
    super.cleanup(); //To change body of generated methods, choose Tools | Templates.
    rootNode.detachAllChildren();
}

private void createColoredSphere(int zSamples, int radialSamples, float radius) {
    Sphere b = new Sphere(zSamples, radialSamples, radius);
    Geometry geom = new Geometry("Sphere", b);
    Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
    mat.setColor("Color", ColorRGBA.White);
    // mat.setBoolean("VertexColor", true); //Rubby 顶点作色
    //mat.getAdditionalRenderState().setWireframe(true); //显示三角形线框
    geom.setMaterial(mat);
    geom.setLocalTranslation(Vector3f.ZERO);


    Sphere b2 = new Sphere(zSamples, radialSamples, radius);
    //  b2.setMode(Mesh.Mode.Triangles);
    Geometry geom2 = new Geometry("Sphere2", b2);
    Material mat2 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
    ColorRGBA gray = new ColorRGBA(0.3f, 0.3f, 0.3f, 0.3f);
    mat2.setColor("Color", gray);
    mat2.getAdditionalRenderState().setWireframe(true); //显示三角形线框      
    geom2.setMaterial(mat2);
    geom2.setLocalTranslation(Vector3f.ZERO);
    rootNode.attachChild(geom2);
    rootNode.attachChild(geom);
}
 }

After run this example, you will find a red, almost “continue” line on the sphere when zoom out by mouse,
But the red line is broke when zoom in.

Meanwhile, at certain angle, the red line is continue, at some other angles, it is broke.

I haven’t tried to run it but just looking at this code: I think this partially comes down to things like floating point error and partially to the fact that the surface points are calculated in a completely different way than the sphere itself.

To be honest, I’m not sure where the hard-coded values come from in:

Or how it actually relates to spherical coordinates.

Either way, even if you were calculating the perfect sphere surface there… the mesh is only an approximation. It’s only ever actually ‘radius’ right at the vertexes, for example. So if your points are also right one ‘radius’ then they will disappear near the corners as they do in these pictures. When you are zoomed out, the size of the points is large enough that it overcomes this.

So try bumping the radius out a bit.

Alternately, turn off depth testing for the points.