Modified mesh with node.collideWith()

Hey,

I have a slight issue with the collideWith() function on a node with a mesh being modified and a ray object.

The collideWith() seems to collide with the old mesh that was there after I modify it.

For instance I have a few triangles that are flat, the CollisionResult’s contact point is correct, however, when I modify that mesh and move a few vertices, it doesn’t collide with the new visual, instead it collides with those flat triangles.



Here is a simple test case that i wrote. It puts a small sphere at the contact point. Each press of the Spacebar changes the triangles using the perlin noise.



[java]

package mygame;



import com.jme3.app.SimpleApplication;

import com.jme3.collision.CollisionResults;

import com.jme3.input.KeyInput;

import com.jme3.input.controls.ActionListener;

import com.jme3.input.controls.KeyTrigger;

import com.jme3.material.Material;

import com.jme3.math.ColorRGBA;

import com.jme3.math.FastMath;

import com.jme3.math.Ray;

import com.jme3.math.Vector3f;

import com.jme3.renderer.RenderManager;

import com.jme3.scene.Geometry;

import com.jme3.scene.Mesh;

import com.jme3.scene.Node;

import com.jme3.scene.VertexBuffer;

import com.jme3.scene.shape.Sphere;

import com.jme3.terrain.noise.basis.ImprovedNoise;

import com.jme3.util.BufferUtils;

import java.nio.FloatBuffer;

import java.nio.ShortBuffer;



/**

  • test
  • @author normenhansen

    /

    public class Main extends SimpleApplication implements ActionListener {



    private static class CustomMesh extends Mesh {



    private static final float[][] sm_kaafVerts =

    {

    {0, 0, 0}, {0, 1, 0}, {1, 0, 0}, // tri 1

    {1, 0, 0}, {0, 1, 0}, {1, 1, 0}, // tri 2

    };



    private FloatBuffer m_rVB;

    private ShortBuffer m_rIB;



    private int m_iWidth;

    private int m_iHeight;





    public CustomMesh() {

    super();



    create(5, 5);

    }



    public void modify()

    {

    create(5, 5);

    }



    private void create(int iWidth, int iHeight) {

    //clean

    if(null != m_rVB)

    {

    clearBuffer(VertexBuffer.Type.Position);

    m_rVB.clear();

    m_rVB = null;

    }

    if(null != m_rIB)

    {

    clearBuffer(VertexBuffer.Type.Index);

    m_rIB.clear();

    m_rIB = null;

    }



    m_iWidth = iWidth;

    m_iHeight = iHeight;

    // size

    int iTotal = iWidth * iHeight;



    // create buffers

    //num blocks * two tris per block * three verts per tri * three floats per vert

    m_rVB = BufferUtils.createFloatBuffer(iTotal
    233);

    //num blocks * two tris per block * three verts per tri * one index per vert

    m_rIB = BufferUtils.createShortBuffer(iTotal231);

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

    // init data //

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

    int iInd = 0;

    int seed = (int)(FastMath.rand.nextFloat() * 20);



    for(int x = 0; x < iWidth; ++x)

    {

    for(int y = 0; y < iHeight; ++y)

    {

    for(int iVert = 0; iVert < 6; ++iVert)

    {

    float f = 0.0f;//ImprovedNoise.noise(seed+x
    0.05f, seed+(yiVert)0.05f, 0) * 10.0f;

    float fX = x;

    float fY = y;



    f = ImprovedNoise.noise(seed+(fX
    0.1f), seed+(fY
    0.1f), 0) * 2.0f;



    m_rVB .put(x + sm_kaafVerts[iVert][0]) // x

    .put(y + sm_kaafVerts[iVert][1]) // y

    .put(f);// z

    m_rIB.put((short)iInd++);

    }

    }

    }



    // flip

    m_rVB.flip();

    m_rIB.flip();

    setBuffer(VertexBuffer.Type.Position, 3, m_rVB);

    setBuffer(VertexBuffer.Type.Index, 1, m_rIB);



    setMode(Mode.Triangles);

    setDynamic();



    updateCounts();

    updateBound();

    }

    }



    public Node m_rPickNode;

    public Geometry m_rDbgSphere;



    public Geometry m_rCustomMesh_Geo;

    public CustomMesh m_rCustomMesh;



    public static void main(String[] args) {

    Main app = new Main();

    app.setShowSettings(false);

    app.start();

    }



    @Override

    public void simpleInitApp() {

    cam.setLocation(new Vector3f(0, 0, -10));

    cam.lookAt(Vector3f.ZERO, Vector3f.UNIT_Y);

    flyCam.setMoveSpeed(15.0f);



    m_rPickNode = new Node(“NodeBeingPicked”);



    // custom mesh - changes

    m_rCustomMesh = new CustomMesh();

    m_rCustomMesh_Geo = new Geometry(“CustomMesh”, m_rCustomMesh);

    Material rMat = new Material(assetManager, “Common/MatDefs/Misc/Unshaded.j3md”);

    rMat.setColor(“Color”, ColorRGBA.Red);

    m_rCustomMesh_Geo.setMaterial(rMat);

    m_rPickNode.attachChild(m_rCustomMesh_Geo);

    rootNode.attachChild(m_rPickNode);



    // Debug sphere - used to show the picked point

    m_rDbgSphere = new Geometry(“DbgSphere”, new Sphere(5, 5, 0.25f));

    Material rMat2 = new Material(assetManager, “Common/MatDefs/Misc/Unshaded.j3md”);

    rMat2.setColor(“Color”, ColorRGBA.Green);

    rMat2.getAdditionalRenderState().setWireframe(true);

    m_rDbgSphere.setMaterial(rMat2);

    rootNode.attachChild(m_rDbgSphere);



    initInput();



    }



    @Override

    public void simpleUpdate(float tpf) {

    Ray rRay = new Ray(cam.getLocation(), cam.getDirection());

    CollisionResults rResults = new CollisionResults();



    m_rPickNode.collideWith(rRay, rResults);



    if(0 != rResults.size())

    {

    m_rDbgSphere.setLocalTranslation(rResults.getClosestCollision().getContactPoint());

    }

    }



    @Override

    public void simpleRender(RenderManager rm) {

    //TODO: add render code

    }



    private void initInput() {

    inputManager.addMapping(“mod”, new KeyTrigger(KeyInput.KEY_SPACE));

    inputManager.addListener(this, “mod”);

    }



    public void onAction(String name, boolean isPressed, float tpf) {

    if(name.equals(“mod”) && isPressed)

    {

    ((CustomMesh)m_rCustomMesh).modify();

    m_rCustomMesh_Geo.updateModelBound();

    }

    }

    }



    [/java]



    I’m most likely forgetting to do something as usual :slight_smile:



    Thanks to anyone who can help me out.

You have to call mesh.updateCollisionData() (or smething like that) after modifying the mesh.

Ahh I see, the collideWith calls createCollisionData() only if the collision hasn’t been created, so I needed to call the createCollisionData() after I had modified the mesh.



If you remove the updateModelBound() call on the geometry after modifying it doesn’t work again. So that has to stay, however, it’s giving me a warning and saying I shouldn’t need to call this, is there a better way of doing this? or is it one of those things you just have to do?



@normen Thanks for the help

Its ok to call this for now, it will probably set the flag fro refresh by itself at some point though.