📄 j3dutils.java
字号:
PickTool.setCapabilities(box, PickTool.INTERSECT_FULL); objTrans.addChild(box); return (box); } /** */ public static Shape3D addPolyhedron(PathIterator pIt, double distance, double thickness, Appearance ap, TransformGroup objTrans) { double height = thickness + distance; double [] coords = new double[6]; java.util.List<Point3d> topList = new ArrayList<Point3d>(); java.util.List<Point3d> bottomList = new ArrayList<Point3d>(); java.util.List<Shape3D> shapes = new ArrayList<Shape3D>(); while (!pIt.isDone()) { int type = pIt.currentSegment(coords); if (type == PathIterator.SEG_CLOSE) { int listLen = topList.size(); Point3d [] pts = new Point3d[listLen*2]; correctNormals(topList, bottomList); System.arraycopy(topList.toArray(), 0, pts, 0, listLen); System.arraycopy(bottomList.toArray(), 0, pts, listLen, listLen); int numFaces = listLen + 2; // contour + top + bottom int[] indices = new int[listLen*6]; int[] stripCounts = new int[numFaces]; int[] contourCount = new int[numFaces]; Arrays.fill(contourCount, 1); Arrays.fill(stripCounts, 4); stripCounts[0] = listLen; // top stripCounts[numFaces-1] = listLen; // bottom int count = 0; // Top face for (int i = 0; i < listLen; i++) indices[count++] = i; // Contour for (int i = 0; i < listLen; i++) { indices[count++] = i; indices[count++] = i + listLen; indices[count++] = (i+1)%listLen + listLen; indices[count++] = (i+1)%listLen; } // Bottom face for (int i = 0; i < listLen; i++) indices[count++] = (listLen-i)%listLen + listLen; GeometryInfo gi = new GeometryInfo(GeometryInfo.POLYGON_ARRAY); gi.setCoordinates(pts); gi.setCoordinateIndices(indices); gi.setStripCounts(stripCounts); gi.setContourCounts(contourCount); NormalGenerator ng = new NormalGenerator(); ng.setCreaseAngle ((float) Math.toRadians(30)); ng.generateNormals(gi); GeometryArray c = gi.getGeometryArray(); c.setCapability(GeometryArray.ALLOW_INTERSECT); Shape3D box = new Shape3D(c, ap); box.setCapability(Shape3D.ENABLE_PICK_REPORTING); box.setCapability(Node.ALLOW_LOCAL_TO_VWORLD_READ); box.setCapability(Shape3D.ALLOW_PICKABLE_READ); box.setCapability(Shape3D.ALLOW_APPEARANCE_READ); box.setCapability(Shape3D.ALLOW_APPEARANCE_WRITE); box.setCapability(Shape3D.ALLOW_BOUNDS_READ); PickTool.setCapabilities(box, PickTool.INTERSECT_FULL); objTrans.addChild(box); shapes.add(box); topList.clear(); bottomList.clear(); } else if (type == PathIterator.SEG_MOVETO || type == PathIterator.SEG_LINETO) { Point3d pt = new Point3d(coords[0], coords[1], distance); topList.add(pt); pt = new Point3d(coords[0], coords[1], height); bottomList.add(pt); } pIt.next(); } if (shapes.size()>1) System.out.println("Error: case not handled"); return shapes.get(0); } /** * Method to correct points sequence to obtain valid normals * @param topList * @param bottomList */ public static void correctNormals(List<Point3d> topList, List<Point3d> bottomList) { // Determining normal direction Point3d p0 = topList.get(0); Point3d p1 = new Point3d(topList.get(1)); p1.sub(p0); Point3d pn = new Point3d(topList.get(topList.size()-1)); pn.sub(p0); Vector3d aux = new Vector3d(); aux.cross(new Vector3d(p1), new Vector3d(pn)); // the other layer Point3d b0 = new Point3d(bottomList.get(0)); b0.sub(p0); // Now the dot product double dot = aux.dot(new Vector3d(b0)); if (dot > 0) // Invert sequence of points otherwise the normals will be wrong { Collections.reverse(topList); Collections.reverse(bottomList); } } /******************************************************************************************************* * DEMO SECTION *******************************************************************************************************/ /** * This class is @serial */ public static class ThreeDDemoKnot implements Serializable { private static final long serialVersionUID = -7059885190094183408L; float xValue; float yValue; float zValue; Vector3f translation; float scale; float heading; // Sets the camera's heading. This automatically modifies the target's position. float pitch; // Sets the camera's pitch in degrees. This automatically modifies the target's position. float bank; // Sets the camera's bank in degrees. The angle is relative to the horizon. double rotZ; double rotY; double rotX; Quat4f rotation;// public Shape3D shape; public ThreeDDemoKnot(double xValue, double yValue, double zValue, double scale, double heading, double pitch, double bank, double rotX, double rotY, double rotZ) { this.xValue = (float)xValue; this.yValue = (float)yValue; this.zValue = (float)zValue; this.scale = (float)scale; this.heading = (float)heading; this.pitch = (float)pitch; this.bank = (float)bank; this.rotZ = rotZ; this.rotX = rotX; this.rotY = rotY; } public ThreeDDemoKnot(double scale, Vector3f trans, Quat4f rot, Shape3D shape) { this.scale = (float)scale; this.translation = trans; this.rotation = rot;// this.shape = shape; } } /** * Method to generate each individual frame key for the interporlation * based on Poly information * @param ratio * @param knot * @return */ public static KBKeyFrame getNextKBKeyFrame(float ratio, ThreeDDemoKnot knot) { // Prepare spline keyframe data Vector3f pos = new Vector3f (knot.xValue+100, knot.yValue+100, knot.zValue); Point3f point = new Point3f (pos); // position Point3f scale = new Point3f(knot.scale, knot.scale, knot.scale); // uniform scale3D KBKeyFrame key = new KBKeyFrame(ratio, 0, point, knot.heading, knot.pitch, knot.bank, scale, 0.0f, 0.0f, 1.0f); return key; } public static TCBKeyFrame getNextTCBKeyFrame(float ratio, ThreeDDemoKnot knot) { // Prepare spline keyframe data Vector3f pos = knot.translation; // Initial translatio is not given as vector if (pos == null) pos = new Vector3f (knot.xValue, knot.yValue, knot.zValue); Point3f point = new Point3f (pos); // position Quat4f quat = knot.rotation; // Initial rotation not given as Quat4f if (quat == null) quat = createQuaternionFromEuler(knot.rotX, knot.rotY, knot.rotZ); Point3f scale = new Point3f(knot.scale, knot.scale, knot.scale); // uniform scale3D TCBKeyFrame key = new TCBKeyFrame(ratio, 0, point, quat, scale, 0.0f, 0.0f, 1.0f); return key; } /** * Convert an angular rotation about an axis to a Quaternion. * From Selman's book * @param axis * @param angle * @return */ private static Quat4f createQuaternionFromAxisAndAngle( Vector3d axis, double angle ) { double sin_a = Math.sin( angle / 2 ); double cos_a = Math.cos( angle / 2 ); // use a vector so we can call normalize Vector4f q = new Vector4f( ); q.x = (float) (axis.x * sin_a); q.y = (float) (axis.y * sin_a); q.z = (float) (axis.z * sin_a); q.w = (float) cos_a; // It is necessary to normalise the quaternion // in case any values are very close to zero. q.normalize( ); // convert to a Quat4f and return return new Quat4f( q ); } /** * Convert three rotations about the Euler axes to a Quaternion. * From Selman's book * @param angleX * @param angleY * @param angleZ * @return */ public static Quat4f createQuaternionFromEuler( double angleX, double angleY, double angleZ ) { // simply call createQuaternionFromAxisAndAngle // for each axis and multiply the results Quat4f qx = createQuaternionFromAxisAndAngle(J3DAxis.axisX, angleX); Quat4f qy = createQuaternionFromAxisAndAngle(J3DAxis.axisY, angleY); Quat4f qz = createQuaternionFromAxisAndAngle(J3DAxis.axisZ, angleZ); // qx = qx * qy qx.mul( qy ); // qx = qx * qz qx.mul( qz ); return qx; } /******************************************************************************************************* * Color Tab SECTION *******************************************************************************************************/ public static void get3DColorsInTab(Map<String,ColorPatternPanel.Info> transAndSpecialMap) { // 3D Stuff transAndSpecialMap.put("Special: 3D CELL INSTANCES", new ColorPatternPanel.Info(get3DColorInstanceCellPref())); transAndSpecialMap.put("Special: 3D HIGHLIGHTED INSTANCES", new ColorPatternPanel.Info(get3DColorHighlightedPref())); transAndSpecialMap.put("Special: 3D AMBIENT LIGHT", new ColorPatternPanel.Info(get3DColorAmbientLightPref())); transAndSpecialMap.put("Special: 3D DIRECTIONAL LIGHT", new ColorPatternPanel.Info(get3DColorDirectionalLightPref())); Pref[] colors = {cache3DColorAxisX, cache3DColorAxisY, cache3DColorAxisZ}; String[] axisNames = {" X", " Y", " Z"}; String name = "Special: 3D AXIS"; for (int i = 0; i < colors.length; i++) { String color3DName = name+axisNames[i]; transAndSpecialMap.put(color3DName, new ColorPatternPanel.Info(colors[i])); } } public static Boolean set3DColorsInTab(LayersTab tab) { int[] oldColors = get3DColorAxes(); int [] colors3D = {oldColors[0], oldColors[1], oldColors[2]}; boolean colorChanged = false; int c = -1; if ((c = tab.specialMapColor("Special: 3D CELL INSTANCES", get3DColorInstanceCell())) >= 0) { set3DColorInstanceCell(c); colorChanged = true; } if ((c = tab.specialMapColor("Special: 3D HIGHLIGHTED INSTANCES", get3DColorHighlighted())) >= 0) { set3DColorHighlighted(c); colorChanged = true; } if ((c = tab.specialMapColor("Special: 3D AMBIENT LIGHT", get3DColorAmbientLight())) >= 0) { set3DColorAmbientLight(c); colorChanged = true; } if ((c = tab.specialMapColor("Special: 3D DIRECTIONAL LIGHT", get3DColorDirectionalLight())) >= 0) { set3DColorDirectionalLight(c); colorChanged = true; } if ((c = tab.specialMapColor("Special: 3D AXIS X", cache3DColorAxisX.getInt())) >= 0) { colors3D[0] = c; colorChanged = true; } if ((c = tab.specialMapColor("Special: 3D AXIS Y", cache3DColorAxisY.getInt())) >= 0) { colors3D[1] = c; colorChanged = true; } if ((c = tab.specialMapColor("Special: 3D AXIS Z", cache3DColorAxisZ.getInt())) >= 0) { colors3D[2] = c; colorChanged = true; } if (colors3D[0] != oldColors[0] || colors3D[1] != oldColors[1] || colors3D[2] != oldColors[2]) { set3DColorAxes(colors3D); colorChanged = true; } return Boolean.valueOf(colorChanged); } /******************************************************************************************************* * IMAGE SECTION *******************************************************************************************************/ /** * Class to create offscreen from canvas 3D */ public static class OffScreenCanvas3D extends Canvas3D { public OffScreenCanvas3D(GraphicsConfiguration graphicsConfiguration, boolean offScreen) { super(graphicsConfiguration, offScreen); } BufferedImage doRender(int width, int height) { BufferedImage bImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); ImageComponent2D buffer = new ImageComponent2D(ImageComponent.FORMAT_RGBA, bImage); setOffScreenBuffer(buffer); renderOffScreenBuffer(); waitForOffScreenRendering(); bImage = getOffScreenBuffer().getImage(); return bImage; } public void postSwap() { // No-op since we always wait for off-screen rendering to complete } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -