有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java使用java3D和rotpospathInterpolator制作正确的动画

我试图让一个物体在一个正方形中飞过我的场景(这是正确的),但我希望它也朝向它要去的地方

目前的问题是物体会飞,并且在飞行时会旋转(这不是自然现象)。我希望它飞到一个点,然后停下来旋转,然后飞到下一个点,然后再次旋转,依此类推

我试图通过Java3D函数实现这一点: 旋转插补器

这就是我正在做的:

Alpha alphaNave = new Alpha( -1, Alpha.INCREASING_ENABLE, 0,0,6000,0,0,0,0,0 );
TransformGroup target = new TransformGroup();
Transform3D axisOfRotPos = new Transform3D();
float[] alphas = {0.0f, 0.25f, 0.50f, 0.75f, 1.0f};
Quat4f[] quats = new Quat4f[5];
Point3f[] positions = new Point3f[5];

target.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);

    quats[0] = new Quat4f(0.0f, 1.0f, 0.0f, (float) Math.toRadians(0));
    quats[1] = new Quat4f(0.0f, 1.0f, 0.0f, (float) Math.toRadians(90));
    quats[2] = new Quat4f(0.0f, 1.0f, 0.0f, (float) Math.toRadians(180));
    quats[3] = new Quat4f(0.0f, 1.0f, 0.0f, (float) Math.toRadians(270));
    quats[4] = quats[0];

    positions[0]= new Point3f( -20.0f,  0.0f, 20.0f);
    positions[1]= new Point3f( -20.0f, 0.0f, -20.0f);
    positions[2]= new Point3f( 20.0f,  0.0f, -20.0f);
    positions[3]= new Point3f( 20.0f,  0.0f, 20.0f);
    positions[4]= positions[0];

RotPosPathInterpolator rotPosPath = new RotPosPathInterpolator(
            alphaNave, target, axisOfRotPos, alphas, quats, positions);

