* This example can only be run as an application as it uses a MenuBar which can * only be associated with a Frame (in AWT) */ public class AppearanceTest extends Java3dApplet { private static int m_kWidth = 400; private static int m_kHeight = 400; private Frame m_Frame = null; private Appearance m_Appearance = null; private AppearanceComponent[] m_ComponentArray = null; public AppearanceTest() { m_Appearance = new Appearance(); TextureComponent.setComponent(this); m_ComponentArray = new AppearanceComponent[] { new PolygonComponent(m_Appearance), new ColoringComponent(m_Appearance), new LineComponent(m_Appearance), new MaterialComponent(m_Appearance), new PointComponent(m_Appearance), new RenderingComponent(m_Appearance), new TransparencyComponent(m_Appearance), new TextureComponent(m_Appearance), new TextureAttributesComponent(m_Appearance), new TexGenComponent(m_Appearance) }; } protected void addCanvas3D(Canvas3D c3d) { if (m_Frame != null) { MenuBar menuBar = new MenuBar(); for (int n = 0; n < m_ComponentArray.length; n++) menuBar.add(m_ComponentArray[n].createMenu()); m_Frame.setMenuBar(menuBar); } setLayout(new BorderLayout()); add(c3d, BorderLayout.CENTER); doLayout(); } protected double getScale() { return 0.1; } protected BranchGroup createSceneBranchGroup() { BranchGroup objRoot = super.createSceneBranchGroup(); TransformGroup zoomTg = new TransformGroup(); zoomTg.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); zoomTg.setCapability(TransformGroup.ALLOW_TRANSFORM_READ); // attach a navigation behavior to the position of the viewer KeyNavigatorBehavior key = new KeyNavigatorBehavior(zoomTg); key.setSchedulingBounds(createApplicationBounds()); key.setEnable(true); objRoot.addChild(key); // create a TransformGroup to flip the hand onto its end and enlarge it. TransformGroup objTrans1 = new TransformGroup(); Transform3D tr = new Transform3D(); objTrans1.getTransform(tr); tr.setEuler(new Vector3d(0.5 * Math.PI, 0.6, 0)); objTrans1.setTransform(tr); // Set up the global lights Color3f lColor1 = new Color3f(0.7f, 0.7f, 0.7f); Vector3f lDir1 = new Vector3f(-1.0f, -1.0f, -1.0f); Color3f alColor = new Color3f(0.2f, 0.2f, 0.2f); AmbientLight aLgt = new AmbientLight(alColor); aLgt.setInfluencingBounds(getApplicationBounds()); DirectionalLight lgt1 = new DirectionalLight(lColor1, lDir1); lgt1.setInfluencingBounds(getApplicationBounds()); objRoot.addChild(aLgt); objRoot.addChild(lgt1); int nScale = 50; Box box = new Box(nScale, nScale, nScale, Primitive.GENERATE_NORMALS | Primitive.GENERATE_TEXTURE_COORDS, m_Appearance); Shape3D frontFace = box.getShape(Box.LEFT); // create a new left face so we can // assign per-vertex colors GeometryArray geometry = new QuadArray(4, GeometryArray.COORDINATES | GeometryArray.NORMALS | GeometryArray.COLOR_4 | GeometryArray.TEXTURE_COORDINATE_2); nScale = 40; final float[] verts = { // left face -1.0f * nScale, -1.0f * nScale, 1.0f * nScale, -1.0f * nScale, 1.0f * nScale, 1.0f * nScale, -1.0f * nScale, 1.0f * nScale, -1.0f * nScale, -1.0f * nScale, -1.0f * nScale, -1.0f * nScale }; final float[] colors = { // left face 1, 0, 0, 0, 0, 1, 0, 0.2f, 0, 0, 1, 0.8f, 0, 0, 0, 1, }; float[] tcoords = { // left 1, 0, 1, 1, 0, 1, 0, 0 }; Vector3f normalVector = new Vector3f(-1.0f, 0.0f, 0.0f); geometry.setColors(0, colors, 0, 4); for (int n = 0; n < 4; n++) geometry.setNormal(n, normalVector); geometry.setTextureCoordinates(0, tcoords, 0, 4); geometry.setCoordinates(0, verts); frontFace.setGeometry(geometry); // connect the scenegraph objTrans1.addChild(box); zoomTg.addChild(objTrans1); objRoot.addChild(zoomTg); return objRoot; } public static void main(String[] args) { AppearanceTest appearanceTest = new AppearanceTest(); appearanceTest.saveCommandLineArguments(args); Frame frame = (Frame) new MainFrame(appearanceTest, m_kWidth, m_kHeight); appearanceTest.m_Frame = frame; appearanceTest.initJava3d(); } } /******************************************************************************* * Copyright (C) 2001 Daniel Selman * * First distributed with the book "Java 3D Programming" by Daniel Selman and * published by Manning Publications. http://manning.com/selman * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation, version 2. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * The license can be found on the WWW at: http://www.fsf.org/copyleft/gpl.html * * Or by writing to: Free Software Foundation, Inc., 59 Temple Place - Suite * 330, Boston, MA 02111-1307, USA. * * Authors can be contacted at: Daniel Selman: daniel@selman.org * * If you make changes you think others would like, please contact one of the * authors or someone at the www.j3d.org web site. ******************************************************************************/ //***************************************************************************** /** * Java3dApplet * * Base class for defining a Java 3D applet. Contains some useful methods for * defining views and scenegraphs etc. * * @author Daniel Selman * @version 1.0 */ //***************************************************************************** abstract class Java3dApplet extends Applet { public static int m_kWidth = 300; public static int m_kHeight = 300; protected String[] m_szCommandLineArray = null; protected VirtualUniverse m_Universe = null; protected BranchGroup m_SceneBranchGroup = null; protected Bounds m_ApplicationBounds = null; // protected com.tornadolabs.j3dtree.Java3dTree m_Java3dTree = null; public Java3dApplet() { } public boolean isApplet() { try { System.getProperty("user.dir"); System.out.println("Running as Application."); return false; } catch (Exception e) { } System.out.println("Running as Applet."); return true; } public URL getWorkingDirectory() throws java.net.MalformedURLException { URL url = null; try { File file = new File(System.getProperty("user.dir")); System.out.println("Running as Application:"); System.out.println(" " + file.toURL()); return file.toURL(); } catch (Exception e) { } System.out.println("Running as Applet:"); System.out.println(" " + getCodeBase()); return getCodeBase(); } public VirtualUniverse getVirtualUniverse() { return m_Universe; } //public com.tornadolabs.j3dtree.Java3dTree getJ3dTree() { //return m_Java3dTree; // } public Locale getFirstLocale() { java.util.Enumeration e = m_Universe.getAllLocales(); if (e.hasMoreElements() != false) return (Locale) e.nextElement(); return null; } protected Bounds getApplicationBounds() { if (m_ApplicationBounds == null) m_ApplicationBounds = createApplicationBounds(); return m_ApplicationBounds; } protected Bounds createApplicationBounds() { m_ApplicationBounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0), 100.0); return m_ApplicationBounds; } protected Background createBackground() { Background back = new Background(new Color3f(0.9f, 0.9f, 0.9f)); back.setApplicationBounds(createApplicationBounds()); return back; } public void initJava3d() { // m_Java3dTree = new com.tornadolabs.j3dtree.Java3dTree(); m_Universe = createVirtualUniverse(); Locale locale = createLocale(m_Universe); BranchGroup sceneBranchGroup = createSceneBranchGroup(); ViewPlatform vp = createViewPlatform(); BranchGroup viewBranchGroup = createViewBranchGroup( getViewTransformGroupArray(), vp); createView(vp); Background background = createBackground(); if (background != null) sceneBranchGroup.addChild(background); // m_Java3dTree.recursiveApplyCapability(sceneBranchGroup); // m_Java3dTree.recursiveApplyCapability(viewBranchGroup); locale.addBranchGraph(sceneBranchGroup); addViewBranchGroup(locale, viewBranchGroup); onDoneInit(); } protected void onDoneInit() { // m_Java3dTree.updateNodes(m_Universe); } protected double getScale() { return 1.0; } public TransformGroup[] getViewTransformGroupArray() { TransformGroup[] tgArray = new TransformGroup[1]; tgArray[0] = new TransformGroup(); // move the camera BACK a little... // note that we have to invert the matrix as // we are moving the viewer Transform3D t3d = new Transform3D(); t3d.setScale(getScale()); t3d.setTranslation(new Vector3d(0.0, 0.0, -20.0)); t3d.invert(); tgArray[0].setTransform(t3d); return tgArray; } protected void addViewBranchGroup(Locale locale, BranchGroup bg) { locale.addBranchGraph(bg); } protected Locale createLocale(VirtualUniverse u) { return new Locale(u); } protected BranchGroup createSceneBranchGroup() { m_SceneBranchGroup = new BranchGroup(); return m_SceneBranchGroup; } protected View createView(ViewPlatform vp) { View view = new View(); PhysicalBody pb = createPhysicalBody(); PhysicalEnvironment pe = createPhysicalEnvironment(); AudioDevice audioDevice = createAudioDevice(pe); if (audioDevice != null) { pe.setAudioDevice(audioDevice); audioDevice.initialize(); } view.setPhysicalEnvironment(pe); view.setPhysicalBody(pb); if (vp != null) view.attachViewPlatform(vp); view.setBackClipDistance(getBackClipDistance()); view.setFrontClipDistance(getFrontClipDistance()); Canvas3D c3d = createCanvas3D(); view.addCanvas3D(c3d); addCanvas3D(c3d); return view; } protected PhysicalBody createPhysicalBody() { return new PhysicalBody(); } protected AudioDevice createAudioDevice(PhysicalEnvironment pe) { JavaSoundMixer javaSoundMixer = new JavaSoundMixer(pe); if (javaSoundMixer == null) System.out.println("create of audiodevice failed"); return javaSoundMixer; } protected PhysicalEnvironment createPhysicalEnvironment() { return new PhysicalEnvironment(); } protected float getViewPlatformActivationRadius() { return 100; } protected ViewPlatform createViewPlatform() { ViewPlatform vp = new ViewPlatform(); vp.setViewAttachPolicy(View.RELATIVE_TO_FIELD_OF_VIEW); vp.setActivationRadius(getViewPlatformActivationRadius()); return vp; } protected Canvas3D createCanvas3D() { GraphicsConfigTemplate3D gc3D = new GraphicsConfigTemplate3D(); gc3D.setSceneAntialiasing(GraphicsConfigTemplate.PREFERRED); GraphicsDevice gd[] = GraphicsEnvironment.getLocalGraphicsEnvironment() .getScreenDevices(); Canvas3D c3d = new Canvas3D(gd[0].getBestConfiguration(gc3D)); c3d.setSize(getCanvas3dWidth(c3d), getCanvas3dHeight(c3d)); return c3d; } protected int getCanvas3dWidth(Canvas3D c3d) { return m_kWidth; } protected int getCanvas3dHeight(Canvas3D c3d) { return m_kHeight; } protected double getBackClipDistance() { return 100.0; } protected double getFrontClipDistance() { return 1.0; } protected BranchGroup createViewBranchGroup(TransformGroup[] tgArray, ViewPlatform vp) { BranchGroup vpBranchGroup = new BranchGroup(); if (tgArray != null && tgArray.length > 0) { Group parentGroup = vpBranchGroup; TransformGroup curTg = null; for (int n = 0; n < tgArray.length; n++) { curTg = tgArray[n]; parentGroup.addChild(curTg); parentGroup = curTg; } tgArray[tgArray.length - 1].addChild(vp); } else vpBranchGroup.addChild(vp); return vpBranchGroup; } protected void addCanvas3D(Canvas3D c3d) { setLayout(new BorderLayout()); add(c3d, BorderLayout.CENTER); doLayout(); } protected VirtualUniverse createVirtualUniverse() { return new VirtualUniverse(); } protected void saveCommandLineArguments(String[] szArgs) { m_szCommandLineArray = szArgs; } protected String[] getCommandLineArguments() { return m_szCommandLineArray; } } class LineComponent extends AppearanceComponent { public LineComponent(Appearance app) { super(app); } protected int[] getCapabilities() { return new int[] { LineAttributes.ALLOW_ANTIALIASING_WRITE, LineAttributes.ALLOW_PATTERN_WRITE, LineAttributes.ALLOW_WIDTH_WRITE }; } protected NodeComponent createComponent() { return (NodeComponent) new LineAttributes(); } protected void setAppearanceCapability() { m_Appearance.setCapability(Appearance.ALLOW_LINE_ATTRIBUTES_WRITE); } protected void assignToAppearance() { m_Appearance.setLineAttributes((LineAttributes) m_NodeComponent); } protected void assignNullToAppearance() { m_Appearance.setLineAttributes(null); } protected String getName() { return "Line"; } protected String[] getMenuItemNames() { return new String[] { "-", "Antialiasing", "-", "On", "Off", "-", "Pattern", "-", "Dash", "DashDot", "Dot", "Solid", "-", "Width", "-", "1", "2", "5", "10" }; } private LineAttributes getLineAttributes() { return (LineAttributes) m_NodeComponent; } public void onOn() { getLineAttributes().setLineAntialiasingEnable(true); } public void onOff() { getLineAttributes().setLineAntialiasingEnable(false); } public void onDash() { getLineAttributes().setLinePattern(LineAttributes.PATTERN_DASH); } public void onDashDot() { getLineAttributes().setLinePattern(LineAttributes.PATTERN_DASH_DOT); } public void onDot() { getLineAttributes().setLinePattern(LineAttributes.PATTERN_DOT); } public void onSolid() { getLineAttributes().setLinePattern(LineAttributes.PATTERN_SOLID); } public void on1() { getLineAttributes().setLineWidth(1); } public void on2() { getLineAttributes().setLineWidth(2); } public void on5() { getLineAttributes().setLineWidth(5); } public void on10() { getLineAttributes().setLineWidth(10); } } class MaterialComponent extends AppearanceComponent { public MaterialComponent(Appearance app) { super(app); } protected int[] getCapabilities() { return new int[] { Material.ALLOW_COMPONENT_WRITE }; } protected NodeComponent createComponent() { return (NodeComponent) new Material(); } protected void setAppearanceCapability() { m_Appearance.setCapability(Appearance.ALLOW_MATERIAL_WRITE); } protected void assignToAppearance() { m_Appearance.setMaterial((Material) m_NodeComponent); } protected void assignNullToAppearance() { m_Appearance.setMaterial(null); } protected String getName() { return "Material"; } protected String[] getMenuItemNames() { return new String[] { "-", "Ambient", "-", "A_White", "A_Black", "A_Blue", "-", "Diffuse", "-", "D_White", "D_Black", "D_Blue", "-", "Emissive", "-", "E_White", "E_Black", "E_Blue", "-", "Specular", "-", "S_White", "S_Black", "S_Blue", "-", "Lighting", "-", "On", "Off", "-", "Shininess", "-", "1", "70", }; } private Material getMaterial() { return (Material) m_NodeComponent; } public void onA_White() { getMaterial().setAmbientColor(1, 1, 1); } public void onA_Black() { getMaterial().setAmbientColor(0, 0, 0); } public void onA_Blue() { getMaterial().setAmbientColor(0, 0, 1); } public void onE_White() { getMaterial().setEmissiveColor(1, 1, 1); } public void onE_Black() { getMaterial().setEmissiveColor(0, 0, 0); } public void onE_Blue() { getMaterial().setEmissiveColor(0, 0, 1); } public void onD_White() { getMaterial().setDiffuseColor(1, 1, 1); } public void onD_Black() { getMaterial().setDiffuseColor(0, 0, 0); } public void onD_Blue() { getMaterial().setDiffuseColor(0, 0, 1); } public void onS_White() { getMaterial().setSpecularColor(1, 1, 1); } public void onS_Black() { getMaterial().setSpecularColor(0, 0, 0); } public void onS_Blue() { getMaterial().setSpecularColor(0, 0, 1); } public void onOn() { getMaterial().setLightingEnable(true); } public void onOff() { getMaterial().setLightingEnable(false); } public void on1() { getMaterial().setShininess(1); } public void on70() { getMaterial().setShininess(70); } } class PointComponent extends AppearanceComponent { public PointComponent(Appearance app) { super(app); } protected int[] getCapabilities() { return new int[] { PointAttributes.ALLOW_ANTIALIASING_WRITE, PointAttributes.ALLOW_SIZE_WRITE }; } protected NodeComponent createComponent() { return (NodeComponent) new PointAttributes(); } protected void setAppearanceCapability() { m_Appearance.setCapability(Appearance.ALLOW_POINT_ATTRIBUTES_WRITE); } protected void assignToAppearance() { m_Appearance.setPointAttributes((PointAttributes) m_NodeComponent); } protected void assignNullToAppearance() { m_Appearance.setPointAttributes(null); } protected String getName() { return "Point"; } protected String[] getMenuItemNames() { return new String[] { "-", "Antialiasing", "-", "On", "Off", "-", "Size", "-", "1", "5", "10" }; } private PointAttributes getPointAttributes() { return (PointAttributes) m_NodeComponent; } public void onOn() { getPointAttributes().setPointAntialiasingEnable(true); } public void onOff() { getPointAttributes().setPointAntialiasingEnable(false); } public void on1() { getPointAttributes().setPointSize(1); } public void on5() { getPointAttributes().setPointSize(5); } public void on10() { getPointAttributes().setPointSize(10); } } class PolygonComponent extends AppearanceComponent { public PolygonComponent(Appearance app) { super(app); } protected int[] getCapabilities() { return new int[] { PolygonAttributes.ALLOW_CULL_FACE_WRITE, PolygonAttributes.ALLOW_MODE_WRITE, PolygonAttributes.ALLOW_NORMAL_FLIP_WRITE, PolygonAttributes.ALLOW_OFFSET_WRITE }; } protected NodeComponent createComponent() { return (NodeComponent) new PolygonAttributes(); } protected void setAppearanceCapability() { m_Appearance.setCapability(Appearance.ALLOW_POLYGON_ATTRIBUTES_WRITE); } protected void assignToAppearance() { m_Appearance.setPolygonAttributes((PolygonAttributes) m_NodeComponent); } protected void assignNullToAppearance() { m_Appearance.setPolygonAttributes(null); } protected String getName() { return "Polygon"; } protected String[] getMenuItemNames() { return new String[] { "-", "Cull", "-", "Back", "Front", "None", "-", "Mode", "-", "Fill", "Line", "Point", "-", "Normal", "-", "Flip_ON", "Flip_OFF", "-", "Offset", "-", "0", "10", "50", "200" }; } private PolygonAttributes getPolygonAttributes() { return (PolygonAttributes) m_NodeComponent; } public void onBack() { getPolygonAttributes().setCullFace(PolygonAttributes.CULL_BACK); } public void onFront() { getPolygonAttributes().setCullFace(PolygonAttributes.CULL_FRONT); } public void onNone() { getPolygonAttributes().setCullFace(PolygonAttributes.CULL_NONE); } public void onFill() { getPolygonAttributes().setPolygonMode(PolygonAttributes.POLYGON_FILL); } public void onLine() { getPolygonAttributes().setPolygonMode(PolygonAttributes.POLYGON_LINE); } public void onPoint() { getPolygonAttributes().setPolygonMode(PolygonAttributes.POLYGON_POINT); } public void onFlip_ON() { getPolygonAttributes().setBackFaceNormalFlip(true); } public void onFlip_OFF() { getPolygonAttributes().setBackFaceNormalFlip(false); } public void on0() { getPolygonAttributes().setPolygonOffset(0); } public void on10() { getPolygonAttributes().setPolygonOffset(10); } public void on50() { getPolygonAttributes().setPolygonOffset(50); } public void on200() { getPolygonAttributes().setPolygonOffset(200); } } class RenderingComponent extends AppearanceComponent { public RenderingComponent(Appearance app) { super(app); } protected int[] getCapabilities() { return new int[] { RenderingAttributes.ALLOW_ALPHA_TEST_FUNCTION_WRITE, RenderingAttributes.ALLOW_ALPHA_TEST_VALUE_WRITE, RenderingAttributes.ALLOW_DEPTH_ENABLE_READ }; } protected NodeComponent createComponent() { return (NodeComponent) new RenderingAttributes(); } protected void setAppearanceCapability() { m_Appearance.setCapability(Appearance.ALLOW_RENDERING_ATTRIBUTES_WRITE); } protected void assignToAppearance() { m_Appearance .setRenderingAttributes((RenderingAttributes) m_NodeComponent); } protected void assignNullToAppearance() { m_Appearance.setRenderingAttributes(null); } protected String getName() { return "Rendering"; } protected String[] getMenuItemNames() { return new String[] { "-", "AlphaTest", "-", "ALWAYS", "NEVER", "EQUAL", "NOT_EQUAL", "LESS", "LESS_OR_EQUAL", "GREATER", "GREATER_OR_EQUAL", "-", "AlphaTest Value", "-", "0", "0point5", "1", "-", "Depth Buffer", "-", "On", "Off", "-", "Depth Buffer Write", "-", "Enable", "Disable", }; } private RenderingAttributes getRenderingAttributes() { return (RenderingAttributes) m_NodeComponent; } public void onALWAYS() { getRenderingAttributes().setAlphaTestFunction( RenderingAttributes.ALWAYS); } public void onNEVER() { getRenderingAttributes() .setAlphaTestFunction(RenderingAttributes.NEVER); } public void onEQUAL() { getRenderingAttributes() .setAlphaTestFunction(RenderingAttributes.EQUAL); } public void onNOT_EQUAL() { getRenderingAttributes().setAlphaTestFunction( RenderingAttributes.NOT_EQUAL); } public void onLESS() { getRenderingAttributes().setAlphaTestFunction(RenderingAttributes.LESS); } public void onLESS_OR_EQUAL() { getRenderingAttributes().setAlphaTestFunction( RenderingAttributes.LESS_OR_EQUAL); } public void onGREATER() { getRenderingAttributes().setAlphaTestFunction( RenderingAttributes.GREATER); } public void onGREATER_OR_EQUAL() { getRenderingAttributes().setAlphaTestFunction( RenderingAttributes.GREATER_OR_EQUAL); } public void on0() { getRenderingAttributes().setAlphaTestValue(0); } public void on0point5() { getRenderingAttributes().setAlphaTestValue(0.5f); } public void on1() { getRenderingAttributes().setAlphaTestValue(1); } public void onOn() { getRenderingAttributes().setDepthBufferEnable(true); } public void onOff() { getRenderingAttributes().setDepthBufferEnable(false); } public void onEnable() { getRenderingAttributes().setDepthBufferWriteEnable(true); } public void onDisable() { getRenderingAttributes().setDepthBufferWriteEnable(false); } } class TexGenComponent extends AppearanceComponent { TexCoordGeneration m_TexCoordGeneration = null; final float m_PlaneFactor = 0.02f; public TexGenComponent(Appearance app) { super(app); } protected int[] getCapabilities() { return new int[] { TexCoordGeneration.ALLOW_ENABLE_WRITE }; } protected NodeComponent createComponent() { return (NodeComponent) new TexCoordGeneration( TexCoordGeneration.OBJECT_LINEAR, TexCoordGeneration.TEXTURE_COORDINATE_3); } protected void setAppearanceCapability() { m_Appearance.setCapability(Appearance.ALLOW_TEXGEN_WRITE); } protected void assignToAppearance() { m_TexCoordGeneration = new TexCoordGeneration(); m_TexCoordGeneration.duplicateNodeComponent(m_NodeComponent); m_Appearance.setTexCoordGeneration(m_TexCoordGeneration); } protected void assignNullToAppearance() { m_Appearance.setTexCoordGeneration(null); } protected String getName() { return "TexCoordGen"; } protected String[] getMenuItemNames() { return new String[] { "-", "Enable", "-", "On", "Off", "-", "GenMode", "-", "EYE_LINEAR", "OBJECT_LINEAR", "SPHERE_MAP", "-", "Format", "-", "TEXTURE_COORDINATE_2", "TEXTURE_COORDINATE_3", "-", "Plane R", "-", "R_1_0_0_0", "R_0_1_0_5", "R_0_0_1_0", "R_0_0_0_1", "-", "Plane S", "-", "S_1_0_0_0", "S_0_1_0_5", "S_0_0_1_0", "S_0_0_0_1", "-", "Plane T", "-", "T_1_0_0_0", "T_0_1_0_5", "T_0_0_1_0", "T_0_0_0_1", }; } private TexCoordGeneration getTexCoordGeneration() { return (TexCoordGeneration) m_NodeComponent; } public void onOn() { getTexCoordGeneration().setEnable(true); assignToAppearance(); } public void onOff() { getTexCoordGeneration().setEnable(false); assignToAppearance(); } public void onEYE_LINEAR() { getTexCoordGeneration().setGenMode(TexCoordGeneration.EYE_LINEAR); assignToAppearance(); } public void onOBJECT_LINEAR() { getTexCoordGeneration().setGenMode(TexCoordGeneration.OBJECT_LINEAR); assignToAppearance(); } public void onSPHERE_MAP() { getTexCoordGeneration().setGenMode(TexCoordGeneration.SPHERE_MAP); assignToAppearance(); } public void onTEXTURE_COORDINATE_2() { getTexCoordGeneration().setFormat( TexCoordGeneration.TEXTURE_COORDINATE_2); assignToAppearance(); } public void onTEXTURE_COORDINATE_3() { getTexCoordGeneration().setFormat( TexCoordGeneration.TEXTURE_COORDINATE_3); assignToAppearance(); } public void onR_1_0_0_0() { getTexCoordGeneration().setPlaneR(new Vector4f(m_PlaneFactor, 0, 0, 0)); assignToAppearance(); } public void onR_0_1_0_5() { getTexCoordGeneration().setPlaneR( new Vector4f(0, m_PlaneFactor, 0, 0.5f)); assignToAppearance(); } public void onR_0_0_1_0() { getTexCoordGeneration().setPlaneR(new Vector4f(0, 0, m_PlaneFactor, 0)); assignToAppearance(); } public void onR_0_0_0_1() { getTexCoordGeneration().setPlaneR(new Vector4f(0, 0, 0, m_PlaneFactor)); assignToAppearance(); } public void onS_1_0_0_0() { getTexCoordGeneration().setPlaneS(new Vector4f(m_PlaneFactor, 0, 0, 0)); assignToAppearance(); } public void onS_0_1_0_5() { getTexCoordGeneration().setPlaneS( new Vector4f(0, m_PlaneFactor, 0, 0.5f)); assignToAppearance(); } public void onS_0_0_1_0() { getTexCoordGeneration().setPlaneS(new Vector4f(0, 0, m_PlaneFactor, 0)); assignToAppearance(); } public void onS_0_0_0_1() { getTexCoordGeneration().setPlaneS(new Vector4f(0, 0, 0, m_PlaneFactor)); assignToAppearance(); } public void onT_1_0_0_0() { getTexCoordGeneration().setPlaneT(new Vector4f(m_PlaneFactor, 0, 0, 0)); assignToAppearance(); } public void onT_0_1_0_5() { getTexCoordGeneration().setPlaneT( new Vector4f(0, m_PlaneFactor, 0, 0.5f)); assignToAppearance(); } public void onT_0_0_1_0() { getTexCoordGeneration().setPlaneT(new Vector4f(0, 0, m_PlaneFactor, 0)); assignToAppearance(); } public void onT_0_0_0_1() { getTexCoordGeneration().setPlaneT(new Vector4f(0, 0, 0, m_PlaneFactor)); assignToAppearance(); } } class TextureAttributesComponent extends AppearanceComponent { public TextureAttributesComponent(Appearance app) { super(app); } protected int[] getCapabilities() { return new int[] { TextureAttributes.ALLOW_BLEND_COLOR_WRITE, TextureAttributes.ALLOW_MODE_WRITE, TextureAttributes.ALLOW_TRANSFORM_WRITE, }; } protected NodeComponent createComponent() { return (NodeComponent) new TextureAttributes(); } protected void setAppearanceCapability() { m_Appearance.setCapability(Appearance.ALLOW_TEXTURE_ATTRIBUTES_WRITE); } protected void assignToAppearance() { m_Appearance.setTextureAttributes((TextureAttributes) m_NodeComponent); } protected void assignNullToAppearance() { m_Appearance.setTextureAttributes(null); } protected String getName() { return "TextureAttributes"; } protected String[] getMenuItemNames() { return new String[] { "-", "Mode", "-", "MODULATE", "DECAL", "BLEND", "REPLACE", "-", "Blend Color", "-", "T_White_Alpha_0point3", "T_Black_Alpha_0point7", "T_Blue_Alpha_1", "-", "Transform", "-", "0_degrees", "X_30_degrees", "Y_30_degrees", "Z_30_degrees", "-", "Perspective Correction", "-", "NICEST", "FASTEST" }; } private TextureAttributes getTextureAttributes() { return (TextureAttributes) m_NodeComponent; } public void onMODULATE() { getTextureAttributes().setTextureMode(TextureAttributes.MODULATE); } public void onDECAL() { getTextureAttributes().setTextureMode(TextureAttributes.DECAL); } public void onBLEND() { getTextureAttributes().setTextureMode(TextureAttributes.BLEND); } public void onREPLACE() { getTextureAttributes().setTextureMode(TextureAttributes.REPLACE); } public void onT_White_Alpha_0point3() { getTextureAttributes().setTextureBlendColor(1, 1, 1, 0.3f); } public void onT_Black_Alpha_0point7() { getTextureAttributes().setTextureBlendColor(0, 0, 0, 0.7f); } public void onT_Blue_Alpha_1() { getTextureAttributes().setTextureBlendColor(0, 0, 1, 1); } public void on0_degrees() { Transform3D t3d = new Transform3D(); getTextureAttributes().setTextureTransform(t3d); } public void onX_30_degrees() { Transform3D t3d = new Transform3D(); t3d.rotX(Math.toRadians(30)); getTextureAttributes().setTextureTransform(t3d); } public void onY_30_degrees() { Transform3D t3d = new Transform3D(); t3d.rotY(Math.toRadians(30)); getTextureAttributes().setTextureTransform(t3d); } public void onZ_30_degrees() { Transform3D t3d = new Transform3D(); t3d.rotZ(Math.toRadians(30)); getTextureAttributes().setTextureTransform(t3d); } public void onNICEST() { getTextureAttributes().setPerspectiveCorrectionMode( TextureAttributes.NICEST); } public void onFASTEST() { getTextureAttributes().setPerspectiveCorrectionMode( TextureAttributes.FASTEST); } } class TextureComponent extends AppearanceComponent { // hack, so we have an image observer when we load Textures public static Component m_Component = null; private Texture m_Texture = null; public TextureComponent(Appearance app) { super(app); } public static void setComponent(Component comp) { m_Component = comp; } protected int[] getCapabilities() { return new int[] { Texture.ALLOW_ENABLE_WRITE, }; } protected NodeComponent createComponent() { TextureLoader texLoader = new TextureLoader("texture00.jpg", m_Component); ImageComponent2D image = texLoader.getImage(); Texture2D tex2D = new Texture2D(Texture.MULTI_LEVEL_MIPMAP, Texture.RGBA, image.getWidth(), image.getHeight()); for (int n = 0; n <= 6; n++) { texLoader = new TextureLoader("texture0" + n + ".jpg", m_Component); tex2D.setImage(n, texLoader.getImage()); } return (NodeComponent) tex2D; } protected void setAppearanceCapability() { m_Appearance.setCapability(Appearance.ALLOW_TEXTURE_WRITE); } protected void assignToAppearance() { m_Texture = (Texture) new Texture2D(); m_Texture = (Texture) m_NodeComponent.cloneNodeComponent(true); m_Appearance.setTexture(m_Texture); } protected void assignNullToAppearance() { m_Appearance.setTexture(null); } protected String getName() { return "Texture"; } protected String[] getMenuItemNames() { return new String[] { "-", "Boundary Color", "-", "White", "Black", "BlueTransparent", "-", "Boundary Mode S", "-", "S_CLAMP", "S_WRAP", "-", "Boundary Mode T", "-", "T_CLAMP", "T_WRAP", "-", "Enable", "-", "On", "Off", "-", "Image", "-", "Texture0", "Texture1", "Texture2", "-", "MagFilter", "-", "Mag_FASTEST", "Mag_NICEST", "Mag_BASE_LEVEL_POINT", "Mag_BASE_LEVEL_LINEAR", "-", "MinFilter", "-", "Min_FASTEST", "Min_NICEST", "Min_BASE_LEVEL_POINT", "Min_BASE_LEVEL_LINEAR", "Min_MULTI_LEVEL_POINT", "Min_MULTI_LEVEL_LINEAR", "-", "MipMap Mode", "-", "BASE_LEVEL", "MULTI_LEVEL_MIPMAP", }; } private Texture getTexture() { return (Texture) m_NodeComponent; } public void onWhite() { getTexture().setBoundaryColor(1, 1, 1, 0); assignToAppearance(); } public void onBlack() { getTexture().setBoundaryColor(0, 0, 0, 0); assignToAppearance(); } public void onBlueTransparent() { getTexture().setBoundaryColor(0, 0, 1, 0.5f); assignToAppearance(); } public void onS_CLAMP() { getTexture().setBoundaryModeS(Texture.CLAMP); assignToAppearance(); } public void onS_WRAP() { getTexture().setBoundaryModeS(Texture.WRAP); assignToAppearance(); } public void onT_CLAMP() { getTexture().setBoundaryModeT(Texture.CLAMP); assignToAppearance(); } public void onT_WRAP() { getTexture().setBoundaryModeT(Texture.WRAP); assignToAppearance(); } public void onOn() { getTexture().setEnable(true); assignToAppearance(); } public void onOff() { getTexture().setEnable(false); assignToAppearance(); } public void onTexture0() { TextureLoader texLoader = null; for (int n = 0; n <= 6; n++) { texLoader = new TextureLoader("texture0" + n + ".jpg", m_Component); getTexture().setImage(n, texLoader.getImage()); } assignToAppearance(); } public void onTexture1() { TextureLoader texLoader = null; for (int n = 0; n <= 6; n++) { texLoader = new TextureLoader("texture1" + n + ".jpg", m_Component); getTexture().setImage(n, texLoader.getImage()); } assignToAppearance(); } public void onTexture2() { TextureLoader texLoader = null; for (int n = 0; n <= 6; n++) { texLoader = new TextureLoader("texture2" + n + ".gif", m_Component); getTexture().setImage(n, texLoader.getImage()); } assignToAppearance(); } public void onMag_FASTEST() { getTexture().setMagFilter(Texture.FASTEST); assignToAppearance(); } public void onMag_NICEST() { getTexture().setMagFilter(Texture.NICEST); assignToAppearance(); } public void onMag_BASE_LEVEL_POINT() { getTexture().setMagFilter(Texture.BASE_LEVEL_POINT); assignToAppearance(); } public void onMag_BASE_LEVEL_LINEAR() { getTexture().setMagFilter(Texture.BASE_LEVEL_LINEAR); assignToAppearance(); } public void onMin_FASTEST() { getTexture().setMinFilter(Texture.FASTEST); assignToAppearance(); } public void onMin_NICEST() { getTexture().setMinFilter(Texture.NICEST); assignToAppearance(); } public void onMin_BASE_LEVEL_POINT() { getTexture().setMinFilter(Texture.BASE_LEVEL_POINT); assignToAppearance(); } public void onMin_BASE_LEVEL_LINEAR() { getTexture().setMinFilter(Texture.BASE_LEVEL_LINEAR); assignToAppearance(); } public void onMin_MULTI_LEVEL_POINT() { getTexture().setMinFilter(Texture.MULTI_LEVEL_POINT); assignToAppearance(); } public void onMin_MULTI_LEVEL_LINEAR() { getTexture().setMinFilter(Texture.MULTI_LEVEL_LINEAR); assignToAppearance(); } public void onBASE_LEVEL() { getTexture().setMipMapMode(Texture.BASE_LEVEL); assignToAppearance(); } public void onMULTI_LEVEL_MIPMAP() { getTexture().setMipMapMode(Texture.MULTI_LEVEL_MIPMAP); assignToAppearance(); } } class TransparencyComponent extends AppearanceComponent { public TransparencyComponent(Appearance app) { super(app); } protected int[] getCapabilities() { return new int[] { TransparencyAttributes.ALLOW_MODE_WRITE, TransparencyAttributes.ALLOW_VALUE_WRITE }; } protected NodeComponent createComponent() { return (NodeComponent) new TransparencyAttributes(); } protected void setAppearanceCapability() { m_Appearance .setCapability(Appearance.ALLOW_TRANSPARENCY_ATTRIBUTES_WRITE); } protected void assignToAppearance() { m_Appearance .setTransparencyAttributes((TransparencyAttributes) m_NodeComponent); } protected void assignNullToAppearance() { m_Appearance.setTransparencyAttributes(null); } protected String getName() { return "Transparency"; } protected String[] getMenuItemNames() { return new String[] { "-", "Transparency", "-", "0", "0point2", "0point5", "0point8", "1", "-", "Mode", "-", "NONE", "FASTEST", "NICEST", "SCREEN_DOOR", "BLENDED" }; } private TransparencyAttributes getTransparencyAttributes() { return (TransparencyAttributes) m_NodeComponent; } public void on0() { getTransparencyAttributes().setTransparency(0); } public void on0point2() { getTransparencyAttributes().setTransparency(0.2f); } public void on0point5() { getTransparencyAttributes().setTransparency(0.5f); } public void on0point8() { getTransparencyAttributes().setTransparency(0.8f); } public void on1() { getTransparencyAttributes().setTransparency(1); } public void onNONE() { getTransparencyAttributes().setTransparencyMode( TransparencyAttributes.NONE); } public void onFASTEST() { getTransparencyAttributes().setTransparencyMode( TransparencyAttributes.FASTEST); } public void onNICEST() { getTransparencyAttributes().setTransparencyMode( TransparencyAttributes.NICEST); } public void onSCREEN_DOOR() { getTransparencyAttributes().setTransparencyMode( TransparencyAttributes.SCREEN_DOOR); } public void onBLENDED() { getTransparencyAttributes().setTransparencyMode( TransparencyAttributes.BLENDED); } } abstract class AppearanceComponent implements ActionListener { protected NodeComponent m_NodeComponent = null; protected Appearance m_Appearance = null; public AppearanceComponent(Appearance app) { m_Appearance = app; m_NodeComponent = createComponent(); int[] capsArray = getCapabilities(); if (capsArray != null) { for (int n = 0; n < capsArray.length; n++) m_NodeComponent.setCapability(capsArray[n]); } setAppearanceCapability(); assignToAppearance(); } abstract protected int[] getCapabilities(); abstract protected void setAppearanceCapability(); abstract protected NodeComponent createComponent(); abstract protected void assignToAppearance(); abstract protected void assignNullToAppearance(); abstract protected String getName(); abstract protected String[] getMenuItemNames(); public Menu createMenu() { String szName = getName(); String[] itemArray = getMenuItemNames(); ActionListener listener = this; Menu menu = new Menu(szName); MenuItem menuItem = new MenuItem("Null"); menuItem.addActionListener(listener); menu.add(menuItem); menuItem = new MenuItem("Non_Null"); menuItem.addActionListener(listener); menu.add(menuItem); for (int n = 0; n < itemArray.length; n++) { menuItem = new MenuItem(itemArray[n]); menuItem.addActionListener(listener); menu.add(menuItem); } return menu; } public void onNull() { assignNullToAppearance(); } public void onNon_Null() { assignToAppearance(); } public void actionPerformed(ActionEvent event) { // (primitive) menu command dispatch Class classObject = getClass(); Method[] methodArray = classObject.getMethods(); for (int n = methodArray.length - 1; n >= 0; n--) { if (("on" + event.getActionCommand()).equals(methodArray[n] .getName())) { try { methodArray[n].invoke(this, null); } catch (InvocationTargetException ie) { System.err .println("Warning. Menu handler threw exception: " + ie.getTargetException()); } catch (Exception e) { System.err .println("Warning. Menu dispatch exception: " + e); } return; } } } } class ColoringComponent extends AppearanceComponent { public ColoringComponent(Appearance app) { super(app); } protected int[] getCapabilities() { return new int[] { ColoringAttributes.ALLOW_COLOR_WRITE, ColoringAttributes.ALLOW_SHADE_MODEL_WRITE }; } protected NodeComponent createComponent() { return (NodeComponent) new ColoringAttributes(); } protected void setAppearanceCapability() { m_Appearance.setCapability(Appearance.ALLOW_COLORING_ATTRIBUTES_WRITE); } protected void assignToAppearance() { m_Appearance .setColoringAttributes((ColoringAttributes) m_NodeComponent); } protected void assignNullToAppearance() { m_Appearance.setColoringAttributes(null); } protected String getName() { return "Coloring"; } protected String[] getMenuItemNames() { return new String[] { "-", "Color", "-", "Red", "Green", "Blue", "-", "Shade Model", "-", "Fastest", "Nicest", "Flat", "Gouraud" }; } private ColoringAttributes getColoringAttributes() { return (ColoringAttributes) m_NodeComponent; } public void onRed() { getColoringAttributes().setColor(1, 0, 0); } public void onGreen() { getColoringAttributes().setColor(0, 1, 0); } public void onBlue() { getColoringAttributes().setColor(0, 0, 1); } public void onFastest() { getColoringAttributes().setShadeModel(ColoringAttributes.FASTEST); } public void onNicest() { getColoringAttributes().setShadeModel(ColoringAttributes.NICEST); } public void onFlat() { getColoringAttributes().setShadeModel(ColoringAttributes.SHADE_FLAT); } public void onGouraud() { getColoringAttributes().setShadeModel(ColoringAttributes.SHADE_GOURAUD); } } //File: hand1.obj /* # Mon Jun 02 17:09:33 1997 # # g hand1 v -0.551223 0.307562 -3.946050 v -0.215465 0.030475 -3.703516 v -0.059140 0.068255 -1.551531 v -0.487235 0.455792 -4.006029 v -0.168743 0.090975 -3.755638 v -0.338689 0.569450 -4.244848 v -0.639211 0.502297 -4.165243 v -0.760687 0.647871 -4.482797 v -0.529792 0.073768 -3.945949 v -0.707612 0.258064 -4.192451 v -0.866004 0.446161 -4.511733 v -0.367733 -0.147323 -4.191223 v -0.717413 0.071719 -4.433171 v -0.893823 0.253971 -4.589350 v -0.172976 -0.188212 -3.754734 v -0.089148 -0.103984 -1.450071 v -0.234491 -0.100206 -3.756646 v -0.131305 -0.032994 -1.531782 v -0.589492 0.641054 -4.376035 v -0.050594 -0.257375 -4.417058 v 0.208857 -0.205637 -4.768191 v 0.007882 -0.231806 -4.028160 v 0.230232 -0.186379 -4.335583 v 0.390435 -0.043258 -4.060836 v 0.002626 -0.129308 -1.430840 v -0.058465 -0.217994 -3.717670 v 0.087189 -0.100005 -1.425612 v 0.044163 -0.171797 -3.707954 v 0.044240 0.657156 -4.536777 v -0.137070 0.604272 -4.344090 v 0.041139 0.604901 -4.118776 v -0.080844 0.531805 -3.993031 v 0.165095 0.484110 -3.906230 v -0.081629 0.087632 -3.782753 v -0.013872 0.088823 -1.554481 v 0.008630 0.041677 -3.708195 v 0.070162 0.059225 -1.467241 v 0.349126 0.784380 -4.327246 v 0.192656 0.707311 -4.316467 v 0.240026 0.669896 -4.092967 v 0.614077 0.770599 -4.245997 v 0.448901 0.789330 -4.242595 v 0.390683 0.635870 -4.050064 v 0.823568 1.030378 -5.230011 v 0.583262 0.935220 -4.789198 v 0.936485 1.075914 -5.144932 v 0.708930 0.972489 -4.713959 v 1.079595 1.050653 -5.079602 v 0.863290 0.942616 -4.657226 v 0.731356 0.950572 -5.335061 v 0.698927 0.816156 -5.569689 v 0.452954 0.862935 -4.860037 v 0.354245 0.777679 -5.103039 v 0.109515 -0.020305 -1.439012 v 0.321579 0.190660 -3.847763 v 0.056950 -0.068344 -3.678991 v 0.551677 0.397382 -4.027330 v 0.748943 0.261978 -4.201552 v 0.797463 0.611225 -4.241810 v 0.934536 0.472987 -4.298673 v 0.919641 0.370477 -5.597496 v 1.079582 0.375487 -5.341094 v 1.225601 0.456396 -5.207421 v 0.593068 0.043314 -5.202118 v 0.711852 0.101000 -4.865152 v 0.871615 0.211454 -4.690717 v 1.063296 0.399320 -4.647913 v 1.342637 0.585582 -5.122607 v 1.150690 0.608137 -4.641154 v 1.366648 0.748651 -5.071675 v 0.745367 0.246406 -5.988852 v 0.494019 -0.022198 -5.740361 v 0.141480 -0.193021 -5.470416 v 0.693354 0.148862 -6.455598 v 0.458179 -0.058425 -6.342125 v 0.092861 -0.121753 -6.334044 v 0.001903 0.615014 -5.359071 v 0.310613 0.694999 -5.659912 v 0.602326 0.700149 -5.960638 v 0.014377 0.478587 -6.304075 v 0.335968 0.619833 -6.312831 v 0.600780 0.612337 -6.446789 v -0.303419 0.594566 -6.098518 v -0.599974 0.655996 -6.132385 v -0.241202 0.626083 -5.200386 v -0.457099 0.677790 -5.161324 v -0.259616 -0.163854 -6.116562 v -0.183392 -0.223625 -5.241480 v -0.635209 0.061396 -6.121774 v -0.504788 -0.103060 -5.122423 v -0.950019 0.234128 -5.837874 v -0.810067 0.092804 -5.080121 v -1.144829 0.478824 -5.746136 v -0.998398 0.334709 -5.084644 v -0.994164 0.856674 -5.773610 v -0.863354 0.756330 -5.102725 v -0.801998 0.842826 -5.870856 v -0.671650 0.764754 -5.123487 v 1.045049 0.802118 -4.632644 v 1.252493 0.924338 -5.055513 v -0.995449 0.583125 -5.083862 v -1.137996 0.713069 -5.735577 v 1.598002 0.816988 -5.564189 v 1.599381 0.700758 -5.624741 v 1.532017 0.614642 -5.716787 v 1.715526 0.933794 -5.717422 v 1.699604 0.816034 -5.787023 v 1.629737 0.731598 -5.898082 v 1.883043 1.059492 -5.899169 v 1.855109 0.932664 -5.998640 v 1.774384 0.842472 -6.140775 v 1.424351 0.559021 -5.523375 v 1.505227 0.658051 -5.434678 v 1.502338 0.787710 -5.373565 v 1.297397 0.577850 -5.903827 v 1.425129 0.560695 -5.822476 v 1.155962 0.509306 -5.718982 v 1.300644 0.494656 -5.623770 v 1.509245 0.835318 -6.384689 v 1.646807 0.801147 -6.286009 v 1.406474 0.713747 -6.133959 v 1.525574 0.687385 -6.031679 v 1.380351 1.065119 -5.565239 v 1.564172 1.172023 -5.714888 v 1.780605 1.304970 -5.893034 v 1.255719 1.087198 -5.619839 v 1.438416 1.182678 -5.766468 v 1.652418 1.312790 -5.952035 v 1.154437 1.043031 -5.702960 v 1.320461 1.134701 -5.855917 v 1.512782 1.262635 -6.051604 v 1.003945 1.036752 -5.521133 v 1.104476 1.081637 -5.435655 v 1.236055 1.056913 -5.374795 v 1.089111 0.843044 -5.888583 v 1.089661 0.962064 -5.803318 v 1.230625 0.966122 -6.097103 v 1.242952 1.066407 -5.981094 v 1.362597 1.098246 -6.323909 v 1.405432 1.196541 -6.191591 v 0.929064 0.824679 -5.709339 v 0.934340 0.953520 -5.615597 v 1.859089 1.203879 -5.868989 v 1.664971 1.072200 -5.695913 v 1.510868 0.957577 -5.544997 v 1.391678 0.940769 -5.352942 v 1.170557 0.692380 -5.926214 v 1.027666 0.653090 -5.757548 v 0.869972 0.619560 -5.748698 v 1.295478 0.827279 -6.155195 v 1.403801 0.956111 -6.395917 v 1.981874 0.878914 -6.465936 v 1.802272 0.826665 -6.577847 v 1.615752 0.851027 -6.620514 v 2.128560 0.944598 -6.721747 v 1.907593 0.869058 -6.790360 v 1.708489 0.849226 -6.769275 v 2.238363 1.116521 -6.349912 v 2.094190 1.105140 -6.141595 v 2.237261 1.035889 -6.535950 v 2.075505 0.976585 -6.291769 v 1.727506 1.346013 -6.328338 v 1.936762 1.311864 -6.600124 v 1.576315 1.256378 -6.447272 v 1.741231 1.205721 -6.680005 v 1.483882 1.132384 -6.546886 v 1.595348 1.106596 -6.700094 v 2.143625 1.363027 -6.343407 v 2.083770 1.364678 -6.472173 v 1.997907 1.370713 -6.136065 v 1.880283 1.392692 -6.219747 v 2.220069 1.245977 -6.358671 v 2.223785 1.204368 -6.587201 v 2.097329 1.131385 -6.757537 v 1.644286 0.966614 -6.763514 v 1.867680 1.032451 -6.812611 v 0.883363 0.124343 -7.228944 v 0.646839 -0.024425 -7.259110 v 0.390212 -0.005959 -7.292361 v 1.070393 0.135169 -7.703971 v 0.802047 0.006235 -7.763816 v 0.511476 0.026061 -7.813804 v 1.163011 0.161832 -8.064369 v 0.918797 0.093289 -8.161346 v 0.636154 0.076768 -8.160398 v 0.269275 -0.049054 -6.787587 v 0.524823 -0.050661 -6.806285 v 0.744409 0.117607 -6.839493 v 0.827585 0.571806 -7.238711 v 1.016438 0.562215 -7.711038 v 1.115469 0.520019 -8.067395 v 0.573132 0.588769 -7.270417 v 0.731449 0.578986 -7.772986 v 0.865027 0.502425 -8.164807 v 0.338782 0.438496 -7.299040 v 0.460865 0.446711 -7.820236 v 0.590458 0.430524 -8.163703 v 0.208617 0.434283 -6.784674 v 0.437333 0.591011 -6.807528 v 0.678646 0.577267 -6.844694 v 0.947532 0.372788 -7.222228 v 0.797216 0.376391 -6.856188 v 0.734974 0.417910 -6.504792 v 1.142651 0.368565 -7.694477 v 1.195867 0.347815 -8.107895 v 0.272439 0.191555 -7.307303 v 0.163854 0.163934 -6.807784 v 0.050485 0.143298 -6.551455 v 0.390845 0.216656 -7.842326 v 0.587957 0.247899 -8.218260 v -0.187159 -0.021301 -8.489817 v -0.144520 -0.066015 -8.115219 v -0.135056 -0.086523 -7.519433 v -0.455856 -0.036286 -8.505733 v -0.424768 -0.127085 -8.081474 v -0.379623 -0.149656 -7.480232 v -0.721089 0.002465 -8.418228 v -0.711949 -0.032964 -8.033904 v -0.633023 -0.036474 -7.439595 v -0.083764 -0.101907 -6.888419 v -0.321252 -0.155635 -6.827525 v -0.570598 -0.013135 -6.792706 v -0.205536 0.346922 -8.488331 v -0.478068 0.389386 -8.503635 v -0.741261 0.375015 -8.416031 v -0.166164 0.372104 -8.112885 v -0.454556 0.470532 -8.077909 v -0.734413 0.413380 -8.030973 v -0.161420 0.377122 -7.515023 v -0.412007 0.496828 -7.474960 v -0.653762 0.440220 -7.436335 v -0.124968 0.400042 -6.878002 v -0.359615 0.536135 -6.818819 v -0.582637 0.502600 -6.791322 v -0.736234 0.212481 -7.423101 v -0.655151 0.259193 -6.812274 v -0.663333 0.364684 -6.389957 v -0.775997 0.191334 -8.463245 v -0.822719 0.196893 -8.024588 v -0.031942 0.130966 -6.924860 v -0.055396 0.134692 -7.532089 v -0.056604 0.146553 -8.134798 v -0.157928 0.161766 -8.546125 v -1.836226 1.016590 -7.410828 v -1.627684 0.872918 -7.538481 v -1.370280 0.758218 -7.595252 v -1.747767 0.932613 -7.142950 v -1.528535 0.732919 -7.246038 v -1.256016 0.658972 -7.340291 v -1.538345 0.794709 -6.746178 v -1.346968 0.594312 -6.836720 v -1.106538 0.540492 -6.926594 v -1.327304 0.638226 -6.296957 v -1.144801 0.423090 -6.386161 v -0.907648 0.349198 -6.500935 v -1.381548 1.162123 -6.749738 v -1.167106 1.131764 -6.834267 v -1.001718 0.954827 -6.919466 v -1.579033 1.276060 -7.151250 v -1.336962 1.223187 -7.246882 v -1.140912 1.040889 -7.333368 v -1.682336 1.295016 -7.423892 v -1.479018 1.212733 -7.544489 v -1.266431 1.072053 -7.592119 v -1.173291 1.003628 -6.309747 v -0.980917 0.984092 -6.395974 v -0.826961 0.810684 -6.501183 v -0.978037 0.704393 -6.955856 v -1.119137 0.806439 -7.374477 v -1.298471 0.903687 -7.643332 v -0.811802 0.542748 -6.562383 v -1.320080 0.864534 -6.271852 v -1.536038 1.021683 -6.715133 v -1.746360 1.149667 -7.118443 v -1.808232 1.181964 -7.439637 v 2.071132 1.255908 -6.105393 v 1.505985 0.975476 -6.611821 v 0.931009 0.299286 -8.285854 v -0.474965 0.178488 -8.633644 v -1.589683 1.061216 -7.631387 v 0.763920 0.520049 -6.078023 # 281 vertices # 0 texture vertices # 0 normals usemtl hand f 2 4 1 f 5 4 2 f 3 5 2 f 5 6 4 f 1 10 9 f 1 7 10 f 7 11 10 f 7 8 11 f 10 12 9 f 12 10 13 f 10 14 13 f 10 11 14 f 12 17 9 f 12 15 17 f 18 15 16 f 15 18 17 f 9 2 1 f 9 17 2 f 18 2 17 f 2 18 3 f 19 4 6 f 7 4 19 f 8 7 19 f 7 1 4 f 20 22 12 f 23 22 20 f 21 23 20 f 23 24 22 f 16 26 25 f 16 15 26 f 15 22 26 f 15 12 22 f 25 28 27 f 25 26 28 f 22 28 26 f 28 22 24 f 30 31 29 f 32 31 30 f 6 32 30 f 32 33 31 f 5 32 6 f 32 5 34 f 5 35 34 f 5 3 35 f 34 33 32 f 33 34 36 f 35 36 34 f 36 35 37 f 39 40 38 f 31 40 39 f 29 31 39 f 31 33 40 f 42 43 41 f 40 43 42 f 38 40 42 f 40 33 43 f 45 46 44 f 46 45 47 f 38 47 45 f 47 38 42 f 46 49 48 f 46 47 49 f 47 41 49 f 47 42 41 f 44 52 45 f 44 50 52 f 50 53 52 f 50 51 53 f 52 38 45 f 38 52 39 f 52 29 39 f 52 53 29 f 36 55 33 f 55 36 56 f 37 56 36 f 56 37 54 f 56 24 55 f 24 56 28 f 27 56 54 f 56 27 28 f 33 57 43 f 33 55 57 f 55 58 57 f 55 24 58 f 57 41 43 f 41 57 59 f 58 59 57 f 59 58 60 f 62 64 61 f 64 62 65 f 63 65 62 f 65 63 66 f 65 21 64 f 21 65 23 f 66 23 65 f 23 66 24 f 66 58 24 f 58 66 67 f 63 67 66 f 67 63 68 f 67 60 58 f 60 67 69 f 68 69 67 f 69 68 70 f 61 72 71 f 61 64 72 f 64 73 72 f 64 21 73 f 71 75 74 f 71 72 75 f 72 76 75 f 72 73 76 f 53 77 29 f 77 53 78 f 51 78 53 f 78 51 79 f 78 80 77 f 80 78 81 f 79 81 78 f 81 79 82 f 83 77 80 f 77 83 85 f 83 86 85 f 83 84 86 f 85 29 77 f 29 85 30 f 86 30 85 f 30 86 6 f 73 87 76 f 87 73 88 f 21 88 73 f 88 21 20 f 88 89 87 f 89 88 90 f 20 90 88 f 90 20 12 f 90 91 89 f 91 90 92 f 90 13 92 f 90 12 13 f 91 94 93 f 91 92 94 f 92 14 94 f 92 13 14 f 95 98 97 f 95 96 98 f 8 98 96 f 98 8 19 f 97 86 84 f 97 98 86 f 19 86 98 f 86 19 6 f 59 49 41 f 49 59 99 f 59 69 99 f 59 60 69 f 99 48 49 f 48 99 100 f 99 70 100 f 99 69 70 f 8 101 11 f 8 96 101 f 96 102 101 f 96 95 102 f 101 14 11 f 14 101 94 f 101 93 94 f 101 102 93 f 103 107 106 f 103 104 107 f 105 107 104 f 107 105 108 f 107 109 106 f 109 107 110 f 108 110 107 f 110 108 111 f 63 113 68 f 63 112 113 f 112 104 113 f 112 105 104 f 68 114 70 f 68 113 114 f 113 103 114 f 113 104 103 f 115 118 117 f 115 116 118 f 105 118 116 f 118 105 112 f 117 62 61 f 117 118 62 f 112 62 118 f 62 112 63 f 120 121 119 f 121 120 122 f 111 122 120 f 122 111 108 f 122 115 121 f 115 122 116 f 108 116 122 f 116 108 105 f 123 127 126 f 123 124 127 f 124 128 127 f 124 125 128 f 126 130 129 f 126 127 130 f 127 131 130 f 127 128 131 f 44 133 132 f 44 46 133 f 48 133 46 f 133 48 134 f 132 126 129 f 132 133 126 f 134 126 133 f 126 134 123 f 135 138 137 f 135 136 138 f 136 130 138 f 136 129 130 f 137 140 139 f 137 138 140 f 138 131 140 f 138 130 131 f 51 142 141 f 51 50 142 f 50 132 142 f 50 44 132 f 141 136 135 f 141 142 136 f 142 129 136 f 142 132 129 f 109 144 106 f 109 143 144 f 125 144 143 f 144 125 124 f 106 145 103 f 106 144 145 f 124 145 144 f 145 124 123 f 100 134 48 f 134 100 146 f 70 146 100 f 146 70 114 f 146 123 134 f 123 146 145 f 114 145 146 f 145 114 103 f 135 148 141 f 135 147 148 f 147 117 148 f 147 115 117 f 141 149 51 f 141 148 149 f 148 61 149 f 148 117 61 f 115 150 121 f 115 147 150 f 135 150 147 f 150 135 137 f 121 151 119 f 121 150 151 f 137 151 150 f 151 137 139 f 120 152 111 f 152 120 153 f 119 153 120 f 153 119 154 f 152 156 155 f 152 153 156 f 153 157 156 f 153 154 157 f 158 161 160 f 158 159 161 f 159 110 161 f 159 109 110 f 160 152 155 f 160 161 152 f 161 111 152 f 161 110 111 f 162 140 131 f 140 162 164 f 162 165 164 f 162 163 165 f 164 139 140 f 139 164 166 f 164 167 166 f 164 165 167 f 168 171 170 f 168 169 171 f 163 171 169 f 171 163 162 f 171 125 170 f 125 171 128 f 162 128 171 f 128 162 131 f 172 169 168 f 169 172 173 f 158 173 172 f 173 158 160 f 169 174 163 f 169 173 174 f 160 174 173 f 174 160 155 f 157 176 156 f 157 175 176 f 167 176 175 f 176 167 165 f 176 155 156 f 155 176 174 f 176 163 174 f 176 165 163 f 177 181 180 f 177 178 181 f 178 182 181 f 178 179 182 f 181 183 180 f 183 181 184 f 181 185 184 f 181 182 185 f 186 75 76 f 75 186 187 f 179 187 186 f 187 179 178 f 187 74 75 f 74 187 188 f 178 188 187 f 188 178 177 f 189 193 192 f 189 190 193 f 191 193 190 f 193 191 194 f 192 196 195 f 192 193 196 f 193 197 196 f 193 194 197 f 81 198 80 f 198 81 199 f 82 199 81 f 199 82 200 f 199 195 198 f 195 199 192 f 200 192 199 f 192 200 189 f 200 201 189 f 201 200 202 f 200 203 202 f 200 82 203 f 202 177 201 f 177 202 188 f 202 74 188 f 202 203 74 f 177 204 201 f 177 180 204 f 183 204 180 f 204 183 205 f 204 189 201 f 189 204 190 f 204 191 190 f 204 205 191 f 195 207 198 f 195 206 207 f 179 207 206 f 207 179 186 f 198 208 80 f 198 207 208 f 186 208 207 f 208 186 76 f 206 182 179 f 182 206 209 f 206 196 209 f 206 195 196 f 209 185 182 f 185 209 210 f 209 197 210 f 209 196 197 f 211 215 214 f 211 212 215 f 213 215 212 f 215 213 216 f 215 217 214 f 217 215 218 f 216 218 215 f 218 216 219 f 220 216 213 f 216 220 221 f 76 221 220 f 221 76 87 f 221 219 216 f 219 221 222 f 87 222 221 f 222 87 89 f 223 227 226 f 223 224 227 f 225 227 224 f 227 225 228 f 227 229 226 f 229 227 230 f 228 230 227 f 230 228 231 f 230 232 229 f 232 230 233 f 231 233 230 f 233 231 234 f 233 80 232 f 80 233 83 f 233 84 83 f 233 234 84 f 222 235 219 f 235 222 236 f 222 237 236 f 222 89 237 f 236 231 235 f 231 236 234 f 237 234 236 f 234 237 84 f 217 239 238 f 217 218 239 f 219 239 218 f 239 219 235 f 239 225 238 f 225 239 228 f 239 231 228 f 239 235 231 f 220 208 76 f 208 220 240 f 213 240 220 f 240 213 241 f 208 232 80 f 208 240 232 f 240 229 232 f 240 241 229 f 241 226 229 f 226 241 242 f 241 212 242 f 241 213 212 f 242 223 226 f 223 242 243 f 242 211 243 f 242 212 211 f 244 248 247 f 244 245 248 f 246 248 245 f 248 246 249 f 248 250 247 f 250 248 251 f 249 251 248 f 251 249 252 f 250 254 253 f 250 251 254 f 252 254 251 f 254 252 255 f 253 91 93 f 253 254 91 f 254 89 91 f 254 255 89 f 256 260 259 f 256 257 260 f 258 260 257 f 260 258 261 f 260 262 259 f 262 260 263 f 260 264 263 f 260 261 264 f 97 265 95 f 265 97 266 f 84 266 97 f 266 84 267 f 265 257 256 f 265 266 257 f 267 257 266 f 257 267 258 f 249 268 252 f 268 249 269 f 249 270 269 f 249 246 270 f 269 258 268 f 258 269 261 f 269 264 261 f 269 270 264 f 255 237 89 f 237 255 271 f 252 271 255 f 271 252 268 f 271 84 237 f 84 271 267 f 268 267 271 f 267 268 258 f 102 253 93 f 253 102 272 f 102 265 272 f 102 95 265 f 272 250 253 f 250 272 273 f 272 256 273 f 272 265 256 f 259 273 256 f 273 259 274 f 262 274 259 f 274 262 275 f 273 247 250 f 273 274 247 f 274 244 247 f 274 275 244 f 172 159 158 f 159 172 276 f 172 170 276 f 172 168 170 f 276 109 159 f 109 276 143 f 170 143 276 f 143 170 125 f 151 154 119 f 154 151 277 f 151 166 277 f 151 139 166 f 154 175 157 f 154 277 175 f 277 167 175 f 277 166 167 f 197 278 210 f 197 194 278 f 191 278 194 f 278 191 205 f 278 185 210 f 185 278 184 f 278 183 184 f 278 205 183 f 223 279 224 f 223 243 279 f 211 279 243 f 279 211 214 f 279 225 224 f 225 279 238 f 279 217 238 f 279 214 217 f 262 280 275 f 262 263 280 f 264 280 263 f 280 264 270 f 280 244 275 f 244 280 245 f 270 245 280 f 245 270 246 f 74 281 71 f 74 203 281 f 82 281 203 f 281 82 79 f 71 149 61 f 71 281 149 f 79 149 281 f 149 79 51 # 552 elements */