Код беспорядок (и кажется, что его части были продублированы при публикации?). Однако по существу вопроса:
Это правда, что один TransformGroup
может содержать только один конкретный Transform3D
. Хотя можно собрать несколько преобразований (например, вращение и перемещение) в одном Transform3D
, это не очень хорошо работает с предопределенными интерполяторами.
Вся идея Java3D как API на основе графа сцены состоит в том, чтобы собрать "дерево" узлов, где каждый узел служит определенной цели.
В этом случае ваше дерево будет состоять из нескольких узлов:
S Sphere: The planet
|
|
RTG Rotation TransformGroup: Responsible for
| rotating the planet about its y-asis
|
|
TTG Translation TransformGroup: Responsible for
| translating the (rotating) planet away from
| the sun
|
OTG Orbit TransformGroup: Responsible for
| rotating the (translated and rotating) planet
| about the center of the sun
|
Root The root node of your universe
Вы можете убедиться, что структура кода похожа на структуру графика, задав соответствующие имена переменных и методов.
Вот полный пример вращающегося объекта, который вращается вокруг центра:
import java.awt.GraphicsConfiguration;
import javax.media.j3d.Alpha;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Canvas3D;
import javax.media.j3d.Node;
import javax.media.j3d.RotationInterpolator;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.vecmath.Point3d;
import javax.vecmath.Vector3d;
import com.sun.j3d.utils.geometry.ColorCube;
import com.sun.j3d.utils.geometry.Sphere;
import com.sun.j3d.utils.universe.SimpleUniverse;
public class SphereOrbit
{
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 viewPlatformTransform = new Transform3D();
Transform3D t0 = new Transform3D();
t0.setTranslation(new Vector3d(0,0,10));
Transform3D t1 = new Transform3D();
t1.rotX(Math.toRadians(-30));
viewPlatformTransform.mul(t1, t0);
simpleUniverse.getViewingPlatform().
getViewPlatformTransform().setTransform(viewPlatformTransform);;
frame.setSize(800,800);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private static BoundingSphere boundingSphere =
new BoundingSphere(new Point3d(0.0,0.0,0.0), Double.MAX_VALUE);
// Build the transform group that does the rotation
// of the planet in its local coordinate system
// (This will cause the planet to spin about its own y-axis)
private static TransformGroup createRotationTransformGroup(
int rotationTimeMs)
{
TransformGroup rotationTransformGroup = new TransformGroup();
rotationTransformGroup.setCapability(
TransformGroup.ALLOW_TRANSFORM_WRITE);
Alpha rotationAlpha = new Alpha(-1, rotationTimeMs);
RotationInterpolator rotationInterpolator =
new RotationInterpolator(rotationAlpha, rotationTransformGroup);
rotationInterpolator.setSchedulingBounds(boundingSphere);
rotationTransformGroup.addChild(rotationInterpolator);
return rotationTransformGroup;
}
// Build the transform group that moves the (rotating) planet
// about a certain (fixed) distance, away from the center
private static TransformGroup createTranslatingTransformGroup(
double distanceFromCenter)
{
TransformGroup translationTransformGroup = new TransformGroup();
Transform3D translationTransform = new Transform3D();
translationTransform.setTranslation(
new Vector3d(distanceFromCenter, 0, 0));
translationTransformGroup.setTransform(translationTransform);
return translationTransformGroup;
}
// Build the transform group that orbits the planet. This
// transform group will rotate the (translated and rotating)
// planet around the center
private static TransformGroup createOrbitTransformGroup(int orbitTimeMs)
{
TransformGroup orbitTransformGroup = new TransformGroup();
orbitTransformGroup.setCapability(
TransformGroup.ALLOW_TRANSFORM_WRITE);
Alpha orbitAlpha = new Alpha(-1, orbitTimeMs);
RotationInterpolator orbitInterpolator =
new RotationInterpolator(orbitAlpha, orbitTransformGroup);
orbitInterpolator.setSchedulingBounds(boundingSphere);
orbitTransformGroup.addChild(orbitInterpolator);
return orbitTransformGroup;
}
private static void createContents(BranchGroup rootBranchGroup)
{
// The basic properties of the Planet
int rotationTimeMs = 1500;
double distanceFromCenter = 3;
int orbitTimeMs = 4000;
// The planet (using a color cube here, so that its
// own rotation is visible)
//Node planet = new Sphere(0.2f);
Node planet = new ColorCube(0.2);
TransformGroup rotationTransformGroup =
createRotationTransformGroup(rotationTimeMs);
// Attach the planet to the rotation transform group
rotationTransformGroup.addChild(planet);
TransformGroup translationTransformGroup =
createTranslatingTransformGroup(distanceFromCenter);
// Attach the rotating planet to the translation transform group
translationTransformGroup.addChild(rotationTransformGroup);
TransformGroup orbitTransformGroup =
createOrbitTransformGroup(orbitTimeMs);
// Add the (translated and rotating) planet to the orbitTransformGroup
orbitTransformGroup.addChild(translationTransformGroup);
rootBranchGroup.addChild(orbitTransformGroup);
}
}
(Примечание. Если внимательно присмотреться, вы заметите, что метод createRotationTransformGroup
и метод createOrbitTransformGroup
на самом деле делают одно и то же! Один из них относится к планете, а другой — к переведенной планете. Итак, для реального приложения их можно было бы объединить в один метод. Я надеялся, что в нынешнем виде идея сборки нескольких нод может стать более понятной)
Изменить: расширено на основе комментариев
Чтобы добавить другой объект (луну), который вращается вокруг существующего объекта (который сам уже вращается и вращается вокруг солнца), вы должны прикрепить новую ветвь к соответствующему существующему узлу графа сцены. Основываясь на приведенном выше изображении («ASCII-Art»), вам нужно будет прикрепить этот узел к «TTG». Новый узел сам будет содержать узел орбиты, узел перемещения и узел вращения (который содержит фактический лунный объект).
![Орбитальный](https://i.stack.imgur.com/cqsWf.gif)
Если вы намерены построить полную солнечную систему, подобную этой, вам, вероятно, следует ввести соответствующие служебные методы, подобные тем, которые я уже набросал в этом расширенном примере:
import java.awt.GraphicsConfiguration;
import javax.media.j3d.Alpha;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Canvas3D;
import javax.media.j3d.Node;
import javax.media.j3d.RotationInterpolator;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.vecmath.Point3d;
import javax.vecmath.Vector3d;
import com.sun.j3d.utils.geometry.ColorCube;
import com.sun.j3d.utils.universe.SimpleUniverse;
public class SphereOrbitExtended
{
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 viewPlatformTransform = new Transform3D();
Transform3D t0 = new Transform3D();
t0.setTranslation(new Vector3d(0,0,10));
Transform3D t1 = new Transform3D();
t1.rotX(Math.toRadians(-30));
viewPlatformTransform.mul(t1, t0);
simpleUniverse.getViewingPlatform().
getViewPlatformTransform().setTransform(viewPlatformTransform);;
frame.setSize(800,800);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private static BoundingSphere boundingSphere =
new BoundingSphere(new Point3d(0.0,0.0,0.0), Double.MAX_VALUE);
// Build the transform group that does a rotation about the
// y-axis, rotating once in the given time
private static TransformGroup createRotationTransformGroup(
int rotationTimeMs, boolean forward)
{
TransformGroup rotationTransformGroup = new TransformGroup();
rotationTransformGroup.setCapability(
TransformGroup.ALLOW_TRANSFORM_WRITE);
Alpha rotationAlpha = new Alpha(-1, rotationTimeMs);
float angle = forward ? (float) (2 * Math.PI) : (float)(-2 * Math.PI);
RotationInterpolator rotationInterpolator =
new RotationInterpolator(rotationAlpha, rotationTransformGroup,
new Transform3D(), 0.0f, angle);
rotationInterpolator.setSchedulingBounds(boundingSphere);
rotationTransformGroup.addChild(rotationInterpolator);
return rotationTransformGroup;
}
// Build the transform group that performs the specified translation
private static TransformGroup createTranslatingTransformGroup(
double dx, double dy, double dz)
{
TransformGroup translationTransformGroup = new TransformGroup();
Transform3D translationTransform = new Transform3D();
translationTransform.setTranslation(
new Vector3d(dx, dy, dz));
translationTransformGroup.setTransform(translationTransform);
return translationTransformGroup;
}
private static void createContents(BranchGroup rootBranchGroup)
{
int orbitTimeMs = 4000;
TransformGroup orbitTransformGroup =
createRotationTransformGroup(orbitTimeMs, true);
rootBranchGroup.addChild(orbitTransformGroup);
double distanceFromCenter = 3;
TransformGroup translationTransformGroup =
createTranslatingTransformGroup(distanceFromCenter, 0, 0);
orbitTransformGroup.addChild(translationTransformGroup);
int rotationTimeMs = 1500;
Node planet = new ColorCube(0.2);
TransformGroup rotationTransformGroup =
createRotationTransformGroup(rotationTimeMs, true);
rotationTransformGroup.addChild(planet);
translationTransformGroup.addChild(rotationTransformGroup);
int moonOrbitTimeMs = 1000;
TransformGroup moonOrbitTransformGroup =
createRotationTransformGroup(moonOrbitTimeMs, false);
translationTransformGroup.addChild(moonOrbitTransformGroup);
double moonDistanceFromPlanet = 0.8;
TransformGroup moonTranslationTransformGroup =
createTranslatingTransformGroup(moonDistanceFromPlanet, 0, 0);
moonOrbitTransformGroup.addChild(moonTranslationTransformGroup);
int moonRotationTimeMs = 500;
Node moon = new ColorCube(0.1);
TransformGroup moonRotationTransformGroup =
createRotationTransformGroup(moonRotationTimeMs, true);
moonRotationTransformGroup.addChild(moon);
moonTranslationTransformGroup.addChild(moonRotationTransformGroup);
}
}
person
Marco13
schedule
14.05.2015