共 (1) 个答案

  1. # 1 楼答案

    首先是简短的旁注:创建四元数时,最后一个分量不是角度。为了创建一个四元数来描述围绕某个轴、围绕某个角度的旋转,最简单的方法是遍历AxisAngle4f

    AxisAngle4f a = new AxisAngle4f(0.0f, 1.0f, 0.0f, angleInRadians);
    Quat4f q = new Quat4f();
    q.set(a);
    

    (不幸的是,没有方便的构造函数来实现这一点。我建议用返回适当四元数的实用方法来包装这三行)


    关于实际问题:如果我正确理解了你,那么期望的行为是:

    Animation

    (这是从我在下面添加的MCVE创建的)

    如果只希望有一个移动(无旋转),则必须在插值路径中插入两个点,其中只有位置更改,但旋转保持不变。类似地,如果只需要旋转,则必须创建两个点,其中只有旋转发生变化,但位置保持不变。当然,您必须始终相应地调整alpha

    在本例中,您的路径将由9个点组成。手动添加这些点,并计算所需的alpha值是一件麻烦事。我建议为此创建一个小型实用程序类。下面的MCVE允许将点(每个点由位置和角度组成)添加到InterpolatorData类,该类随后为插值器提供数据

    import java.awt.GraphicsConfiguration;
    import java.util.ArrayList;
    import java.util.List;
    
    import javax.media.j3d.Alpha;
    import javax.media.j3d.BoundingSphere;
    import javax.media.j3d.BranchGroup;
    import javax.media.j3d.Canvas3D;
    import javax.media.j3d.RotPosPathInterpolator;
    import javax.media.j3d.Transform3D;
    import javax.media.j3d.TransformGroup;
    import javax.swing.JFrame;
    import javax.swing.SwingUtilities;
    import javax.vecmath.AxisAngle4f;
    import javax.vecmath.Point3d;
    import javax.vecmath.Point3f;
    import javax.vecmath.Quat4f;
    import javax.vecmath.Vector3d;
    
    import com.sun.j3d.utils.geometry.ColorCube;
    import com.sun.j3d.utils.universe.SimpleUniverse;
    
    public class RotPosPathInterpolatorTest
    {
        public static void main(String[] args) 
        {
            System.setProperty("sun.awt.noerasebackground", "true");
    
            SwingUtilities.invokeLater(new Runnable()
            {
                @Override
                public void run()
                {
                    createAndShowGUI();
                }
            });
        }
    
        private static void createAndShowGUI()
        {
            JFrame frame = new JFrame();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);;
    
            GraphicsConfiguration config = 
                SimpleUniverse.getPreferredConfiguration();
            Canvas3D canvas = new Canvas3D(config);
            frame.getContentPane().add(canvas);
            SimpleUniverse simpleUniverse = new SimpleUniverse(canvas);
    
            BranchGroup rootBranchGroup = new BranchGroup();
            createContents(rootBranchGroup);
    
            simpleUniverse.addBranchGraph(rootBranchGroup);
    
            Transform3D t0 = new Transform3D();
            t0.rotX(Math.toRadians(-45));
            Transform3D t1 = new Transform3D();
            t1.setTranslation(new Vector3d(0,0,10));
            t0.mul(t1);
            simpleUniverse.
                getViewingPlatform().
                getViewPlatformTransform().
                setTransform(t0);
    
            frame.setSize(400, 400);
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        }
    
        private static class InterpolatorData
        {
            private final List<Point3f> positions = new ArrayList<Point3f>();
            private final List<Quat4f> orientations = new ArrayList<Quat4f>();
    
            void add(Point3f p, float angleDeg)
            {
                positions.add(p);
    
                AxisAngle4f a = new AxisAngle4f(
                    0.0f, 1.0f, 0.0f, (float) Math.toRadians(angleDeg));
                Quat4f q = new Quat4f();
                q.set(a);
                orientations.add(q);
            }
    
            Point3f[] getPositions()
            {
                return positions.toArray(new Point3f[0]);
            }
    
            Quat4f[] getOrientations()
            {
                return orientations.toArray(new Quat4f[0]);
            }
    
            float[] getAlphas()
            {
                float alphas[] = new float[positions.size()];
                float delta = 1.0f / (alphas.length - 1);
                for (int i=0; i<alphas.length; i++)
                {
                    alphas[i] = i * delta;
                }
                return alphas;
            }
        }
    
        private static void createContents(BranchGroup rootBranchGroup)
        {
            Alpha alpha = new Alpha(-1, Alpha.INCREASING_ENABLE, 
                0, 0, 6000, 0, 0, 0, 0, 0);
            TransformGroup target = new TransformGroup();
            target.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
            Transform3D axisOfTransform = new Transform3D();
    
            InterpolatorData i = new InterpolatorData();
            i.add(new Point3f(-2.0f, 0.0f,  2.0f),   0.0f);
            i.add(new Point3f(-2.0f, 0.0f, -2.0f),   0.0f);
            i.add(new Point3f(-2.0f, 0.0f, -2.0f),  90.0f);
            i.add(new Point3f( 2.0f, 0.0f, -2.0f),  90.0f);
            i.add(new Point3f( 2.0f, 0.0f, -2.0f), 180.0f);
            i.add(new Point3f( 2.0f, 0.0f,  2.0f), 180.0f);
            i.add(new Point3f( 2.0f, 0.0f,  2.0f), 270.0f);
            i.add(new Point3f(-2.0f, 0.0f,  2.0f), 270.0f);
            i.add(new Point3f(-2.0f, 0.0f,  2.0f),   0.0f);
    
            RotPosPathInterpolator interpolator = new RotPosPathInterpolator(
                alpha, target, axisOfTransform, 
                i.getAlphas(), i.getOrientations(), i.getPositions());        
            interpolator.setSchedulingBounds(
                new BoundingSphere(new Point3d(), 100.0));
    
            rootBranchGroup.addChild(target);
            target.addChild(interpolator);
            target.addChild(new ColorCube(0.4));
        }
    }
    

    另一条评论:使用这样一个实用程序类,这个解决方案可能还可以,但是对于更复杂的路径和行为,我们可能会为路径处理创建一个专用的基础设施