2017-12-14 103 views
6

यह हनुक्का और मैं एक कताई शीर्ष (dreidel) चेतन करने के लिए कोशिश कर रहा हूँ:कताई शीर्ष को एनिमेट कैसे करें?

spinning top

मैं इसे अपनी ही धुरी पर स्पिन मिल सकती है। यहाँ मेरी कोड है:

import static javafx.scene.paint.Color.*; 

import javafx.animation.KeyFrame; 
import javafx.animation.KeyValue; 
import javafx.animation.Timeline; 
import javafx.application.Application; 
import javafx.beans.property.DoubleProperty; 
import javafx.beans.property.SimpleDoubleProperty; 
import javafx.geometry.Point3D; 
import javafx.scene.Camera; 
import javafx.scene.Group; 
import javafx.scene.PerspectiveCamera; 
import javafx.scene.Scene; 
import javafx.scene.SceneAntialiasing; 
import javafx.scene.paint.PhongMaterial; 
import javafx.scene.shape.Box; 
import javafx.scene.shape.Cylinder; 
import javafx.scene.shape.Sphere; 
import javafx.scene.transform.Rotate; 
import javafx.scene.transform.Translate; 
import javafx.stage.Stage; 
import javafx.util.Duration; 

public class DreidelAnim extends Application { 

    private double bodyBase = 30; 
    private double bodyHeight = bodyBase * 3/2; 
    private double baseRadius = bodyBase/2; 

    @Override 
    public void start(Stage stage) throws Exception { 
     DoubleProperty spinAngle = new SimpleDoubleProperty(); 
     Rotate spin = new Rotate(0, Rotate.Z_AXIS); 
     spin.angleProperty().bind(spinAngle); 

     Timeline spinAnim = new Timeline(new KeyFrame(Duration.seconds(2), new KeyValue(spinAngle, 360))); 
     spinAnim.setCycleCount(Timeline.INDEFINITE); 
     spinAnim.play(); 

     Group dreidel = createDreidel(); 
     Translate zTrans = new Translate(0, 0, -(bodyHeight/2 + baseRadius)); 
     dreidel.getTransforms().addAll(spin, zTrans); 

     Scene scene = new Scene(dreidel, 200, 200, true, SceneAntialiasing.BALANCED); 
     scene.setFill(SKYBLUE); 
     scene.setCamera(createCamera()); 

     stage.setScene(scene); 
     stage.show(); 
    } 

    private Group createDreidel() { 
     double handleHeight = bodyBase * 3/4; 
     Cylinder handle = new Cylinder(bodyBase/6, handleHeight); 
     handle.setTranslateZ(-(bodyHeight + handleHeight)/2); 
     handle.setRotationAxis(Rotate.X_AXIS); 
     handle.setRotate(90); 
     handle.setMaterial(new PhongMaterial(RED)); 

     Box body = new Box(bodyBase, bodyBase, bodyHeight); 
     body.setMaterial(new PhongMaterial(BLUE)); 

     Sphere base = new Sphere(baseRadius); 
     base.setTranslateZ(bodyHeight/2); 
     base.setMaterial(new PhongMaterial(GREEN)); 

     return new Group(handle, body, base); 
    } 

    private Camera createCamera() { 
     PerspectiveCamera camera = new PerspectiveCamera(true); 
     camera.setFarClip(1000); 

     int xy = 150; 
     Translate trans = new Translate(-xy, xy, -120); 
     Rotate rotXY = new Rotate(70, new Point3D(1, 1, 0)); 
     Rotate rotZ = new Rotate(45, new Point3D(0, 0, 1)); 
     camera.getTransforms().addAll(trans, rotXY, rotZ); 

     return camera; 
    } 

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

मैं एक साधारण मॉडल बनाया है, इसकी धुरी के चारों ओर यह कताई, और यह अनुवाद ताकि उसके टिप (0, 0, 0) पर है।

enter image description here

मैं कैसे शीर्ष जहां यह भी एक घूर्णन अक्ष पर स्पिन है पर तस्वीर के लिए कुछ इसी तरह प्राप्त कर सकते हैं: यहाँ परिणाम है?

उत्तर

8

धुरी के घूर्णन के आसपास ऑब्जेक्ट स्पिन को Precession कहा जाता है। कताई शीर्ष गति के लिए 2 रोटेशन की आवश्यकता होती है:

