2015-02-25 13 views
6

जैसा कि मैं जावाएफएक्स में अपना पहला 3 डी गेम बना रहा था - जहां आप माउस का उपयोग करके भागों से जहाजों को इकट्ठा करने में सक्षम होंगे। यह एक समस्या प्रस्तुत करता है क्योंकि जावाएक्स में कोई देशी मेटोड नहीं है जो दृश्यमान कैमरे स्क्रीन 2 डी को दृश्यमान 3 डी स्पेस में परिवर्तित करने के लिए काम करता है।जावाएफएक्स वर्चुअल प्लेन पर माउस के साथ 3 डी ऑब्जेक्ट्स मूविंग

यहां एक प्रतिनिधित्व है जो मैं स्वीकार करने की कोशिश कर रहा हूं। माउस द्वारा स्थानांतरित एक ब्लॉक को एक काल्पनिक विमान पर जाना चाहिए जो हमेशा कैमरे के संबंध में 90 घूर्णन करता है: Representation मैंने बिना किसी सफलता के त्रिकोणमिति के साथ समस्या को हल करने का प्रयास किया है। मैंने एक कोड स्निपेट संलग्न नहीं किया है क्योंकि मैं एक अधिक सामान्य गणितीय समाधान की तलाश में हूं, लेकिन अनुरोध किए जाने पर इसे प्रदान करेगा।

सभी मदद की सराहना की जाएगी!

वांछित परिणाम: Before

After

+0

यह प्रकाशन का हिस्सा नहीं है आईसी एपीआई, लेकिन आप कैमराहेल्पर का उपयोग करने का प्रयास कर सकते हैं .. में 3 विधियां हैं, जिन्हें आप चाहते हैं ** है।pickProjectionPlane (कैमरा, एक्स, वाई) – jdub1581

उत्तर

7

के रूप में @ jdub1581 बताते हैं, Camera दृश्य पर अपने 3 डी objets के साथ माउस आंदोलन को बाध्य करने के लिए महत्वपूर्ण है।

स्टार्टर के लिए, हम सार्वजनिक एपीआई PickResult के बारे में जानते हैं, जो हमें कैमरे की स्थिति से किए गए कुछ रे ट्रेसिंग तकनीकों के आधार पर माउस के साथ 3 डी ऑब्जेक्ट का चयन करने की अनुमति देता है।

लेकिन एक बार हमारे पास एक वस्तु है, इसे स्थानांतरित करना एक अलग समस्या है।

ओपनजेएफएक्स भंडार पर खिलौने परियोजना में Camera3D कक्षा को इस समस्या के समाधान (3 डी ऑब्जेक्ट्स को 3 डी स्पेस में ले जाने) के लिए एक समाधान की तलाश में है।

/* 
* returns 3D direction from the Camera position to the mouse 
* in the Scene space 
*/ 

public Vec3d unProjectDirection(double sceneX, double sceneY, 
           double sWidth, double sHeight) { 
} 

जब से तुम गणितीय स्पष्टीकरण के लिए कहा, इस विधि त्रिकोणमिति आप देख रहे थे उपयोग करता है:

यह एक promissing विधि unProjectDirection कहा जाता है। यह आपको एक 3D सदिश (एक्स, वाई) माउस निर्देशांक के आधार पर दे देंगे, एक निजी Vec3d वर्ग (है कि हम सार्वजनिक Point3D से बदल सकते हैं) का उपयोग: में एक सामान्यीकृत वेक्टर पाने के लिए

double tanOfHalfFOV = Math.tan(Math.toRadians(camera.getFieldOfView()) * 0.5f); 
Vec3d vMouse = new Vec3d(tanOfHalfFOV*(2*sceneX/sWidth-1), tanOfHalfFOV*(2*sceneY/sWidth-sHeight/sWidth), 1); 

कुछ आगे परिवर्तनों लागू होते हैं दृश्य निर्देशांक।

अगला चरण इस सामान्यीकृत वेक्टर को असली निर्देशांक में बदल देगा, केवल कैमरे से ऑब्जेक्ट से दूरी का उपयोग करके, नतीजे पर दिए गए ऑब्जेक्ट पर, ऑब्जेक्ट स्थिति को बदल देगा।

मूल रूप से, इस कोड स्निपेट को एक वस्तु खींच की पूरी प्रक्रिया की रूपरेखा:

scene.setOnMousePressed((MouseEvent me) -> { 
     vecIni = unProjectDirection(me.getSceneX(), me.getSceneY(), 
        scene.getWidth(),scene.getHeight()); 
     distance=me.getPickResult().getIntersectedDistance();   
    }); 

    scene.setOnMouseDragged((MouseEvent me) -> { 
     vecPos = unProjectDirection(mousePosX, mousePosY, 
       scene.getWidth(),scene.getHeight()); 
     Point3D p=vecPos.subtract(vecIni).multiply(distance); 
     node.getTransforms().add(new Translate(p.getX(),p.getY(),p.getZ())); 
     vecIni=vecPos; 
     distance=me.getPickResult().getIntersectedDistance(); 
    }); 

और यह एक पूर्ण काम कर बुनियादी उदाहरण है:

public class Drag3DObject extends Application { 

    private final Group root = new Group(); 
    private PerspectiveCamera camera; 
    private final double sceneWidth = 800; 
    private final double sceneHeight = 600; 

