Newer
Older
CactusServer / src / main / java / framework / model3D / BaseObject3D.java
y-ota on 10 May 2018 16 KB 初うp
  1. package framework.model3D;
  2.  
  3. import java.util.ArrayList;
  4. import java.util.Enumeration;
  5.  
  6. import javax.media.j3d.Appearance;
  7. import javax.media.j3d.BoundingPolytope;
  8. import javax.media.j3d.Geometry;
  9. import javax.media.j3d.IndexedTriangleArray;
  10. import javax.media.j3d.IndexedTriangleFanArray;
  11. import javax.media.j3d.IndexedTriangleStripArray;
  12. import javax.media.j3d.Light;
  13. import javax.media.j3d.Node;
  14. import javax.media.j3d.Shape3D;
  15. import javax.media.j3d.Transform3D;
  16. import javax.media.j3d.TransformGroup;
  17. import javax.media.j3d.TriangleArray;
  18. import javax.media.j3d.TriangleFanArray;
  19. import javax.media.j3d.TriangleStripArray;
  20. import javax.vecmath.Vector3d;
  21. import javax.vecmath.Vector4d;
  22.  
  23. import com.sun.j3d.utils.geometry.Box;
  24. import com.sun.j3d.utils.geometry.Cone;
  25. import com.sun.j3d.utils.geometry.Cylinder;
  26. import com.sun.j3d.utils.geometry.Primitive;
  27. import com.sun.j3d.utils.geometry.Sphere;
  28.  
  29. public class BaseObject3D implements Placeable {
  30. public TransformGroup center;
  31. protected BoundingSurface[] boundingSurfaces = null;
  32. private ArrayList<ShadowVolume> shadowVolumes = new ArrayList<ShadowVolume>();
  33. private BumpMapGenerator bumpMapGenerator = null;
  34. private ReflectionMapGenerator reflectionMapGenerator = null;
  35. protected boolean bBumpMapApplied = false;
  36. protected boolean bReflectionMapApplied = false;
  37. public BaseObject3D() {
  38. center = new TransformGroup();
  39. center.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
  40. center.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
  41. }
  42. public BaseObject3D(Geometry g, Appearance a) {
  43. init(g, a);
  44. }
  45. // コピーコンストラクタ
  46. public BaseObject3D(BaseObject3D obj) {
  47. Transform3D transCenter = new Transform3D();
  48. obj.center.getTransform(transCenter);
  49. this.center = new TransformGroup(transCenter);
  50. this.center.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
  51. this.center.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
  52. Enumeration<Node> nodes = obj.getPrimitiveNodes();
  53. for (; nodes.hasMoreElements();) {
  54. Node node = nodes.nextElement();
  55. if (node != null && node instanceof Shape3D) {
  56. Shape3D shape = (Shape3D)node;
  57. shape.setCapability(Shape3D.ALLOW_APPEARANCE_READ);
  58. shape.setCapability(Shape3D.ALLOW_APPEARANCE_WRITE);
  59. Appearance a = (Appearance)shape.getAppearance().cloneNodeComponent(true);
  60. a.setCapability(Appearance.ALLOW_TEXTURE_READ);
  61. a.setCapability(Appearance.ALLOW_TEXTURE_WRITE);
  62. a.setCapability(Appearance.ALLOW_TEXTURE_ATTRIBUTES_READ);
  63. a.setCapability(Appearance.ALLOW_TEXTURE_ATTRIBUTES_WRITE);
  64. a.setCapability(Appearance.ALLOW_TEXTURE_UNIT_STATE_READ);
  65. a.setCapability(Appearance.ALLOW_TEXTURE_UNIT_STATE_WRITE);
  66. this.center.addChild(new Shape3D((Geometry) shape
  67. .getAllGeometries().nextElement(), a));
  68. } else if (node != null && node instanceof Primitive) {
  69. Primitive primitive = (Primitive)node;
  70. primitive = (Primitive)primitive.cloneTree();
  71. primitive.setCapability(Primitive.ENABLE_APPEARANCE_MODIFY);
  72. this.center.addChild(primitive);
  73. }
  74. }
  75. if (obj.boundingSurfaces != null) {
  76. this.boundingSurfaces = obj.boundingSurfaces;
  77. }
  78. this.bumpMapGenerator = obj.bumpMapGenerator;
  79. this.reflectionMapGenerator = obj.reflectionMapGenerator;
  80. this.bBumpMapApplied = obj.bBumpMapApplied;
  81. this.bReflectionMapApplied = obj.bReflectionMapApplied;
  82. }
  83.  
  84. // 自分を複製する(クローンを作る)
  85. public BaseObject3D duplicate() {
  86. BaseObject3D obj = new BaseObject3D(this);
  87. return obj;
  88. }
  89. public void init(Geometry g, Appearance a) {
  90. center = new TransformGroup();
  91. center.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
  92. center.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
  93. a.setCapability(Appearance.ALLOW_TEXTURE_READ);
  94. a.setCapability(Appearance.ALLOW_TEXTURE_WRITE);
  95. a.setCapability(Appearance.ALLOW_TEXTURE_ATTRIBUTES_READ);
  96. a.setCapability(Appearance.ALLOW_TEXTURE_ATTRIBUTES_WRITE);
  97. a.setCapability(Appearance.ALLOW_TEXTURE_UNIT_STATE_READ);
  98. a.setCapability(Appearance.ALLOW_TEXTURE_UNIT_STATE_WRITE);
  99. Shape3D shape = new Shape3D(g, a);
  100. shape.setCapability(Shape3D.ALLOW_APPEARANCE_READ);
  101. shape.setCapability(Shape3D.ALLOW_APPEARANCE_WRITE);
  102. shape.setCapability(Shape3D.ALLOW_GEOMETRY_READ);
  103. shape.setCapability(Shape3D.ALLOW_GEOMETRY_WRITE);
  104. center.addChild(shape);
  105. }
  106. public void updateGeometry(Geometry g) {
  107. Node node = getPrimitiveNode();
  108. if (node != null && node instanceof Shape3D) {
  109. ((Shape3D)node).removeAllGeometries();
  110. ((Shape3D)node).addGeometry(g);
  111. boundingSurfaces = null;
  112. }
  113. }
  114. @Override
  115. public TransformGroup getTransformGroupToPlace() {
  116. return getBody().center;
  117. }
  118. public BaseObject3D getBody() {
  119. return this;
  120. }
  121. // public void placeFirst(RWTUniverse universe) {
  122. // universe.getRoot().insertChild(this.center, 0);
  123. // }
  124. //
  125. // public void placeLast(RWTUniverse universe) {
  126. // universe.getRoot().addChild(this.center);
  127. // }
  128. //
  129. public Node getPrimitiveNode() {
  130. return (Node)center.getChild(0);
  131. }
  132. public Enumeration<Node> getPrimitiveNodes() {
  133. return (Enumeration<Node>)center.getAllChildren();
  134. }
  135. public Appearance getAppearance() {
  136. Appearance ap = null;
  137. Node node = getPrimitiveNode();
  138. if (node != null && node instanceof Shape3D) {
  139. Shape3D shape = (Shape3D)node;
  140. ap = shape.getAppearance();
  141. if (ap == null) {
  142. ap = new Appearance();
  143. shape.setAppearance(ap);
  144. }
  145. } else if (node != null && node instanceof Primitive) {
  146. Primitive primitive = (Primitive)node;
  147. ap = primitive.getAppearance();
  148. if (ap == null) {
  149. ap = new Appearance();
  150. primitive.setAppearance(ap);
  151. }
  152. }
  153. return ap;
  154. }
  155. public ArrayList<Appearance> getAppearances() {
  156. ArrayList<Appearance> appearances = new ArrayList<Appearance>();
  157. appearances.add(getAppearance());
  158. return appearances;
  159. }
  160.  
  161. /**
  162. * 衝突判定用のボリューム(ポリゴンと粗い判定用の多角柱)を取得する
  163. * @return 衝突判定用のボリューム列
  164. */
  165. public BoundingSurface[] getBoundingSurfaces() {
  166. if (boundingSurfaces == null) {
  167. Node node = getPrimitiveNode();
  168. if (node == null) return null;
  169. ArrayList<Vector3d> vertex3DList = null;
  170. if (node instanceof Box) {
  171. // Boxの場合
  172. Box box = ((Box)node);
  173. // 頂点列を取得する
  174. vertex3DList = getVertexList(box.getShape(Box.BACK).getGeometry());
  175. vertex3DList.addAll(getVertexList(box.getShape(Box.BOTTOM).getGeometry()));
  176. vertex3DList.addAll(getVertexList(box.getShape(Box.FRONT).getGeometry()));
  177. vertex3DList.addAll(getVertexList(box.getShape(Box.LEFT).getGeometry()));
  178. vertex3DList.addAll(getVertexList(box.getShape(Box.RIGHT).getGeometry()));
  179. vertex3DList.addAll(getVertexList(box.getShape(Box.TOP).getGeometry()));
  180. } else if (node instanceof Cylinder) {
  181. // Cylinderの場合
  182. Cylinder cylinder = ((Cylinder)node);
  183. // 頂点列を取得する
  184. vertex3DList = getVertexList(cylinder.getShape(Cylinder.BODY).getGeometry());
  185. vertex3DList.addAll(getVertexList(cylinder.getShape(Cylinder.BOTTOM).getGeometry()));
  186. vertex3DList.addAll(getVertexList(cylinder.getShape(Cylinder.TOP).getGeometry()));
  187. } else if (node instanceof Cone) {
  188. // Coneの場合
  189. Cone cone = ((Cone)node);
  190. // 頂点列を取得する
  191. vertex3DList = getVertexList(cone.getShape(Cone.BODY).getGeometry());
  192. vertex3DList.addAll(getVertexList(cone.getShape(Cone.CAP).getGeometry()));
  193. } else if (node instanceof Sphere) {
  194. // Sphereの場合
  195. Sphere sphere = ((Sphere)node);
  196. // 頂点列を取得する
  197. vertex3DList = getVertexList(sphere.getShape(Sphere.BODY).getGeometry());
  198. } else if (node instanceof Shape3D) {
  199. // Shape3Dの場合
  200. Shape3D shape = (Shape3D)node;
  201. // 頂点列を取得する
  202. vertex3DList = getVertexList(shape.getGeometry());
  203. }
  204. if (vertex3DList == null) return null;
  205.  
  206. BoundingSurface[] surfaces = new BoundingSurface[vertex3DList.size() / 3];
  207.  
  208. for (int i = 0; i < vertex3DList.size(); i += 3) {
  209. Vector3d v1 = vertex3DList.get(i);
  210. Vector3d v2 = vertex3DList.get(i + 1);
  211. Vector3d v3 = vertex3DList.get(i + 2);
  212. BoundingSurface bSurface = new BoundingSurface();
  213. bSurface.addVertex((Vector3d)v1.clone());
  214. bSurface.addVertex((Vector3d)v2.clone());
  215. bSurface.addVertex((Vector3d)v3.clone());
  216. bSurface.setBounds(createBoundingPolytope(v1, v2, v3));
  217. surfaces[i / 3] = bSurface;
  218. }
  219. boundingSurfaces = surfaces;
  220. }
  221. return boundingSurfaces;
  222. }
  223.  
  224. private ArrayList<Vector3d> getVertexList(Geometry g) {
  225. ArrayList<Vector3d> vertex3DList = new ArrayList<Vector3d>();
  226. double coordinate1[] = new double[3];
  227. if (g instanceof IndexedTriangleArray) {
  228. // IndexedTriangleArray の場合
  229. IndexedTriangleArray triArray = (IndexedTriangleArray)g;
  230.  
  231. // 全頂点を3D上の頂点をvertex3DListに入れていく。
  232. for (int i = 0; i < triArray.getIndexCount(); i++) {
  233. triArray.getCoordinates(triArray.getCoordinateIndex(i), coordinate1);
  234. vertex3DList.add(new Vector3d(coordinate1));
  235. }
  236. } else if (g instanceof TriangleArray) {
  237. // TriangleArray の場合
  238. TriangleArray triArray = (TriangleArray)g;
  239. // 全頂点を3D上の頂点をvertex3DListに入れていく。
  240. for (int i = 0; i < triArray.getVertexCount(); i++) {
  241. triArray.getCoordinates(i, coordinate1);
  242. vertex3DList.add(new Vector3d(coordinate1));
  243. }
  244. } else if (g instanceof IndexedTriangleStripArray) {
  245. // IndexedTriangleStripArray の場合
  246. IndexedTriangleStripArray triStripAttay = (IndexedTriangleStripArray)g;
  247. int stripVertexCounts[] = new int[triStripAttay.getNumStrips()];
  248. triStripAttay.getStripIndexCounts(stripVertexCounts);
  249. // 全頂点を3D上の頂点をvertex3DListに入れていく
  250. int index = 0;
  251. double coordinate2[] = new double[3];
  252. double coordinate3[] = new double[3];
  253. double coordinate4[] = new double[3];
  254. for (int i = 0; i < triStripAttay.getNumStrips(); i++) {
  255. for (int j = 0; j < stripVertexCounts[i]; j += 2) {
  256. triStripAttay.getCoordinates(triStripAttay.getCoordinateIndex(index), coordinate1);
  257. triStripAttay.getCoordinates(triStripAttay.getCoordinateIndex(index+1), coordinate2);
  258. triStripAttay.getCoordinates(triStripAttay.getCoordinateIndex(index+2), coordinate3);
  259. triStripAttay.getCoordinates(triStripAttay.getCoordinateIndex(index+3), coordinate4);
  260. vertex3DList.add(new Vector3d(coordinate1)); //1つめの三角形
  261. vertex3DList.add(new Vector3d(coordinate2));
  262. vertex3DList.add(new Vector3d(coordinate3));
  263. vertex3DList.add(new Vector3d(coordinate2)); //2つめの三角形
  264. vertex3DList.add(new Vector3d(coordinate4));
  265. vertex3DList.add(new Vector3d(coordinate3));
  266. index += 2;
  267. }
  268. }
  269. } else if (g instanceof TriangleStripArray) {
  270. // TriangleStripArray の場合
  271. TriangleStripArray triStripAttay = (TriangleStripArray)g;
  272. int stripVertexCounts[] = new int[triStripAttay.getNumStrips()];
  273. triStripAttay.getStripVertexCounts(stripVertexCounts);
  274. // 全頂点を3D上の頂点をvertex3DListに入れていく
  275. int index = 0;
  276. double coordinate2[] = new double[3];
  277. double coordinate3[] = new double[3];
  278. double coordinate4[] = new double[3];
  279. for (int i = 0; i < triStripAttay.getNumStrips(); i++) {
  280. for (int j = 0; j < stripVertexCounts[i]; j += 2) {
  281. triStripAttay.getCoordinates(index, coordinate1);
  282. triStripAttay.getCoordinates(index+1, coordinate2);
  283. triStripAttay.getCoordinates(index+2, coordinate3);
  284. triStripAttay.getCoordinates(index+3, coordinate4);
  285. vertex3DList.add(new Vector3d(coordinate1)); //1つめの三角形
  286. vertex3DList.add(new Vector3d(coordinate2));
  287. vertex3DList.add(new Vector3d(coordinate3));
  288. vertex3DList.add(new Vector3d(coordinate2)); //2つめの三角形
  289. vertex3DList.add(new Vector3d(coordinate4));
  290. vertex3DList.add(new Vector3d(coordinate3));
  291. index += 2;
  292. }
  293. }
  294. } else if (g instanceof IndexedTriangleFanArray) {
  295. // IndexedTriangleFanArray の場合
  296. IndexedTriangleFanArray triFanAttay = (IndexedTriangleFanArray)g;
  297. int stripVertexCounts[] = new int[triFanAttay.getNumStrips()];
  298. triFanAttay.getStripIndexCounts(stripVertexCounts);
  299. // 全頂点を3D上の頂点をvertex3DListに入れていく
  300. int index = 0;
  301. double coordinate2[] = new double[3];
  302. double coordinate3[] = new double[3];
  303. double coordinate4[] = null;
  304. for (int i = 0; i < triFanAttay.getNumStrips(); i++) {
  305. triFanAttay.getCoordinates(triFanAttay.getCoordinateIndex(index), coordinate1); // 中心点
  306. triFanAttay.getCoordinates(triFanAttay.getCoordinateIndex(index+1), coordinate2);
  307. index += 2;
  308. for (int j = 2; j < stripVertexCounts[i]; j++) {
  309. triFanAttay.getCoordinates(triFanAttay.getCoordinateIndex(index), coordinate3);
  310. vertex3DList.add(new Vector3d(coordinate1));
  311. vertex3DList.add(new Vector3d(coordinate2));
  312. vertex3DList.add(new Vector3d(coordinate3));
  313. coordinate4 = coordinate2;
  314. coordinate2 = coordinate3;
  315. coordinate3 = coordinate4;
  316. index++;
  317. }
  318. }
  319. } else if (g instanceof TriangleFanArray) {
  320. // TriangleFanArray の場合
  321. TriangleFanArray triFanAttay = (TriangleFanArray)g;
  322. int stripVertexCounts[] = new int[triFanAttay.getNumStrips()];
  323. triFanAttay.getStripVertexCounts(stripVertexCounts);
  324. // 全頂点を3D上の頂点をvertex3DListに入れていく
  325. int index = 0;
  326. double coordinate2[] = new double[3];
  327. double coordinate3[] = new double[3];
  328. double coordinate4[] = null;
  329. for (int i = 0; i < triFanAttay.getNumStrips(); i++) {
  330. triFanAttay.getCoordinates(index, coordinate1); // 中心点
  331. triFanAttay.getCoordinates(index + 1, coordinate2);
  332. index += 2;
  333. for (int j = 2; j < stripVertexCounts[i]; j++) {
  334. triFanAttay.getCoordinates(index, coordinate3);
  335. vertex3DList.add(new Vector3d(coordinate1));
  336. vertex3DList.add(new Vector3d(coordinate2));
  337. vertex3DList.add(new Vector3d(coordinate3));
  338. coordinate4 = coordinate2;
  339. coordinate2 = coordinate3;
  340. coordinate3 = coordinate4;
  341. index++;
  342. }
  343. }
  344. } else {
  345. // QuadArray系等は未対応
  346. return null;
  347. }
  348. return vertex3DList;
  349. }
  350.  
  351. protected BoundingPolytope createBoundingPolytope(Vector3d vertex1,
  352. Vector3d vertex2, Vector3d vertex3) {
  353. Vector3d v1 = new Vector3d();
  354. Vector3d v2 = new Vector3d();
  355. Vector3d v3 = new Vector3d();
  356. Vector3d v4 = new Vector3d();
  357. Vector3d v5 = new Vector3d();
  358. Vector3d v6 = new Vector3d();
  359. Vector3d cv1 = new Vector3d();
  360. Vector3d cv2 = new Vector3d();
  361. cv1.sub(vertex3, vertex1);
  362. cv2.sub(vertex2, vertex1);
  363. Vector3d cv = new Vector3d();
  364. cv.cross(cv1, cv2);
  365. cv.normalize();
  366. cv.scale(0.01);
  367. v1.set(vertex1);
  368. v2.set(vertex2);
  369. v3.set(vertex3);
  370. v4.set(vertex1);
  371. v4.add(cv);
  372. v5.set(vertex2);
  373. v5.add(cv);
  374. v6.set(vertex3);
  375. v6.add(cv);
  376.  
  377. Vector3d pv1 = new Vector3d();
  378. Vector3d pv2 = new Vector3d();
  379. Vector3d pv3 = new Vector3d();
  380. Vector3d pn = new Vector3d();
  381. Vector4d[] plane = new Vector4d[5];
  382.  
  383. // 0
  384. pv1 = v1;
  385. pv2.sub(v2, v1);
  386. pv3.sub(v3, v1);
  387.  
  388. pn.cross(pv2, pv3);
  389. pn.normalize();
  390. plane[0] = new Vector4d(pn.x, pn.y, pn.z, -pn.dot(pv1));
  391.  
  392. // 1
  393. pv1 = v1;
  394. pv2.sub(v4, v1);
  395. pv3.sub(v2, v1);
  396.  
  397. pn.cross(pv2, pv3);
  398. pn.normalize();
  399. plane[1] = new Vector4d(pn.x, pn.y, pn.z, -pn.dot(pv1));
  400.  
  401. // 2
  402. pv1 = v1;
  403. pv2.sub(v3, v1);
  404. pv3.sub(v4, v1);
  405.  
  406. pn.cross(pv2, pv3);
  407. pn.normalize();
  408. plane[2] = new Vector4d(pn.x, pn.y, pn.z, -pn.dot(pv1));
  409.  
  410. // 3
  411. pv1 = v6;
  412. pv2.sub(v3, v6);
  413. pv3.sub(v5, v6);
  414.  
  415. pn.cross(pv2, pv3);
  416. pn.normalize();
  417. plane[3] = new Vector4d(pn.x, pn.y, pn.z, -pn.dot(pv1));
  418.  
  419. // 4
  420. pv1 = v6;
  421. pv2.sub(v5, v6);
  422. pv3.sub(v4, v6);
  423.  
  424. pn.cross(pv2, pv3);
  425. pn.normalize();
  426. plane[4] = new Vector4d(pn.x, pn.y, pn.z, -pn.dot(pv1));
  427.  
  428. return new BoundingPolytope(plane);
  429. }
  430.  
  431. public void createShadowVolume(ArrayList<Light> lights, double shadowDepth, Transform3D localToWorld) {
  432. for (int n = 0; n < lights.size(); n++) {
  433. shadowVolumes.add(new ShadowVolume(this, lights.get(n), shadowDepth, localToWorld));
  434. }
  435. }
  436.  
  437. public void updateShadowVolume(Transform3D localToWorld) {
  438. for (int n = 0; n < shadowVolumes.size(); n++) {
  439. shadowVolumes.get(n).update(localToWorld);
  440. }
  441. }
  442. public void setBumpMapping(BumpMapGenerator g) {
  443. bumpMapGenerator = g;
  444. bBumpMapApplied = true;
  445. }
  446. public BumpMapGenerator getBumpMappingInfo() {
  447. return bumpMapGenerator;
  448. }
  449. public boolean isBumpMappingApplied() {
  450. return bBumpMapApplied;
  451. }
  452. public void setReflectionMapping(ReflectionMapGenerator g) {
  453. reflectionMapGenerator = g;
  454. bReflectionMapApplied = true;
  455. }
  456. public ReflectionMapGenerator getReflectionMappingInfo() {
  457. return reflectionMapGenerator;
  458. }
  459. public boolean isReflectionMappingApplied() {
  460. return bReflectionMapApplied;
  461. }
  462. public boolean hasAppearancePrepared() {
  463. if (bumpMapGenerator != null && !bumpMapGenerator.hasMapped()) return false;
  464. if (reflectionMapGenerator != null && !reflectionMapGenerator.hasMapped()) return false;
  465. return true;
  466. }
  467. }