  1. अपने आंतरिक धुरी (लाल संभाल के समानांतर) के आसपास ऑब्जेक्ट का घूर्णन।
  2. इस मामले में एक स्थिर धुरी (z के आस-पास आंतरिक धुरी में से एक घूर्णन)।

इसके चेहरे पर, आपको 2 Animation उदाहरणों की आवश्यकता होगी। हालांकि, दोनों घूर्णन वास्तव में वही हैं। दोनों के लिए पिवट बिंदु (0, 0, 0) (zTrans के बाद) है और वे z धुरी के आसपास दोनों हैं, उनमें से केवल एक कोण पर झुका हुआ है।

यहाँ संशोधित कोड है:

import static javafx.scene.paint.Color.*; 

import javafx.animation.KeyFrame; 
import javafx.animation.KeyValue; 
import javafx.animation.Timeline; 
import javafx.application.Application; 
import javafx.beans.property.DoubleProperty; 
import javafx.beans.property.SimpleDoubleProperty; 
import javafx.geometry.Point3D; 
import javafx.scene.Camera; 
import javafx.scene.Group; 
import javafx.scene.PerspectiveCamera; 
import javafx.scene.Scene; 
import javafx.scene.SceneAntialiasing; 
import javafx.scene.paint.PhongMaterial; 
import javafx.scene.shape.Box; 
import javafx.scene.shape.Cylinder; 
import javafx.scene.shape.Sphere; 
import javafx.scene.transform.Rotate; 
import javafx.scene.transform.Translate; 
import javafx.stage.Stage; 
import javafx.util.Duration; 

public class FinalDreidelSpin extends Application { 

    private double bodyBase = 30; 
    private double bodyHeight = bodyBase * 3/2; 
    private double baseRadius = bodyBase/2; 

    @Override 
    public void start(Stage stage) throws Exception { 
     double tiltAngle = 40; 
     DoubleProperty spinAngle = new SimpleDoubleProperty(); 

     Rotate spin = new Rotate(0, Rotate.Z_AXIS); 
     Rotate tilt = new Rotate(tiltAngle, Rotate.X_AXIS); 

     spin.angleProperty().bind(spinAngle); 

     Timeline spinAnim = new Timeline(); 
     spinAnim.getKeyFrames().add(new KeyFrame(Duration.seconds(2), new KeyValue(spinAngle, 360))); 
     spinAnim.setCycleCount(Timeline.INDEFINITE); 
     spinAnim.play(); 

     Group dreidel = createDreidel(); 
     Translate zTrans = new Translate(0, 0, -(bodyHeight/2 + baseRadius)); 
     dreidel.getTransforms().addAll(spin, tilt, spin, zTrans); 

     Scene scene = new Scene(new Group(dreidel, createAxes()), 200, 200, true, SceneAntialiasing.BALANCED); 
     scene.setFill(SKYBLUE); 
     scene.setCamera(createCamera()); 

     stage.setScene(scene); 
     stage.show(); 
    } 

    private Group createDreidel() { 
     double handleHeight = bodyBase * 3/4; 
     Cylinder handle = new Cylinder(bodyBase/6, handleHeight); 
     handle.setTranslateZ(-(bodyHeight + handleHeight)/2); 
     handle.setRotationAxis(Rotate.X_AXIS); 
     handle.setRotate(90); 
     handle.setMaterial(new PhongMaterial(RED)); 

     Box body = new Box(bodyBase, bodyBase, bodyHeight); 
     body.setMaterial(new PhongMaterial(BLUE)); 

     Sphere base = new Sphere(baseRadius); 
     base.setTranslateZ(bodyHeight/2); 
     base.setMaterial(new PhongMaterial(GREEN)); 

     return new Group(handle, body, base); 
    } 

    private Camera createCamera() { 
     PerspectiveCamera camera = new PerspectiveCamera(true); 
     camera.setFarClip(1000); 

     int xy = 150; 
     Translate trans = new Translate(-xy, xy, -100); 
     Rotate rotXY = new Rotate(70, new Point3D(1, 1, 0)); 
     Rotate rotZ = new Rotate(45, new Point3D(0, 0, 1)); 
     camera.getTransforms().addAll(trans, rotXY, rotZ); 

     return camera; 
    } 

