package framework.model3D; import java.util.ArrayList; import java3d.BoundingPolytope; import java3d.BoundingSphere; import java3d.Bounds; import java3d.Transform3D; import java3d.Matrix4d; import java3d.Point3d; import java3d.Vector3d; import java3d.Vector4d; public class BoundingSurface implements Cloneable { private Bounds bounds = null; // 粗い衝突判定用(粗い地面用) private ArrayList<BoundingSurface> children = new ArrayList<BoundingSurface>(); private ArrayList<Vector3d> vertexList = new ArrayList<Vector3d>(); private static Vector4d plane[] = { new Vector4d(), new Vector4d(), new Vector4d(), new Vector4d(), new Vector4d() }; public Object clone() { BoundingSurface s = new BoundingSurface(); if (bounds != null) { s.setBounds((Bounds)bounds.clone()); } for (int i = 0; i < children.size(); i++) { s.children.add((BoundingSurface)children.get(i).clone()); } for (int i = 0; i < vertexList.size(); i++) { s.vertexList.add((Vector3d)vertexList.get(i).clone()); } return s; } public void setBounds(Bounds bounds) { this.bounds = bounds; } public Bounds getBounds() { return bounds; } public void addVertex(Vector3d v) { vertexList.add(v); } public void addChild(BoundingSurface bs, boolean bCombineBounds) { children.add(bs); if (bCombineBounds) { if (bounds == null) { bounds = (Bounds)bs.bounds.clone(); } else { bounds.combine(bs.bounds); } } } public void transform(Transform3D transform3D) { bounds.transform(transform3D); for (int i = 0; i < vertexList.size(); i++) { Matrix4d mat4d = new Matrix4d(); transform3D.get(mat4d); double x = mat4d.m00 * vertexList.get(i).x + mat4d.m01 * vertexList.get(i).y + mat4d.m02 * vertexList.get(i).z + mat4d.m03; double y = mat4d.m10 * vertexList.get(i).x + mat4d.m11 * vertexList.get(i).y + mat4d.m12 * vertexList.get(i).z + mat4d.m13; double z = mat4d.m20 * vertexList.get(i).x + mat4d.m21 * vertexList.get(i).y + mat4d.m22 * vertexList.get(i).z + mat4d.m23; vertexList.get(i).x = x; vertexList.get(i).y = y; vertexList.get(i).z = z; } } /** * BoundingSphereとの粗い衝突判定 * @param bs 衝突判定の対象 * @return 衝突しているBoundingSurfaceのリスト(nullを返すことはない) */ public ArrayList<BoundingSurface> intersect(BoundingSphere bs) { ArrayList<BoundingSurface> results = new ArrayList<BoundingSurface>(); if (children == null || children.size() == 0) { if (bounds.intersect(bs)) { results.add(this); } } else { if (bounds == null || bounds.intersect(bs)) { for (int n = 0; n < children.size(); n++) { results.addAll(children.get(n).intersect(bs)); } } } return results; } /** * OBBとの詳細な衝突判定 * @param obb 衝突判定の対象 * @return 衝突判定の結果 */ public CollisionResult intersect(OBB obb) { if (children == null || children.size() == 0) { // 葉の場合は、凸ポリゴンを立ち上げた薄い多角柱 if (bounds instanceof BoundingPolytope) { ((BoundingPolytope)bounds).getPlanes(plane); CollisionResult cr = obb.intersect(plane[0]); // obbが底面を含む無限平面と交わっているか? if (cr != null) { // 無限平面と交わっている場合、無限平面との衝突点が凸ポリゴンの内部に位置するか? if (GeometryUtility.inside(vertexList, cr.collisionPoint.getVector3d(), cr.normal)) { return cr; } } } return null; } else { for (int n = 0; n < children.size(); n++) { CollisionResult cr = children.get(n).intersect(obb); if (cr != null) { return cr; } } return null; } } }