    private double mousePosX; 
    private double mousePosY; 
    private double mouseOldX; 
    private double mouseOldY; 
    private final Rotate rotateX = new Rotate(-20, Rotate.X_AXIS); 
    private final Rotate rotateY = new Rotate(-20, Rotate.Y_AXIS); 

    private volatile boolean isPicking=false; 
    private Point3D vecIni, vecPos; 
    private double distance; 
    private Sphere s; 

    @Override 
    public void start(Stage stage) { 
     Box floor = new Box(1500, 10, 1500); 
     floor.setMaterial(new PhongMaterial(Color.GRAY)); 
     floor.setTranslateY(150); 
     root.getChildren().add(floor); 

     Sphere sphere = new Sphere(150); 
     sphere.setMaterial(new PhongMaterial(Color.RED)); 
     sphere.setTranslateY(-5); 
     root.getChildren().add(sphere); 

     Scene scene = new Scene(root, sceneWidth, sceneHeight, true, SceneAntialiasing.BALANCED); 
     scene.setFill(Color.web("3d3d3d")); 

     camera = new PerspectiveCamera(true); 
     camera.setVerticalFieldOfView(false); 

     camera.setNearClip(0.1); 
     camera.setFarClip(100000.0); 
     camera.getTransforms().addAll (rotateX, rotateY, new Translate(0, 0, -3000)); 

     PointLight light = new PointLight(Color.GAINSBORO); 
     root.getChildren().add(light); 
     root.getChildren().add(new AmbientLight(Color.WHITE)); 
     scene.setCamera(camera); 

     scene.setOnMousePressed((MouseEvent me) -> { 
      mousePosX = me.getSceneX(); 
      mousePosY = me.getSceneY(); 
      PickResult pr = me.getPickResult(); 
      if(pr!=null && pr.getIntersectedNode() != null && pr.getIntersectedNode() instanceof Sphere){ 
       distance=pr.getIntersectedDistance(); 
       s = (Sphere) pr.getIntersectedNode(); 
       isPicking=true; 
       vecIni = unProjectDirection(mousePosX, mousePosY, scene.getWidth(),scene.getHeight()); 
      } 
     }); 
     scene.setOnMouseDragged((MouseEvent me) -> { 
      mousePosX = me.getSceneX(); 
      mousePosY = me.getSceneY(); 
      if(isPicking){ 
       vecPos = unProjectDirection(mousePosX, mousePosY, scene.getWidth(),scene.getHeight()); 
       Point3D p=vecPos.subtract(vecIni).multiply(distance); 
       s.getTransforms().add(new Translate(p.getX(),p.getY(),p.getZ())); 
       vecIni=vecPos; 
       PickResult pr = me.getPickResult(); 
       if(pr!=null && pr.getIntersectedNode() != null && pr.getIntersectedNode()==s){ 
        distance=pr.getIntersectedDistance(); 
       } else { 
        isPicking=false; 
       } 
      } else { 
       rotateX.setAngle(rotateX.getAngle()-(mousePosY - mouseOldY)); 
       rotateY.setAngle(rotateY.getAngle()+(mousePosX - mouseOldX)); 
       mouseOldX = mousePosX; 
       mouseOldY = mousePosY; 
      } 
     }); 
     scene.setOnMouseReleased((MouseEvent me)->{ 
      if(isPicking){ 
       isPicking=false; 
      } 
     }); 

     stage.setTitle("3D Dragging"); 
     stage.setScene(scene); 
     stage.show(); 
    } 

    /* 
    From fx83dfeatures.Camera3D 
    http://hg.openjdk.java.net/openjfx/8u-dev/rt/file/5d371a34ddf1/apps/toys/FX8-3DFeatures/src/fx83dfeatures/Camera3D.java 
    */ 
    public Point3D unProjectDirection(double sceneX, double sceneY, double sWidth, double sHeight) { 
     double tanHFov = Math.tan(Math.toRadians(camera.getFieldOfView()) * 0.5f); 
     Point3D vMouse = new Point3D(tanHFov*(2*sceneX/sWidth-1), tanHFov*(2*sceneY/sWidth-sHeight/sWidth), 1); 

     Point3D result = localToSceneDirection(vMouse); 
     return result.normalize(); 
    } 

    public Point3D localToScene(Point3D pt) { 
     Point3D res = camera.localToParentTransformProperty().get().transform(pt); 
     if (camera.getParent() != null) { 
      res = camera.getParent().localToSceneTransformProperty().get().transform(res); 
     } 
     return res; 
    } 

    public Point3D localToSceneDirection(Point3D dir) { 
     Point3D res = localToScene(dir); 
     return res.subtract(localToScene(new Point3D(0, 0, 0))); 
    } 

    public static void main(String[] args) { 
     launch(args); 
    } 
} 

है कि आप उठा और खींचने की अनुमति देगा दृश्य पर क्षेत्र:

dragging 3d

+0

वाह, महान जवाब! यही वह है जिसकी तलाश में मैं हूं! : डी बहुत धन्यवाद। –

+0

धन्यवाद। निश्चित रूप से आपको अपने लिए कुछ चीजें समझनी पड़ेगी, लेकिन यह एक शुरुआती बिंदु है। यदि आपको इसकी आवश्यकता है, तो इस [repository] (https://github.com/FXyz/FXyz) पर एक नज़र डालें, हम JavaFX 3 डी के लिए उन्नत सुविधाओं पर काम कर रहे हैं। –

+0

बहुत बढ़िया, मैं इसे जांचना सुनिश्चित कर दूंगा। –

संबंधित मुद्दे