    private Group createAxes() { 
     int axisWidth = 1; 
     int axisLength = 400; 

     Cylinder xAxis = new Cylinder(axisWidth, axisLength); 
     xAxis.setMaterial(new PhongMaterial(CYAN)); 

     Cylinder yAxis = new Cylinder(axisWidth, axisLength); 
     yAxis.setRotationAxis(Rotate.Z_AXIS); 
     yAxis.setRotate(90); 
     yAxis.setMaterial(new PhongMaterial(MAGENTA)); 

     Cylinder zAxis = new Cylinder(axisWidth, axisLength); 
     zAxis.setRotationAxis(Rotate.X_AXIS); 
     zAxis.setRotate(90); 
     zAxis.setMaterial(new PhongMaterial(YELLOW)); 

     return new Group(xAxis, yAxis, zAxis); 
    } 

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

कहाँ मैं सुविधा को देखने के लिए कुल्हाड़ियों अभ्यावेदन गयी। ध्यान दें कि getTransforms() सूची में इसकी वस्तुओं को अद्वितीय होने की आवश्यकता नहीं है (getChildren() के विपरीत), जो हमें एक ही एनीमेशन का पुन: उपयोग करने की अनुमति देता है। जैसा कि नीचे उल्लेख किया गया है एनिमेशन के क्रम भी महत्वपूर्ण है।

झुकाव एक्स या y धुरी के चारों ओर एक सरल रोटेशन है।
हम tilt और फिर spin, getTransforms().addAll(tilt, spin, zTrans), हम आंतरिक रोटेशन (1 ऊपर सूचीबद्ध) मिल चाहते हैं, तो केवल झुका:

spin

हम spin और फिर tilt, getTransforms().addAll(spin, tilt, zTrans), हम पुरस्सरण मिलेगा तो (ऊपर 2 सूचीबद्ध):

precession

2 के संयोजन पूरा कोड में के रूप में वांछित परिणाम देना होगा:

full

3

यह एक और संभावित जवाब, बहुत बहुत @ user1803551 दृष्टिकोण में आधारित है, लेकिन एक 3 डी जाल है कि एक बनावट छवि का उपयोग कर सकते हैं का उपयोग कर, और एक अलग पुरस्सरण की अवधि है।इस छवि को

dreidel

आदेश में एक बनावट लागू करने के लिए, मैं net अवधारणा dreidel के शरीर के लिए इस्तेमाल करेंगे, और:

यह है कि यह कैसे लगता है कि है

जो इस image पर आधारित है।

अंत में मैं हैंडल के लिए नियमित सिलेंडर जोड़ दूंगा।

मैं शरीर के लिए TriangleMesh बनाने के तरीके के विवरण में नहीं जाऊंगा, लेकिन हम 9 शिखर (3 डी निर्देशांक), 16 बनावट निर्देशांक (2 डी), और 14 त्रिकोण चेहरों को कशेरुक सूचकांक और बनावट सूचकांक सहित परिभाषित करते हैं। । घन को इसके पक्ष width द्वारा परिभाषित किया गया है, और पिरामिड इसके height द्वारा परिभाषित किया गया है। शुद्ध आयाम L = 4 * width, H = 2 * width + height हैं। 2 - -

उदाहरण के लिए, चेहरा 0 कोने 0 है 1, और बनावट सूचकांक 8 - 3 - 7, जहां शिखर 0 निर्देशांक {width/2, width/2, width/2}, और बनावट सूचकांक 8 निर्देशांक {width, 2 * width}, जो [0, 1] के बीच सामान्यीकृत हैं है : {width/L, 2 * width/H}

इस मामले में, और नमूना के लिए, मान hardcoded रहे हैं:

float width = 375f; 
float height = 351f; 

इस 3D आकार वर्ग है:

class DreidelMesh extends Group { 

    float width = 375f; 
    float height = 351f; 

    public DreidelMesh(){ 
     MeshView bodyMesh = new MeshView(createBodyMesh()); 
     PhongMaterial material = new PhongMaterial(); 
     material.setDiffuseMap(new Image(getClass().getResourceAsStream("3dreidel3d.png"))); 
     bodyMesh.setMaterial(material); 

     Cylinder handle = new Cylinder(45, 260); 
     handle.setTranslateY(-(handle.getHeight() + width)/2); 
     material = new PhongMaterial(Color.web("#daaf6d")); 
     handle.setMaterial(material); 

     getTransforms().add(new Rotate(90, Rotate.X_AXIS)); 
     getChildren().addAll(bodyMesh, handle); 
    } 

