- package framework.model3D;
-
- import java.util.ArrayList;
- import java.util.Enumeration;
-
- import javax.media.j3d.Appearance;
- import javax.media.j3d.BoundingPolytope;
- import javax.media.j3d.Geometry;
- import javax.media.j3d.IndexedTriangleArray;
- import javax.media.j3d.IndexedTriangleFanArray;
- import javax.media.j3d.IndexedTriangleStripArray;
- import javax.media.j3d.Light;
- import javax.media.j3d.Node;
- import javax.media.j3d.Shape3D;
- import javax.media.j3d.Transform3D;
- import javax.media.j3d.TransformGroup;
- import javax.media.j3d.TriangleArray;
- import javax.media.j3d.TriangleFanArray;
- import javax.media.j3d.TriangleStripArray;
- import javax.vecmath.Vector3d;
- import javax.vecmath.Vector4d;
-
- import com.sun.j3d.utils.geometry.Box;
- import com.sun.j3d.utils.geometry.Cone;
- import com.sun.j3d.utils.geometry.Cylinder;
- import com.sun.j3d.utils.geometry.Primitive;
- import com.sun.j3d.utils.geometry.Sphere;
-
- public class BaseObject3D implements Placeable {
- public TransformGroup center;
-
- protected BoundingSurface[] boundingSurfaces = null;
- private ArrayList<ShadowVolume> shadowVolumes = new ArrayList<ShadowVolume>();
-
- private BumpMapGenerator bumpMapGenerator = null;
- private ReflectionMapGenerator reflectionMapGenerator = null;
- protected boolean bBumpMapApplied = false;
- protected boolean bReflectionMapApplied = false;
-
- public BaseObject3D() {
- center = new TransformGroup();
- center.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
- center.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
- }
-
- public BaseObject3D(Geometry g, Appearance a) {
- init(g, a);
- }
-
- // コピーコンストラクタ
- public BaseObject3D(BaseObject3D obj) {
- Transform3D transCenter = new Transform3D();
- obj.center.getTransform(transCenter);
- this.center = new TransformGroup(transCenter);
- this.center.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
- this.center.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
- Enumeration<Node> nodes = obj.getPrimitiveNodes();
- for (; nodes.hasMoreElements();) {
- Node node = nodes.nextElement();
- if (node != null && node instanceof Shape3D) {
- Shape3D shape = (Shape3D)node;
- shape.setCapability(Shape3D.ALLOW_APPEARANCE_READ);
- shape.setCapability(Shape3D.ALLOW_APPEARANCE_WRITE);
- Appearance a = (Appearance)shape.getAppearance().cloneNodeComponent(true);
- a.setCapability(Appearance.ALLOW_TEXTURE_READ);
- a.setCapability(Appearance.ALLOW_TEXTURE_WRITE);
- a.setCapability(Appearance.ALLOW_TEXTURE_ATTRIBUTES_READ);
- a.setCapability(Appearance.ALLOW_TEXTURE_ATTRIBUTES_WRITE);
- a.setCapability(Appearance.ALLOW_TEXTURE_UNIT_STATE_READ);
- a.setCapability(Appearance.ALLOW_TEXTURE_UNIT_STATE_WRITE);
- this.center.addChild(new Shape3D((Geometry) shape
- .getAllGeometries().nextElement(), a));
- } else if (node != null && node instanceof Primitive) {
- Primitive primitive = (Primitive)node;
- primitive = (Primitive)primitive.cloneTree();
- primitive.setCapability(Primitive.ENABLE_APPEARANCE_MODIFY);
- this.center.addChild(primitive);
- }
- }
- if (obj.boundingSurfaces != null) {
- this.boundingSurfaces = obj.boundingSurfaces;
- }
- this.bumpMapGenerator = obj.bumpMapGenerator;
- this.reflectionMapGenerator = obj.reflectionMapGenerator;
- this.bBumpMapApplied = obj.bBumpMapApplied;
- this.bReflectionMapApplied = obj.bReflectionMapApplied;
- }
-
- // 自分を複製する(クローンを作る)
- public BaseObject3D duplicate() {
- BaseObject3D obj = new BaseObject3D(this);
- return obj;
- }
-
- public void init(Geometry g, Appearance a) {
- center = new TransformGroup();
- center.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
- center.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
- a.setCapability(Appearance.ALLOW_TEXTURE_READ);
- a.setCapability(Appearance.ALLOW_TEXTURE_WRITE);
- a.setCapability(Appearance.ALLOW_TEXTURE_ATTRIBUTES_READ);
- a.setCapability(Appearance.ALLOW_TEXTURE_ATTRIBUTES_WRITE);
- a.setCapability(Appearance.ALLOW_TEXTURE_UNIT_STATE_READ);
- a.setCapability(Appearance.ALLOW_TEXTURE_UNIT_STATE_WRITE);
- Shape3D shape = new Shape3D(g, a);
- shape.setCapability(Shape3D.ALLOW_APPEARANCE_READ);
- shape.setCapability(Shape3D.ALLOW_APPEARANCE_WRITE);
- shape.setCapability(Shape3D.ALLOW_GEOMETRY_READ);
- shape.setCapability(Shape3D.ALLOW_GEOMETRY_WRITE);
- center.addChild(shape);
- }
-
- public void updateGeometry(Geometry g) {
- Node node = getPrimitiveNode();
- if (node != null && node instanceof Shape3D) {
- ((Shape3D)node).removeAllGeometries();
- ((Shape3D)node).addGeometry(g);
- boundingSurfaces = null;
- }
- }
-
- @Override
- public TransformGroup getTransformGroupToPlace() {
- return getBody().center;
- }
-
- public BaseObject3D getBody() {
- return this;
- }
-
- // public void placeFirst(RWTUniverse universe) {
- // universe.getRoot().insertChild(this.center, 0);
- // }
- //
- // public void placeLast(RWTUniverse universe) {
- // universe.getRoot().addChild(this.center);
- // }
- //
- public Node getPrimitiveNode() {
- return (Node)center.getChild(0);
- }
-
- public Enumeration<Node> getPrimitiveNodes() {
- return (Enumeration<Node>)center.getAllChildren();
- }
-
- public Appearance getAppearance() {
- Appearance ap = null;
- Node node = getPrimitiveNode();
- if (node != null && node instanceof Shape3D) {
- Shape3D shape = (Shape3D)node;
- ap = shape.getAppearance();
- if (ap == null) {
- ap = new Appearance();
- shape.setAppearance(ap);
- }
- } else if (node != null && node instanceof Primitive) {
- Primitive primitive = (Primitive)node;
- ap = primitive.getAppearance();
- if (ap == null) {
- ap = new Appearance();
- primitive.setAppearance(ap);
- }
- }
- return ap;
- }
-
- public ArrayList<Appearance> getAppearances() {
- ArrayList<Appearance> appearances = new ArrayList<Appearance>();
- appearances.add(getAppearance());
- return appearances;
- }
-
- /**
- * 衝突判定用のボリューム(ポリゴンと粗い判定用の多角柱)を取得する
- * @return 衝突判定用のボリューム列
- */
- public BoundingSurface[] getBoundingSurfaces() {
- if (boundingSurfaces == null) {
- Node node = getPrimitiveNode();
- if (node == null) return null;
-
- ArrayList<Vector3d> vertex3DList = null;
- if (node instanceof Box) {
- // Boxの場合
- Box box = ((Box)node);
- // 頂点列を取得する
- vertex3DList = getVertexList(box.getShape(Box.BACK).getGeometry());
- vertex3DList.addAll(getVertexList(box.getShape(Box.BOTTOM).getGeometry()));
- vertex3DList.addAll(getVertexList(box.getShape(Box.FRONT).getGeometry()));
- vertex3DList.addAll(getVertexList(box.getShape(Box.LEFT).getGeometry()));
- vertex3DList.addAll(getVertexList(box.getShape(Box.RIGHT).getGeometry()));
- vertex3DList.addAll(getVertexList(box.getShape(Box.TOP).getGeometry()));
- } else if (node instanceof Cylinder) {
- // Cylinderの場合
- Cylinder cylinder = ((Cylinder)node);
- // 頂点列を取得する
- vertex3DList = getVertexList(cylinder.getShape(Cylinder.BODY).getGeometry());
- vertex3DList.addAll(getVertexList(cylinder.getShape(Cylinder.BOTTOM).getGeometry()));
- vertex3DList.addAll(getVertexList(cylinder.getShape(Cylinder.TOP).getGeometry()));
- } else if (node instanceof Cone) {
- // Coneの場合
- Cone cone = ((Cone)node);
- // 頂点列を取得する
- vertex3DList = getVertexList(cone.getShape(Cone.BODY).getGeometry());
- vertex3DList.addAll(getVertexList(cone.getShape(Cone.CAP).getGeometry()));
- } else if (node instanceof Sphere) {
- // Sphereの場合
- Sphere sphere = ((Sphere)node);
- // 頂点列を取得する
- vertex3DList = getVertexList(sphere.getShape(Sphere.BODY).getGeometry());
- } else if (node instanceof Shape3D) {
- // Shape3Dの場合
- Shape3D shape = (Shape3D)node;
- // 頂点列を取得する
- vertex3DList = getVertexList(shape.getGeometry());
- }
- if (vertex3DList == null) return null;
-
- BoundingSurface[] surfaces = new BoundingSurface[vertex3DList.size() / 3];
-
- for (int i = 0; i < vertex3DList.size(); i += 3) {
- Vector3d v1 = vertex3DList.get(i);
- Vector3d v2 = vertex3DList.get(i + 1);
- Vector3d v3 = vertex3DList.get(i + 2);
- BoundingSurface bSurface = new BoundingSurface();
- bSurface.addVertex((Vector3d)v1.clone());
- bSurface.addVertex((Vector3d)v2.clone());
- bSurface.addVertex((Vector3d)v3.clone());
- bSurface.setBounds(createBoundingPolytope(v1, v2, v3));
- surfaces[i / 3] = bSurface;
- }
- boundingSurfaces = surfaces;
- }
- return boundingSurfaces;
- }
-
- private ArrayList<Vector3d> getVertexList(Geometry g) {
- ArrayList<Vector3d> vertex3DList = new ArrayList<Vector3d>();
- double coordinate1[] = new double[3];
- if (g instanceof IndexedTriangleArray) {
- // IndexedTriangleArray の場合
- IndexedTriangleArray triArray = (IndexedTriangleArray)g;
-
- // 全頂点を3D上の頂点をvertex3DListに入れていく。
- for (int i = 0; i < triArray.getIndexCount(); i++) {
- triArray.getCoordinates(triArray.getCoordinateIndex(i), coordinate1);
- vertex3DList.add(new Vector3d(coordinate1));
- }
- } else if (g instanceof TriangleArray) {
- // TriangleArray の場合
- TriangleArray triArray = (TriangleArray)g;
-
- // 全頂点を3D上の頂点をvertex3DListに入れていく。
- for (int i = 0; i < triArray.getVertexCount(); i++) {
- triArray.getCoordinates(i, coordinate1);
- vertex3DList.add(new Vector3d(coordinate1));
- }
- } else if (g instanceof IndexedTriangleStripArray) {
- // IndexedTriangleStripArray の場合
- IndexedTriangleStripArray triStripAttay = (IndexedTriangleStripArray)g;
- int stripVertexCounts[] = new int[triStripAttay.getNumStrips()];
- triStripAttay.getStripIndexCounts(stripVertexCounts);
- // 全頂点を3D上の頂点をvertex3DListに入れていく
- int index = 0;
- double coordinate2[] = new double[3];
- double coordinate3[] = new double[3];
- double coordinate4[] = new double[3];
- for (int i = 0; i < triStripAttay.getNumStrips(); i++) {
- for (int j = 0; j < stripVertexCounts[i]; j += 2) {
- triStripAttay.getCoordinates(triStripAttay.getCoordinateIndex(index), coordinate1);
- triStripAttay.getCoordinates(triStripAttay.getCoordinateIndex(index+1), coordinate2);
- triStripAttay.getCoordinates(triStripAttay.getCoordinateIndex(index+2), coordinate3);
- triStripAttay.getCoordinates(triStripAttay.getCoordinateIndex(index+3), coordinate4);
- vertex3DList.add(new Vector3d(coordinate1)); //1つめの三角形
- vertex3DList.add(new Vector3d(coordinate2));
- vertex3DList.add(new Vector3d(coordinate3));
- vertex3DList.add(new Vector3d(coordinate2)); //2つめの三角形
- vertex3DList.add(new Vector3d(coordinate4));
- vertex3DList.add(new Vector3d(coordinate3));
- index += 2;
- }
- }
- } else if (g instanceof TriangleStripArray) {
- // TriangleStripArray の場合
- TriangleStripArray triStripAttay = (TriangleStripArray)g;
- int stripVertexCounts[] = new int[triStripAttay.getNumStrips()];
- triStripAttay.getStripVertexCounts(stripVertexCounts);
- // 全頂点を3D上の頂点をvertex3DListに入れていく
- int index = 0;
- double coordinate2[] = new double[3];
- double coordinate3[] = new double[3];
- double coordinate4[] = new double[3];
- for (int i = 0; i < triStripAttay.getNumStrips(); i++) {
- for (int j = 0; j < stripVertexCounts[i]; j += 2) {
- triStripAttay.getCoordinates(index, coordinate1);
- triStripAttay.getCoordinates(index+1, coordinate2);
- triStripAttay.getCoordinates(index+2, coordinate3);
- triStripAttay.getCoordinates(index+3, coordinate4);
- vertex3DList.add(new Vector3d(coordinate1)); //1つめの三角形
- vertex3DList.add(new Vector3d(coordinate2));
- vertex3DList.add(new Vector3d(coordinate3));
- vertex3DList.add(new Vector3d(coordinate2)); //2つめの三角形
- vertex3DList.add(new Vector3d(coordinate4));
- vertex3DList.add(new Vector3d(coordinate3));
- index += 2;
- }
- }
- } else if (g instanceof IndexedTriangleFanArray) {
- // IndexedTriangleFanArray の場合
- IndexedTriangleFanArray triFanAttay = (IndexedTriangleFanArray)g;
- int stripVertexCounts[] = new int[triFanAttay.getNumStrips()];
- triFanAttay.getStripIndexCounts(stripVertexCounts);
- // 全頂点を3D上の頂点をvertex3DListに入れていく
- int index = 0;
- double coordinate2[] = new double[3];
- double coordinate3[] = new double[3];
- double coordinate4[] = null;
- for (int i = 0; i < triFanAttay.getNumStrips(); i++) {
- triFanAttay.getCoordinates(triFanAttay.getCoordinateIndex(index), coordinate1); // 中心点
- triFanAttay.getCoordinates(triFanAttay.getCoordinateIndex(index+1), coordinate2);
- index += 2;
- for (int j = 2; j < stripVertexCounts[i]; j++) {
- triFanAttay.getCoordinates(triFanAttay.getCoordinateIndex(index), coordinate3);
- vertex3DList.add(new Vector3d(coordinate1));
- vertex3DList.add(new Vector3d(coordinate2));
- vertex3DList.add(new Vector3d(coordinate3));
- coordinate4 = coordinate2;
- coordinate2 = coordinate3;
- coordinate3 = coordinate4;
- index++;
- }
- }
- } else if (g instanceof TriangleFanArray) {
- // TriangleFanArray の場合
- TriangleFanArray triFanAttay = (TriangleFanArray)g;
- int stripVertexCounts[] = new int[triFanAttay.getNumStrips()];
- triFanAttay.getStripVertexCounts(stripVertexCounts);
- // 全頂点を3D上の頂点をvertex3DListに入れていく
- int index = 0;
- double coordinate2[] = new double[3];
- double coordinate3[] = new double[3];
- double coordinate4[] = null;
- for (int i = 0; i < triFanAttay.getNumStrips(); i++) {
- triFanAttay.getCoordinates(index, coordinate1); // 中心点
- triFanAttay.getCoordinates(index + 1, coordinate2);
- index += 2;
- for (int j = 2; j < stripVertexCounts[i]; j++) {
- triFanAttay.getCoordinates(index, coordinate3);
- vertex3DList.add(new Vector3d(coordinate1));
- vertex3DList.add(new Vector3d(coordinate2));
- vertex3DList.add(new Vector3d(coordinate3));
- coordinate4 = coordinate2;
- coordinate2 = coordinate3;
- coordinate3 = coordinate4;
- index++;
- }
- }
- } else {
- // QuadArray系等は未対応
- return null;
- }
- return vertex3DList;
- }
-
- protected BoundingPolytope createBoundingPolytope(Vector3d vertex1,
- Vector3d vertex2, Vector3d vertex3) {
- Vector3d v1 = new Vector3d();
- Vector3d v2 = new Vector3d();
- Vector3d v3 = new Vector3d();
- Vector3d v4 = new Vector3d();
- Vector3d v5 = new Vector3d();
- Vector3d v6 = new Vector3d();
- Vector3d cv1 = new Vector3d();
- Vector3d cv2 = new Vector3d();
- cv1.sub(vertex3, vertex1);
- cv2.sub(vertex2, vertex1);
- Vector3d cv = new Vector3d();
- cv.cross(cv1, cv2);
- cv.normalize();
- cv.scale(0.01);
- v1.set(vertex1);
- v2.set(vertex2);
- v3.set(vertex3);
- v4.set(vertex1);
- v4.add(cv);
- v5.set(vertex2);
- v5.add(cv);
- v6.set(vertex3);
- v6.add(cv);
-
- Vector3d pv1 = new Vector3d();
- Vector3d pv2 = new Vector3d();
- Vector3d pv3 = new Vector3d();
- Vector3d pn = new Vector3d();
- Vector4d[] plane = new Vector4d[5];
-
- // 0
- pv1 = v1;
- pv2.sub(v2, v1);
- pv3.sub(v3, v1);
-
- pn.cross(pv2, pv3);
- pn.normalize();
- plane[0] = new Vector4d(pn.x, pn.y, pn.z, -pn.dot(pv1));
-
- // 1
- pv1 = v1;
- pv2.sub(v4, v1);
- pv3.sub(v2, v1);
-
- pn.cross(pv2, pv3);
- pn.normalize();
- plane[1] = new Vector4d(pn.x, pn.y, pn.z, -pn.dot(pv1));
-
- // 2
- pv1 = v1;
- pv2.sub(v3, v1);
- pv3.sub(v4, v1);
-
- pn.cross(pv2, pv3);
- pn.normalize();
- plane[2] = new Vector4d(pn.x, pn.y, pn.z, -pn.dot(pv1));
-
- // 3
- pv1 = v6;
- pv2.sub(v3, v6);
- pv3.sub(v5, v6);
-
- pn.cross(pv2, pv3);
- pn.normalize();
- plane[3] = new Vector4d(pn.x, pn.y, pn.z, -pn.dot(pv1));
-
- // 4
- pv1 = v6;
- pv2.sub(v5, v6);
- pv3.sub(v4, v6);
-
- pn.cross(pv2, pv3);
- pn.normalize();
- plane[4] = new Vector4d(pn.x, pn.y, pn.z, -pn.dot(pv1));
-
- return new BoundingPolytope(plane);
- }
-
- public void createShadowVolume(ArrayList<Light> lights, double shadowDepth, Transform3D localToWorld) {
- for (int n = 0; n < lights.size(); n++) {
- shadowVolumes.add(new ShadowVolume(this, lights.get(n), shadowDepth, localToWorld));
- }
- }
-
- public void updateShadowVolume(Transform3D localToWorld) {
- for (int n = 0; n < shadowVolumes.size(); n++) {
- shadowVolumes.get(n).update(localToWorld);
- }
- }
-
- public void setBumpMapping(BumpMapGenerator g) {
- bumpMapGenerator = g;
- bBumpMapApplied = true;
- }
-
- public BumpMapGenerator getBumpMappingInfo() {
- return bumpMapGenerator;
- }
-
- public boolean isBumpMappingApplied() {
- return bBumpMapApplied;
- }
-
- public void setReflectionMapping(ReflectionMapGenerator g) {
- reflectionMapGenerator = g;
- bReflectionMapApplied = true;
- }
-
- public ReflectionMapGenerator getReflectionMappingInfo() {
- return reflectionMapGenerator;
- }
-
- public boolean isReflectionMappingApplied() {
- return bReflectionMapApplied;
- }
-
- public boolean hasAppearancePrepared() {
- if (bumpMapGenerator != null && !bumpMapGenerator.hasMapped()) return false;
- if (reflectionMapGenerator != null && !reflectionMapGenerator.hasMapped()) return false;
- return true;
- }
- }