Drag & Drop in 3D problem

Hi



I’m trying to implement drag & drop functionality in 3D. I’m using the technique that places a 2D quad/plane parallel to the viewport in which the object can be moved (or dragged) freely. This works like a charm, but everything becomes confusing when the objects are grouped and/or rotated.

I have a sphere object in my scene that can be dragged. The quad where the sphere can be dragged is also visible. These two objects are added to a container node which is then in turn added to the rootNode. The problem arises when I want to rotate the container node. The rotate call in the update method makes the container rotate, if I then drag the sphere the coordinates stop making sense to me.



I need this functionality to work when rotating. I tried some stuff with regrouping and worldToLocal coordinates, but nothing worked lik I excpected it to. In the end I need the billboardcontrol to be attached to the quad so it is always facing the camera



Here’s the code:



[java]

import com.jme3.collision.CollisionResult;

import com.jme3.collision.CollisionResults;

import com.jme3.input.controls.ActionListener;

import com.jme3.input.controls.AnalogListener;

import com.jme3.input.controls.MouseButtonTrigger;

import com.jme3.light.DirectionalLight;

import com.jme3.material.Material;

import com.jme3.material.RenderState.BlendMode;

import com.jme3.math.ColorRGBA;

import com.jme3.math.Quaternion;

import com.jme3.math.Ray;

import com.jme3.math.Vector2f;

import com.jme3.math.Vector3f;

import com.jme3.renderer.queue.RenderQueue.Bucket;

import com.jme3.scene.Geometry;

import com.jme3.scene.Node;

import com.jme3.scene.control.BillboardControl;

import com.jme3.scene.shape.Quad;

import com.jme3.scene.shape.Sphere;

import com.jme3.system.AppSettings;



public class QuadPickTest extends GraphApplication implements ActionListener{



private Node container;

private Node quadNode;

private Node sphereNode;

private boolean dragging = false;



public static void main(String[] args) {

QuadPickTest app = new QuadPickTest();



AppSettings settings = new AppSettings(true);

settings.setResolution(1440, 900);



app.setSettings(settings);

app.setShowSettings(false);

app.start();

}



@Override

public void simpleInitApp() {

System.out.println(“wadde”);

cam.setLocation(new Vector3f(0, 33, 105));

cam.setDirection(new Vector3f(0, -0.27f, -0.962f));

cam.setRotation(new Quaternion(0, 1, -0.13629319f, 0));



viewPort.setBackgroundColor(new ColorRGBA(50 / 255f, 50 / 255f, 50 / 255f, 1.0f));



Quad quad = new Quad(70,50);

Geometry parallelQuad = new Geometry(“parallelQuad”, quad);



// parallelQuad.rotate(0,0.5f,0);



parallelQuad.setLocalTranslation(new Vector3f(-quad.getWidth()/2,-quad.getHeight()/2,0));



Material mat = new Material(assetManager, “Common/MatDefs/Light/Lighting.j3md”);

mat.setBoolean(“m_UseMaterialColors”, true);

mat.setFloat(“m_Shininess”, 10);

mat.setColor(“m_Ambient”, new ColorRGBA(0.0f,0.0f,0.7f,0.5f));

mat.setColor(“m_Diffuse”, new ColorRGBA(0.6f, 0.6f, 0.6f, 0.3f));

mat.setColor(“m_Specular”, ColorRGBA.White);



mat.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);

parallelQuad.setMaterial(mat);

quadNode = new Node();

BillboardControl bc = new BillboardControl();

quadNode.addControl(bc);

quadNode.attachChild(parallelQuad);



DirectionalLight sun = new DirectionalLight();

sun.setDirection(new Vector3f(-1,-1,-1).normalizeLocal());

sun.setColor(ColorRGBA.White);

rootNode.addLight(sun);



Sphere sphere = new Sphere(10,10,1);

Geometry geom = new Geometry(“Registration Point”, sphere);



mat.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);

geom.setMaterial(mat);



sphereNode = new Node();

sphereNode.attachChild(geom);

sphereNode.setQueueBucket(Bucket.Transparent);

sphereNode.setLocalTranslation(new Vector3f(0.1f,0,0));



container = new Node();

// Node sphereContainer = new Node();

// sphereContainer.attachChild(sphereNode);

container.attachChild(sphereNode);

container.attachChild(quadNode);

rootNode.attachChild(container);



//container.rotate(0, 0.5f, 0);



initKeys();

}



private void initKeys(){

String[] mappings = new String[]{ “Drag” };

// Add left mouse button for dragging

inputManager.addMapping(“Drag”, new MouseButtonTrigger(0));

inputManager.addListener(this, mappings);

}



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

dragging = keyDown;

}



@Override

public void update(){

super.update();



container.rotate(0,0.0005f,0);



if (dragging){

Vector2f currMouseCoords = new Vector2f(inputManager.getCursorPosition());

CollisionResults results = new CollisionResults();

Ray ray = new Ray(cam.getWorldCoordinates(currMouseCoords, 0),

cam.getWorldCoordinates(currMouseCoords, 1).subtractLocal(

cam.getWorldCoordinates(currMouseCoords, 0)).normalizeLocal());



quadNode.collideWith(ray, results);



if (results.size() > 0) {

CollisionResult closest = results.getClosestCollision();



//1.

// Vector3f store = Vector3f.ZERO;

// sphereNode.worldToLocal(closest.getContactPoint(), store);

// sphereNode.setLocalTranslation(store);



//2.

sphereNode.setLocalTranslation(closest.getContactPoint());



// System.out.println("contact: " + closest. getContactPoint());

// System.out.println("store: " + store);

}

}

}

}

[/java]

1 Like