    private TriangleMesh createBodyMesh() { 
     TriangleMesh m = new TriangleMesh(); 

     float L = 4f * width; 
     float H = 2f * width + height; 
     float w2 = width/2f; 

     // POINTS 
     m.getPoints().addAll(
      w2, w2, w2, 
      w2, w2, -w2, 
      w2, -w2, w2, 
      w2, -w2, -w2, 
      -w2, w2, w2, 
      -w2, w2, -w2, 
      -w2, -w2, w2, 
      -w2, -w2, -w2, 
      0f, w2 + height, 0f 
     ); 

     // TEXTURES 
     m.getTexCoords().addAll(
      width/L, 0f, 
      2f * width/ L, 0f, 
      0f, width/H, 
      width/L, width/H, 
      2f * width/ L, width/H, 
      3f * width/ L, width/H, 
      1f, width/H, 
      0f, 2f * width/H, 
      width/L, 2f * width/H, 
      2f * width/ L, 2f * width/H, 
      3f * width/ L, 2f * width/H, 
      1f, 2f * width/H, 
      width/2f/L, 1f, 
      3f * width/2f/L, 1f, 
      5f * width/2f/L, 1f, 
      7f * width/2f/L, 1f 
     ); 

     // FACES 
     m.getFaces().addAll(
      0, 8, 2, 3, 1, 7,   
      2, 3, 3, 2, 1, 7,   
      4, 9, 5, 10, 6, 4,   
      6, 4, 5, 10, 7, 5,   
      0, 8, 1, 7, 8, 12,   
      4, 9, 0, 8, 8, 13,   
      5, 10, 4, 9, 8, 14,   
      1, 11, 5, 10, 8, 15,    
      2, 3, 6, 4, 3, 0,    
      3, 0, 6, 4, 7, 1,    
      0, 8, 4, 9, 2, 3,   
      2, 3, 4, 9, 6, 4,   
      1, 11, 3, 6, 5, 10,   
      5, 10, 3, 6, 7, 5 
     ); 
     return m; 
    } 
} 

dreidel

अंत में, इस आकार दृश्य में जोड़ा जाता है, और मैं दो एनिमेशन (एक के बजाय), स्पिन के लिए, और एक पुरस्सरण के लिए धीमी उपलब्ध कराएँगे:

@Override 
public void start(Stage stage) { 
    double tiltAngle = 15; 
    DoubleProperty spinAngle = new SimpleDoubleProperty(); 
    DoubleProperty precessionAngle = new SimpleDoubleProperty(); 

    Rotate spin = new Rotate(0, Rotate.Z_AXIS); 
    Rotate precession = new Rotate(0, Rotate.Z_AXIS); 
    Rotate tilt = new Rotate(tiltAngle, Rotate.X_AXIS); 

    spin.angleProperty().bind(spinAngle); 
    precession.angleProperty().bind(precessionAngle); 

    Timeline spinAnim = new Timeline(); 
    spinAnim.getKeyFrames().add(new KeyFrame(Duration.seconds(1.5), new KeyValue(spinAngle, 360))); 
    spinAnim.setCycleCount(Timeline.INDEFINITE); 
    spinAnim.play(); 

    Timeline precessionAnim = new Timeline(); 
    precessionAnim.getKeyFrames().add(new KeyFrame(Duration.seconds(4), new KeyValue(precessionAngle, 360))); 
    precessionAnim.setCycleCount(Timeline.INDEFINITE); 
    precessionAnim.play(); 

    Group dreidel = new Group(new DreidelMesh()); 
    Translate zTrans = new Translate(0, 0, - dreidel.getBoundsInLocal().getMaxZ()); 
    dreidel.getTransforms().addAll(precession, tilt, spin, zTrans); 

    Scene scene = new Scene(new Group(dreidel), 300, 300, true, SceneAntialiasing.BALANCED); 
    scene.setFill(SKYBLUE); 
    scene.setCamera(createCamera()); 

    stage.setScene(scene); 
    stage.setTitle("JavaFX 3D - Dreidel"); 
    stage.show(); 
} 

आवेदन एनीमेशन दिखाएगा चल रहा है ऊपर प्रदर्शित

+0

हाँ, मुझे लगता है कि आपने विस्तारित प्रश्न का उत्तर दिया "एक * अच्छी लग रही * कताई शीर्ष को एनिमेट कैसे करें?" :) मेरा इरादा गणित/एनिमेशन पर ध्यान केंद्रित करना था। DIY के साथ बहुत अच्छा अंत परिणाम! – user1803551

+0

वैसे, आपका एनिमेटेड gif 1 चक्र के बाद मेरे लिए बंद हो जाता है और छवि गायब हो जाती है। मेरे अंत में एक मुद्दा हो सकता है। – user1803551

+0

यह ठीक काम करता है (मैक/सफारी और विंडोज/फ़ायरफ़ॉक्स)। –

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