Hacky Sculpt Previewer
Jump to navigation
Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.
/** * First attempt at a sculpt previewer * Adapted from Sun's ObjLoad * BSD license (inherited) * */ /** * Original Yumi Murakami. * 6-5-2007 Strife Onizuka: * Fixed centering of object and wrapping around when * downsampling. * 6-5-2007 Yumi Murakami * Use system native UI, attempted to get shading to work. * Now generates surface normals and installs Materials, both * of which are required for shading - but shading still does * not work :( * */ import java.awt.GraphicsConfiguration; import java.awt.image.BufferedImage; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import javax.imageio.*; import javax.imageio.stream.ImageInputStream; import javax.media.j3d.*; import javax.swing.JFileChooser; import javax.swing.JOptionPane; import javax.swing.UIManager; import javax.swing.filechooser.FileNameExtensionFilter; import javax.vecmath.*; import com.sun.j3d.loaders.IncorrectFormatException; import com.sun.j3d.loaders.ParsingErrorException; import com.sun.j3d.loaders.Scene; import com.sun.j3d.loaders.objectfile.ObjectFile; import com.sun.j3d.utils.behaviors.vp.*; import com.sun.j3d.utils.geometry.*; import com.sun.j3d.utils.universe.*; public class SculptPreview extends javax.swing.JFrame { private boolean left_right = true; private boolean top_bottom = false; private boolean spin = false; private boolean noTriangulate = false; private boolean noStripify = false; private double creaseAngle = 60.0; private URL filename = null; private SimpleUniverse univ = null; private BranchGroup scene = null; double[] RGBtoVertex(int RGB) { int blue = RGB & 255; int green = (RGB >> 8) & 255; int red = (RGB >> 16) & 255; double[] result = new double[3]; result[0] = (((double)red) / 255.0) - 0.5; result[1] = (((double)green) / 255.0) - 0.5; result[2] = (((double)blue) / 255.0) - 0.5; return result; } public BranchGroup createSceneGraph() { // Create the root of the branch graph BranchGroup objRoot = new BranchGroup(); // Create a Transformgroup to scale all objects so they // appear in the scene. TransformGroup objScale = new TransformGroup(); Transform3D t3d = new Transform3D(); t3d.setScale(0.7); objScale.setTransform(t3d); objRoot.addChild(objScale); // Create the transform group node and initialize it to the // identity. Enable the TRANSFORM_WRITE capability so that // our behavior code can modify it at runtime. Add it to the // root of the subgraph. TransformGroup objTrans = new TransformGroup(); objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_READ); objScale.addChild(objTrans); Shape3D s = new Shape3D(); BufferedImage theImage = null; JFileChooser chooser = new JFileChooser(); FileNameExtensionFilter filter = new FileNameExtensionFilter("Supported Image Formats",ImageIO.getReaderFileSuffixes()); chooser.setFileFilter(filter); boolean ok = false; while (!ok) { int chooserResult = chooser.showOpenDialog(this); if (chooserResult == JFileChooser.CANCEL_OPTION) { System.exit(0); } ok = true; try { theImage = ImageIO.read(chooser.getSelectedFile()); } catch (IOException e) { JOptionPane.showMessageDialog(this,"An error occured opening the texture file:\n" + e.getMessage(),"File error",JOptionPane.ERROR_MESSAGE); System.out.println("Error opening sculpt texture file"); ok = false; } } int xStep, yStep; int width = theImage.getWidth(); int height = theImage.getHeight(); xStep = width / 64; yStep = height / 64; if (xStep < 1) xStep = 1; if (yStep < 1) yStep = 1; if ((xStep > 1) || (yStep > 1)) { JOptionPane.showMessageDialog(this,"Sculpt texture dimensions are " + width + "x" + height + ".\nMaximum detail level on Second Life to 64x64,\nso the extra pixel data is being wasted.","Texture Over Resolution",JOptionPane.WARNING_MESSAGE); } int xmax = width - (left_right?0:xStep); int ymax = height - (top_bottom?0:yStep); int vertices = (xmax/xStep) * (height/yStep); System.out.println(vertices); TriangleArray ta = new TriangleArray(vertices * 6,GeometryArray.COORDINATES); int x, y, r; r = 0; double[] bottom = new double[3]; double[] top = new double[3]; if(!top_bottom)//find the top center and bottom averages { r = 0; bottom[0] = bottom[1] = bottom[2] = top[0] = top[1] = top[2] = 0.0; for (x=0; x<width; x+=xStep) { double[] pb = RGBtoVertex(theImage.getRGB(x,0)); double[] pt = RGBtoVertex(theImage.getRGB(x,height - xStep)); bottom[0] += pb[0]; bottom[1] += pb[1]; bottom[2] += pb[2]; top[0] += pt[0]; top[1] += pt[1]; top[2] += pt[2]; } bottom[0] = (bottom[0] * xStep) / width; bottom[1] = (bottom[1] * xStep) / width; bottom[2] = (bottom[2] * xStep) / width; top[0] = (top[0] * xStep) / width; top[1] = (top[1] * xStep) / width; top[2] = (top[2] * xStep) / width; } for (x=0; x<xmax; x+=xStep) {//link left to right if(!top_bottom) { int BottomLeftRGB = theImage.getRGB(x,0); int BottomRightRGB = theImage.getRGB((x+xStep) % width,0); ta.setCoordinates(r,bottom); ta.setCoordinates(r+1,RGBtoVertex(BottomRightRGB)); ta.setCoordinates(r+2,RGBtoVertex(BottomLeftRGB)); r+=3; } for (y=0; y<ymax; y+=yStep) { int topLeftRGB = theImage.getRGB(x,y); int topRightRGB = theImage.getRGB((x+xStep) % width,y); int bottomLeftRGB = theImage.getRGB(x,(y+yStep) % height); int bottomRightRGB = theImage.getRGB((x+xStep) % width,(y+yStep) % height); // Top left triangle ta.setCoordinates(r,RGBtoVertex(topLeftRGB)); ta.setCoordinates(r+1,RGBtoVertex(topRightRGB)); ta.setCoordinates(r+2,RGBtoVertex(bottomLeftRGB)); // Bottom right triangle ta.setCoordinates(r+3,RGBtoVertex(topRightRGB)); ta.setCoordinates(r+4,RGBtoVertex(bottomRightRGB)); ta.setCoordinates(r+5,RGBtoVertex(bottomLeftRGB)); r+=6; } if(!top_bottom) { int TopLeftRGB = theImage.getRGB(x,ymax); int TopRightRGB = theImage.getRGB((x+xStep) % width,ymax); ta.setCoordinates(r,RGBtoVertex(TopLeftRGB)); ta.setCoordinates(r+1,RGBtoVertex(TopRightRGB)); ta.setCoordinates(r+2,top); r+=3; } } GeometryInfo info = new GeometryInfo(ta); NormalGenerator gen = new NormalGenerator(); gen.generateNormals(info); s.setGeometry(info.getIndexedGeometryArray()); Appearance app = new Appearance(); Material mat = new Material( new Color3f((float)0.0,(float)0.0,(float)0.0), // Ambient new Color3f((float)1.0,(float)1.0,(float)1.0), // Emissive new Color3f((float)0.5,(float)0.5,(float)0.5), // Diffuse new Color3f((float)1.0,(float)1.0,(float)1.0), // Specular (float)10.0 // Shiny ); // ); app.setMaterial(mat); s.setAppearance(app); objTrans.addChild(s); BoundingSphere bounds = new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0); if (spin) { Transform3D yAxis = new Transform3D(); Alpha rotationAlpha = new Alpha(-1, Alpha.INCREASING_ENABLE, 0, 0, 4000, 0, 0, 0, 0, 0); RotationInterpolator rotator = new RotationInterpolator(rotationAlpha, objTrans, yAxis, 0.0f, (float) Math.PI*2.0f); rotator.setSchedulingBounds(bounds); objTrans.addChild(rotator); } // Set up the background Color3f bgColor = new Color3f(0.05f, 0.05f, 0.5f); Background bgNode = new Background(bgColor); bgNode.setApplicationBounds(bounds); objRoot.addChild(bgNode); return objRoot; } private Canvas3D createUniverse() { // Get the preferred graphics configuration for the default screen GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration(); // Create a Canvas3D using the preferred configuration Canvas3D canvas3d = new Canvas3D(config); // Create simple universe with view branch univ = new SimpleUniverse(canvas3d); BoundingSphere bounds = new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0); // add mouse behaviors to the ViewingPlatform ViewingPlatform viewingPlatform = univ.getViewingPlatform(); PlatformGeometry pg = new PlatformGeometry(); // Set up the ambient light Color3f ambientColor = new Color3f(0.1f, 0.1f, 0.1f); AmbientLight ambientLightNode = new AmbientLight(ambientColor); ambientLightNode.setInfluencingBounds(bounds); pg.addChild(ambientLightNode); // Set up the directional lights Color3f light1Color = new Color3f(1.0f, 1.0f, 0.9f); Vector3f light1Direction = new Vector3f(1.0f, 1.0f, 1.0f); Color3f light2Color = new Color3f(1.0f, 1.0f, 1.0f); Vector3f light2Direction = new Vector3f(-1.0f, -1.0f, -1.0f); DirectionalLight light1 = new DirectionalLight(light1Color, light1Direction); light1.setInfluencingBounds(bounds); pg.addChild(light1); DirectionalLight light2 = new DirectionalLight(light2Color, light2Direction); light2.setInfluencingBounds(bounds); pg.addChild(light2); viewingPlatform.setPlatformGeometry( pg ); // This will move the ViewPlatform back a bit so the // objects in the scene can be viewed. viewingPlatform.setNominalViewingTransform(); if (!spin) { OrbitBehavior orbit = new OrbitBehavior(canvas3d, OrbitBehavior.REVERSE_ALL); orbit.setSchedulingBounds(bounds); viewingPlatform.setViewPlatformBehavior(orbit); } // Ensure at least 5 msec per frame (i.e., < 200Hz) univ.getViewer().getView().setMinimumFrameCycleTime(5); return canvas3d; } /** * Creates new form */ public SculptPreview(String args[]) { // Initialize the GUI components initComponents(); // Create Canvas3D and SimpleUniverse; add canvas to drawing panel Canvas3D c = createUniverse(); drawingPanel.add(c, java.awt.BorderLayout.CENTER); // Create the content branch and add it to the universe scene = createSceneGraph(); univ.addBranchGraph(scene); } // ---------------------------------------------------------------- /** This method is called from within the constructor to * initialize the form. * WARNING: Do NOT modify this code. The content of this method is * always regenerated by the Form Editor. */ // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents private void initComponents() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (Exception e) { System.out.println("Error setting UI!"); } drawingPanel = new javax.swing.JPanel(); setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); setTitle("SculptPreview"); drawingPanel.setLayout(new java.awt.BorderLayout()); drawingPanel.setPreferredSize(new java.awt.Dimension(700, 700)); getContentPane().add(drawingPanel, java.awt.BorderLayout.CENTER); pack(); }// </editor-fold>//GEN-END:initComponents /** * @param args the command line arguments */ public static void main(final String args[]) { java.awt.EventQueue.invokeLater(new Runnable() { public void run() { SculptPreview sp = new SculptPreview(args); sp.setVisible(true); } }); } // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JPanel drawingPanel; // End of variables declaration//GEN-END:variables }