Normand Briere
2019-07-06 77633b188d01228383ced79c26b41ebb2989624c
New 3ds loader.
8 files modified
39 files added
4952 ■■■■■ changed files
CameraPane.java 50 ●●●● patch | view | raw | blame | history
ClickInfo.java 2 ●●●●● patch | view | raw | blame | history
GroupEditor.java 22 ●●●● patch | view | raw | blame | history
ObjEditor.java 77 ●●●● patch | view | raw | blame | history
Object3D.java 4 ●●●● patch | view | raw | blame | history
ObjectFile.java 12 ●●●●● patch | view | raw | blame | history
cFileSystemPane.java 31 ●●●●● patch | view | raw | blame | history
cRadio.java 4 ●●● patch | view | raw | blame | history
com/microcrowd/loader/java3d/max3ds/CannotChopException.java 40 ●●●●● patch | view | raw | blame | history
com/microcrowd/loader/java3d/max3ds/ChunkChopper.java 635 ●●●●● patch | view | raw | blame | history
com/microcrowd/loader/java3d/max3ds/ChunkMap.java 444 ●●●●● patch | view | raw | blame | history
com/microcrowd/loader/java3d/max3ds/ChunkTester.java 31 ●●●●● patch | view | raw | blame | history
com/microcrowd/loader/java3d/max3ds/DefaultTextureImageLoader.java 103 ●●●●● patch | view | raw | blame | history
com/microcrowd/loader/java3d/max3ds/Loader3DS.java 317 ●●●●● patch | view | raw | blame | history
com/microcrowd/loader/java3d/max3ds/Main.java 454 ●●●●● patch | view | raw | blame | history
com/microcrowd/loader/java3d/max3ds/TextureImageLoader.java 42 ●●●●● patch | view | raw | blame | history
com/microcrowd/loader/java3d/max3ds/chunks/AxisChunk.java 83 ●●●●● patch | view | raw | blame | history
com/microcrowd/loader/java3d/max3ds/chunks/BooleanChunk.java 46 ●●●●● patch | view | raw | blame | history
com/microcrowd/loader/java3d/max3ds/chunks/BoundingBoxChunk.java 55 ●●●●● patch | view | raw | blame | history
com/microcrowd/loader/java3d/max3ds/chunks/CameraChunk.java 65 ●●●●● patch | view | raw | blame | history
com/microcrowd/loader/java3d/max3ds/chunks/Chunk.java 139 ●●●●● patch | view | raw | blame | history
com/microcrowd/loader/java3d/max3ds/chunks/ColorChunk.java 82 ●●●●● patch | view | raw | blame | history
com/microcrowd/loader/java3d/max3ds/chunks/FacesDescriptionChunk.java 322 ●●●●● patch | view | raw | blame | history
com/microcrowd/loader/java3d/max3ds/chunks/FacesMaterialChunk.java 59 ●●●●● patch | view | raw | blame | history
com/microcrowd/loader/java3d/max3ds/chunks/FloatChunk.java 47 ●●●●● patch | view | raw | blame | history
com/microcrowd/loader/java3d/max3ds/chunks/FramesChunk.java 45 ●●●●● patch | view | raw | blame | history
com/microcrowd/loader/java3d/max3ds/chunks/FramesDescriptionChunk.java 59 ●●●●● patch | view | raw | blame | history
com/microcrowd/loader/java3d/max3ds/chunks/GlobalColorChunk.java 45 ●●●●● patch | view | raw | blame | history
com/microcrowd/loader/java3d/max3ds/chunks/HierarchyInfoChunk.java 46 ●●●●● patch | view | raw | blame | history
com/microcrowd/loader/java3d/max3ds/chunks/KeyFramerInfoChunk.java 68 ●●●●● patch | view | raw | blame | history
com/microcrowd/loader/java3d/max3ds/chunks/LightChunk.java 80 ●●●●● patch | view | raw | blame | history
com/microcrowd/loader/java3d/max3ds/chunks/MaterialChunk.java 121 ●●●●● patch | view | raw | blame | history
com/microcrowd/loader/java3d/max3ds/chunks/NamedObjectChunk.java 50 ●●●●● patch | view | raw | blame | history
com/microcrowd/loader/java3d/max3ds/chunks/PercentageChunk.java 59 ●●●●● patch | view | raw | blame | history
com/microcrowd/loader/java3d/max3ds/chunks/PivotChunk.java 45 ●●●●● patch | view | raw | blame | history
com/microcrowd/loader/java3d/max3ds/chunks/PositionChunk.java 63 ●●●●● patch | view | raw | blame | history
com/microcrowd/loader/java3d/max3ds/chunks/RotationChunk.java 129 ●●●●● patch | view | raw | blame | history
com/microcrowd/loader/java3d/max3ds/chunks/ScaleChunk.java 67 ●●●●● patch | view | raw | blame | history
com/microcrowd/loader/java3d/max3ds/chunks/SmoothingChunk.java 65 ●●●●● patch | view | raw | blame | history
com/microcrowd/loader/java3d/max3ds/chunks/SpotLightChunk.java 73 ●●●●● patch | view | raw | blame | history
com/microcrowd/loader/java3d/max3ds/chunks/StringChunk.java 52 ●●●●● patch | view | raw | blame | history
com/microcrowd/loader/java3d/max3ds/chunks/TextureChunk.java 47 ●●●●● patch | view | raw | blame | history
com/microcrowd/loader/java3d/max3ds/chunks/Vertex2ListChunk.java 55 ●●●●● patch | view | raw | blame | history
com/microcrowd/loader/java3d/max3ds/chunks/Vertex3ListChunk.java 54 ●●●●● patch | view | raw | blame | history
com/microcrowd/loader/java3d/max3ds/data/KeyFramer.java 526 ●●●●● patch | view | raw | blame | history
com/microcrowd/loader/java3d/max3ds/package.html 3 ●●●●● patch | view | raw | blame | history
com/realvue/sim/ui/loader/java3d/max3ds/Loader3DS.java 34 ●●●●● patch | view | raw | blame | history
CameraPane.java
....@@ -14604,7 +14604,8 @@
1460414604 Globals.MOUSEDRAGGED = false;
1460514605
1460614606 movingcamera = false;
14607
- X = Y = 0;
14607
+ X = 0; // getBounds().width/2;
14608
+ Y = 0; // getBounds().height/2;
1460814609 //System.out.println("mouseReleased: " + e);
1460914610 clickEnd(e.getX(), e.getY(), e.getModifiersEx());
1461014611 }
....@@ -15717,23 +15718,42 @@
1571715718 */
1571815719 if (!isRenderer)
1571915720 {
15720
- object.drawEditHandles(info, 0);
15721
-
15722
- if (drag && (X != 0 || Y != 0) && object.selection.Size() > 0)
15721
+ if (object.selection.Size() > 0)
1572315722 {
15724
- switch (object.selection.get(0).hitSomething)
15723
+ int hitSomething = object.selection.get(0).hitSomething;
15724
+
15725
+ info.DX = 0;
15726
+ info.DY = 0;
15727
+ info.W = 1;
15728
+ if (hitSomething == Object3D.hitCenter)
1572515729 {
15726
- case Object3D.hitCenter: gr.setColor(Color.pink);
15727
- gr.drawLine(X, Y, info.bounds.width/2, info.bounds.height/2);
15728
- break;
15729
- case Object3D.hitRotate: gr.setColor(Color.yellow);
15730
- gr.drawLine(X, Y, info.bounds.width/2, info.bounds.height/2);
15731
- break;
15732
- case Object3D.hitScale: gr.setColor(Color.cyan);
15733
- gr.drawLine(X, Y, info.bounds.width/2, info.bounds.height/2);
15734
- break;
15730
+ info.DX = X;
15731
+ if (X != 0)
15732
+ info.DX -= info.bounds.width/2;
15733
+
15734
+ info.DY = Y;
15735
+ if (Y != 0)
15736
+ info.DY -= info.bounds.height/2;
1573515737 }
15736
-
15738
+
15739
+ object.drawEditHandles(info, 0);
15740
+
15741
+ if (drag && (X != 0 || Y != 0))
15742
+ {
15743
+ switch (hitSomething)
15744
+ {
15745
+ case Object3D.hitCenter: gr.setColor(Color.pink);
15746
+ gr.drawLine(X, Y, info.bounds.width/2, info.bounds.height/2);
15747
+ break;
15748
+ case Object3D.hitRotate: gr.setColor(Color.yellow);
15749
+ gr.drawLine(X, Y, info.bounds.width/2, info.bounds.height/2);
15750
+ break;
15751
+ case Object3D.hitScale: gr.setColor(Color.cyan);
15752
+ gr.drawLine(X, Y, info.bounds.width/2, info.bounds.height/2);
15753
+ break;
15754
+ }
15755
+
15756
+ }
1573715757 }
1573815758 }
1573915759 }
ClickInfo.java
....@@ -26,6 +26,8 @@
2626 double toScreen[][];
2727 iCameraPane pane;
2828 Graphics g;
29
+ int DX, DY;
30
+ float W = 1;
2931
3032 static double matbuffer[][] = new double[4][4];
3133 }
GroupEditor.java
....@@ -380,6 +380,7 @@
380380 shadowYItem.addActionListener(this);
381381 shadowZItem = menu.add(new MenuItem("Shadow Blue"));
382382 shadowZItem.addActionListener(this);
383
+
383384 if (Globals.ADVANCED)
384385 {
385386 menu.add("-");
....@@ -601,6 +602,10 @@
601602 fullButton.setToolTipText("Full-screen window");
602603 fullButton.addActionListener(this);
603604
605
+ oe.toolbarPanel.add(screenfitButton = GetButton("icons/fit.png", !Grafreed.NIMBUSLAF)); //, oe.aConstraints);
606
+ screenfitButton.setToolTipText("Screen fit");
607
+ screenfitButton.addActionListener(this);
608
+
604609 oe.toolbarPanel.add(restoreCameraButton = GetButton("icons/eye.png", !Grafreed.NIMBUSLAF)); //, oe.aConstraints);
605610 restoreCameraButton.setToolTipText("Restore viewpoint");
606611 restoreCameraButton.addActionListener(this);
....@@ -633,10 +638,6 @@
633638
634639 //oe.toolboxPanel.Return();
635640
636
- copyOptionsPanel.add(screenfitButton = GetButton("icons/fit.png", !Grafreed.NIMBUSLAF)); //, oe.aConstraints);
637
- screenfitButton.setToolTipText("Screen fit");
638
- screenfitButton.addActionListener(this);
639
-
640641 // copyOptionsPanel.add(trackCB = GetToggleButton("icons/track.png", CameraPane.TRACK)); //, oe.aConstraints);
641642 // trackCB.setToolTipText("Enable tracking");
642643 // trackCB.addItemListener(this);
....@@ -1214,8 +1215,6 @@
12141215 }
12151216 }
12161217
1217
- String string = (String) object;
1218
-
12191218 System.out.println("Transfer = " + object + "; drop : " + target);
12201219 // if( object instanceof java.io.File[])
12211220 // {
....@@ -1223,6 +1222,8 @@
12231222 // objEditor.DropFile((java.io.File[]) object, true);
12241223 // return;
12251224 // }
1225
+
1226
+ String string = (String) object;
12261227
12271228 // File path for Mac and Windows
12281229 if (string.charAt(0) == '/' || string.charAt(1) == ':')
....@@ -2219,7 +2220,8 @@
22192220 } else
22202221 if (source == undoButton)
22212222 {
2222
- Undo();
2223
+ if (!Undo())
2224
+ java.awt.Toolkit.getDefaultToolkit().beep();
22232225 } else
22242226 if (source == redoButton)
22252227 {
....@@ -2227,7 +2229,8 @@
22272229 } else
22282230 if (source == saveButton)
22292231 {
2230
- Save();
2232
+ if (!Save(true))
2233
+ java.awt.Toolkit.getDefaultToolkit().beep();
22312234 } else
22322235 if (source == oneStepButton)
22332236 {
....@@ -2236,17 +2239,14 @@
22362239 } else
22372240 if (source == screenfitButton)
22382241 {
2239
- //Reload(lastConverter, lastFilename, true);
22402242 ScreenFit();
22412243 } else
22422244 if (source == screenfitpointButton)
22432245 {
2244
- //Reload(lastConverter, lastFilename, true);
22452246 ScreenFitPoint();
22462247 } else
22472248 if (source == snapobjectButton)
22482249 {
2249
- //Reload(lastConverter, lastFilename, true);
22502250 SnapObject();
22512251 } else
22522252 // if (event.getSource() == recompileButton)
ObjEditor.java
....@@ -1979,8 +1979,9 @@
19791979 // 3D models
19801980 if (filename.endsWith(".3ds") || filename.endsWith(".3DS"))
19811981 {
1982
- lastConverter = new com.jmex.model.converters.MaxToJme();
1983
- LoadFile(filename, lastConverter);
1982
+ //lastConverter = new com.jmex.model.converters.MaxToJme();
1983
+ //LoadFile(filename, lastConverter);
1984
+ LoadObjFile(filename); // New 3ds loader
19841985 continue;
19851986 }
19861987 if (filename.endsWith(".dae") || filename.endsWith(".DAE"))
....@@ -2706,6 +2707,7 @@
27062707 LA.matXRotate(((Object3D) group.get(group.size() - 1)).toParent, -Math.PI / 2);
27072708 LA.matXRotate(((Object3D) group.get(group.size() - 1)).fromParent, Math.PI / 2);
27082709 }
2710
+
27092711 //cJME.count++;
27102712 //cJME.count %= 12;
27112713 if (gc)
....@@ -2889,6 +2891,7 @@
28892891 }
28902892 }
28912893 }
2894
+
28922895 cFileSystemPane FSPane;
28932896
28942897 void SetMaterial(cMaterial mat, Object3D.cVector2[] others)
....@@ -2942,6 +2945,7 @@
29422945 }
29432946 }
29442947 }
2948
+
29452949 freezematerial = false;
29462950 }
29472951
....@@ -3566,6 +3570,28 @@
35663570
35673571 public void Save()
35683572 {
3573
+ // Default reduces the probability of heuristics errors.
3574
+ Save(true);
3575
+ }
3576
+
3577
+ private boolean Equal(byte[] compress, byte[] name)
3578
+ {
3579
+ if (compress.length != name.length)
3580
+ {
3581
+ return false;
3582
+ }
3583
+
3584
+ for (int i=compress.length; --i>=0;)
3585
+ {
3586
+ if (compress[i] != name[i])
3587
+ return false;
3588
+ }
3589
+
3590
+ return true;
3591
+ }
3592
+
3593
+ public boolean Save(boolean user)
3594
+ {
35693595 System.err.println("Save");
35703596
35713597 cRadio tab = GetCurrentTab();
....@@ -3576,18 +3602,31 @@
35763602 copy.ExtractBigData(hashtable);
35773603
35783604 byte[] compress = Compress(copy);
3579
-
3580
- //EditorFrame.m_MainFrame.requestFocusInWindow();
3581
- tab.graphs[tab.undoindex++] = compress;
3582
-
3583
- copy.RestoreBigData(hashtable);
35843605
35853606 CameraPane.SWITCH = temp;
35863607
3608
+ boolean thesame = false;
3609
+
3610
+ // Quick heuristic using length. Works only when stream is compressed.
3611
+ if (tab.undoindex > 0 && tab.graphs[tab.undoindex-1] != null && Equal(compress, tab.graphs[tab.undoindex-1]))
3612
+ {
3613
+ thesame = true;
3614
+ }
3615
+
3616
+ //EditorFrame.m_MainFrame.requestFocusInWindow();
3617
+ if (!thesame)
3618
+ {
3619
+ tab.user[tab.undoindex] = user;
3620
+ tab.graphs[tab.undoindex++] = compress;
3621
+ }
3622
+
3623
+ copy.RestoreBigData(hashtable);
3624
+
35873625 //assert(hashtable.isEmpty());
35883626
35893627 for (int i = tab.undoindex; i < tab.graphs.length; i++)
35903628 {
3629
+ tab.user[i] = false;
35913630 tab.graphs[i] = null;
35923631 }
35933632
....@@ -3611,6 +3650,8 @@
36113650 e.printStackTrace();
36123651 }
36133652 }
3653
+
3654
+ return !thesame;
36143655 }
36153656
36163657 void CopyChanged(Object3D obj)
....@@ -3667,7 +3708,7 @@
36673708 redoButton.setEnabled(tab.graphs[tab.undoindex + 1] != null);
36683709 }
36693710
3670
- public void Undo()
3711
+ public boolean Undo()
36713712 {
36723713 System.err.println("Undo");
36733714
....@@ -3676,18 +3717,27 @@
36763717 if (tab.undoindex == 0)
36773718 {
36783719 java.awt.Toolkit.getDefaultToolkit().beep();
3679
- return;
3720
+ return false;
36803721 }
36813722
3682
- if (tab.graphs[tab.undoindex] == null)
3723
+ if (tab.graphs[tab.undoindex] == null || !tab.user[tab.undoindex])
36833724 {
3684
- Save();
3685
- tab.undoindex -= 1;
3725
+ if (Save(false))
3726
+ tab.undoindex -= 1;
3727
+ else
3728
+ {
3729
+ if (tab.undoindex <= 0)
3730
+ return false;
3731
+ else
3732
+ tab.undoindex -= 1;
3733
+ }
36863734 }
36873735
36883736 tab.undoindex -= 1;
36893737
36903738 CopyChanged((Object3D)Uncompress(tab.graphs[tab.undoindex]));
3739
+
3740
+ return true;
36913741 }
36923742
36933743 public void Redo()
....@@ -3703,6 +3753,9 @@
37033753 tab.undoindex += 1;
37043754
37053755 CopyChanged((Object3D)Uncompress(tab.graphs[tab.undoindex]));
3756
+
3757
+ if (!tab.user[tab.undoindex])
3758
+ tab.graphs[tab.undoindex] = null;
37063759 }
37073760
37083761 void ImportGFD()
Object3D.java
....@@ -7288,8 +7288,8 @@
72887288 // {
72897289 // CameraPane.Ymax = spoth;
72907290 // }
7291
- info.g.drawArc(boundary.x, boundary.y,
7292
- boundary.width, boundary.height, 0, 360);
7291
+ info.g.drawArc(boundary.x + info.DX, boundary.y + info.DY,
7292
+ (int)(boundary.width * info.W), (int)(boundary.height * info.W), 0, 360);
72937293 //info.g.drawArc(spot.x, spotw, spot.width/2, boundary.height/2, 0, 360);
72947294 // if (CameraPane.Xmin > boundary.x)
72957295 // {
ObjectFile.java
....@@ -730,11 +730,15 @@
730730 public Scene load(String filename) throws FileNotFoundException,
731731 IncorrectFormatException, ParsingErrorException
732732 {
733
+ if (filename.toLowerCase().endsWith(".obj"))
734
+ {
735
+ setBasePathFromFilename(filename);
733736
734
- setBasePathFromFilename(filename);
735
-
736
- Reader reader = new BufferedReader(new FileReader(filename));
737
- return load(reader);
737
+ Reader reader = new BufferedReader(new FileReader(filename));
738
+ return load(reader);
739
+ }
740
+ else // new 3ds loader
741
+ return new com.microcrowd.loader.java3d.max3ds.Loader3DS().load(filename);
738742 } // End of load(String)
739743
740744 private void setBaseUrlFromUrl(URL url)
cFileSystemPane.java
....@@ -18,6 +18,7 @@
1818 iCallBack owner;
1919
2020 JButton refreshButton;
21
+ JButton rootButton;
2122 JButton loadButton;
2223 JButton printButton;
2324 JButton replaceButton;
....@@ -39,7 +40,7 @@
3940 //ToolTipManager.sharedInstance().registerComponent(jTree);
4041 jTree.setCellRenderer(new cFileSystemModel.Renderer());
4142
42
- ResetModel();
43
+ ResetModel(true);
4344
4445 JScrollPane tree = new JScrollPane(jTree);
4546 //jTree.addTreeSelectionListener(this);
....@@ -64,11 +65,13 @@
6465
6566 fileCommsnds.add(loadButton = new JButton("Load")); //, aConstraints);
6667 loadButton.setToolTipText("Load selected file(s)");
67
- fileCommsnds.add(refreshButton = new JButton("Refresh")); //, aConstraints);
68
- refreshButton.setToolTipText("Refresh entire tree");
69
-
70
- refreshButton.addActionListener(this);
71
- loadButton.addActionListener(this);
68
+ loadButton.addActionListener(this);
69
+ fileCommsnds.add(refreshButton = new JButton("User")); //, aConstraints);
70
+ refreshButton.setToolTipText("Refresh user tree");
71
+ refreshButton.addActionListener(this);
72
+ fileCommsnds.add(rootButton = new JButton("Root")); //, aConstraints);
73
+ rootButton.setToolTipText("Refresh root tree");
74
+ rootButton.addActionListener(this);
7275
7376 if (Globals.ADVANCED)
7477 {
....@@ -114,7 +117,7 @@
114117 // /*DropTarget dropTarget =*/ new DropTarget(oe.cameraView, this);
115118 }
116119
117
- void ResetModel()
120
+ void ResetModel(boolean user)
118121 {
119122 cFilter filter = new cFilter();
120123
....@@ -134,9 +137,11 @@
134137 filter.add("tga");
135138 filter.add("bmp"); // not supported
136139
140
+ File root = java.io.File.listRoots()[0];
141
+ File defaultDirectory = javax.swing.filechooser.FileSystemView.getFileSystemView().getDefaultDirectory();
142
+
137143 jTree.setModel(new cFileSystemModel(
138
- //java.io.File.listRoots()[1])
139
- javax.swing.filechooser.FileSystemView.getFileSystemView().getDefaultDirectory(),
144
+ user?defaultDirectory:root,
140145 filter
141146 ));
142147 }
....@@ -167,7 +172,13 @@
167172 {
168173 if(event.getSource() == refreshButton)
169174 {
170
- ResetModel();
175
+ ResetModel(true);
176
+ return;
177
+ }
178
+
179
+ if(event.getSource() == rootButton)
180
+ {
181
+ ResetModel(false);
171182 return;
172183 }
173184
cRadio.java
....@@ -35,7 +35,9 @@
3535 camera = (Camera)Grafreed.clone(c);
3636 }
3737
38
- byte[] graphs[] = new byte[10000][];
38
+ byte[] graphs[] = new byte[100][];
39
+ boolean[] user = new boolean[100];
40
+
3941 int undoindex = 0;
4042
4143 // Patch to avoid bug with transparency.
com/microcrowd/loader/java3d/max3ds/CannotChopException.java
....@@ -0,0 +1,40 @@
1
+/**
2
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
3
+ * Microcrowd.com
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+ *
19
+ * Contact Josh DeFord jdeford@microcrowd.com
20
+ */
21
+package com.microcrowd.loader.java3d.max3ds;
22
+
23
+/**
24
+ * Exception thrown by chunks to indicate that the
25
+ * chopper cannot appropriately chop(parse) it.
26
+ * This Exception won't return null for getCause()
27
+ */
28
+public class CannotChopException extends Exception
29
+{
30
+ public CannotChopException(Throwable cause)
31
+ {
32
+ this("", cause);
33
+ }
34
+
35
+ public CannotChopException(String message, Throwable cause)
36
+ {
37
+ super(message, cause);
38
+ }
39
+
40
+}
com/microcrowd/loader/java3d/max3ds/ChunkChopper.java
....@@ -0,0 +1,635 @@
1
+/**
2
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
3
+ * Microcrowd.com
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+ *
19
+ * Contact Josh DeFord jdeford@realvue.com
20
+ */
21
+
22
+package com.microcrowd.loader.java3d.max3ds;
23
+
24
+import java.awt.Image;
25
+import java.io.IOException;
26
+import java.io.InputStream;
27
+import java.nio.BufferUnderflowException;
28
+import java.nio.ByteBuffer;
29
+import java.nio.ByteOrder;
30
+import java.nio.channels.Channels;
31
+import java.nio.channels.ReadableByteChannel;
32
+import java.util.HashMap;
33
+import java.util.logging.Level;
34
+import java.util.logging.Logger;
35
+import javax.media.j3d.Behavior;
36
+import javax.media.j3d.BranchGroup;
37
+import javax.media.j3d.Light;
38
+import javax.media.j3d.Texture;
39
+import javax.media.j3d.TransformGroup;
40
+import javax.vecmath.Point3f;
41
+import javax.vecmath.Vector3f;
42
+import com.microcrowd.loader.java3d.max3ds.chunks.Chunk;
43
+import com.microcrowd.loader.java3d.max3ds.data.KeyFramer;
44
+import com.sun.j3d.loaders.SceneBase;
45
+import com.sun.j3d.utils.image.TextureLoader;
46
+
47
+/**
48
+ * A singleton flyweight factory responsible for chopping the
49
+ * data up and sending it to the corresponding
50
+ * chunks(which are flyweights ala the flyweight pattern)
51
+ * for processing.
52
+ * This will sequentially read a 3ds file, load or
53
+ * skip chunks and subchunks and initialize the data
54
+ * for the chunks.
55
+ * <p>
56
+ * Retrieved data may be stored as state in the ChunkChopper
57
+ * via {@link #pushData} for use by other chunks.
58
+ * <p>
59
+ * Features not supported; unknown chunks are skipped.
60
+ */
61
+public class ChunkChopper
62
+{
63
+ private Logger logger = Logger.getLogger(ChunkChopper.class.getName());
64
+
65
+ private Loader3DS loader;
66
+ private BranchGroup sceneGroup;
67
+ private SceneBase base;
68
+ private HashMap dataMap;
69
+ private ByteBuffer chunkBuffer;
70
+ private Integer chunkID;
71
+
72
+ private TransformGroup currentGroup;
73
+ private String currentObjectName;
74
+ private ChunkTester chunkTester = new ChunkTester();
75
+ private Chunk mainChunk = new Chunk("MainChunk");
76
+ private ChunkMap chunkMap = new ChunkMap(mainChunk);
77
+
78
+ private KeyFramer keyFramer = new KeyFramer();
79
+
80
+ /** This should be turned on by Loader3DS to view debugging information. */
81
+ public static boolean debug;
82
+
83
+ /** Current chunk for which debugging info is viewed if debug == true */
84
+ public static Chunk debugChunk;
85
+
86
+ /**
87
+ * private singleton constructor.
88
+ */
89
+ public ChunkChopper(){}
90
+
91
+ /**
92
+ * This sequentially parses the chunks out of the input stream and
93
+ * constructs the 3D entities represented within.
94
+ * A Chunk is a little endian data structure consists of a
95
+ * 6 byte header followed by subchunks and or data.
96
+ * The first short int(little endian) represent the id
97
+ * of the chunk. The next int represent the total
98
+ * length of the chunk(total of data, subchunks and chunk header).
99
+ * <p>
100
+ * The first chunk is the main chunk (id=4D4D) and its length
101
+ * is always the length of the file. It only contains sub chunks.
102
+ * Other chunks may contain data, subchunks or both. If the format
103
+ * of a chunk is unknown skipped.
104
+ * <p>
105
+ * Subclasses of chunk will all automagically load the subchunks.
106
+ * It is the programmers responsibility to ensure that the data
107
+ * preceeding the subchunks is loaded or skipped as
108
+ * required and that something useful is done with the data. If data from the
109
+ * subchunks is needed in order to initialize components then that code should be
110
+ * placed in {@link Chunk#initialize}. Otherwise the data may be dealt with in
111
+ * {@link Chunk#loadData}. Also, if a chunk has data preceeding its subchunks
112
+ * it communicates how many bytes long that data is by returning it from loadData.
113
+ * <p>
114
+ * This chopper reads a file in order from beginning to end
115
+ * @param inputStream the stream with the data to be parsed.
116
+ * @param loader the loader that will be configured from the data.
117
+ * @param modelName name of the model file for display purposes.
118
+ * @param modelSize size in bytes of the file to read.
119
+ */
120
+ public synchronized SceneBase loadSceneBase(InputStream inputStream, Loader3DS loader, int modelSize)
121
+ {
122
+ this.loader = loader;
123
+ this.sceneGroup = new BranchGroup();
124
+ this.base = new SceneBase();
125
+ this.dataMap = new HashMap();
126
+ base.setSceneGroup(sceneGroup);
127
+
128
+ //FileChannel channel = null;
129
+ ReadableByteChannel channel = null;
130
+ try {
131
+ channel = Channels.newChannel(inputStream);
132
+ chunkBuffer = getByteBuffer(channel, modelSize);
133
+ //chunkBuffer = getDirectByteBuffer(channel, modelSize);
134
+
135
+ int mainChunkID = chunkBuffer.getShort();
136
+ long mainChunkLength = chunkBuffer.getInt();
137
+
138
+ long begin = System.currentTimeMillis();
139
+ logger.finest("\n\n\n STARTING SUBCUNKS " + (mainChunkLength - 61));
140
+ try {
141
+ loadSubChunks(mainChunk, 0);
142
+ }
143
+ catch(CannotChopException e){
144
+
145
+ }
146
+ logger.finest("FINISHED WITH THE SUBCHUNKS");
147
+ }
148
+ catch (Exception e) {
149
+ e.printStackTrace();
150
+ }
151
+ finally
152
+ {
153
+ try {
154
+ if(channel != null) {
155
+ channel.close();
156
+ }
157
+ } catch (Exception e){
158
+ //Just closing file.. don't care.
159
+ }
160
+ }
161
+ return base;
162
+ }
163
+
164
+ /**
165
+ * Allocates and loads a byte buffer from the channel
166
+ * @param channel the file channel to load the data from
167
+ * @return a direct byte buffer containing all the data of the channel at position 0
168
+ */
169
+ public ByteBuffer getByteBuffer(ReadableByteChannel channel, int channelSize) throws IOException
170
+ {
171
+ ByteBuffer chunkBuffer = ByteBuffer.allocate(channelSize);
172
+ chunkBuffer.order(ByteOrder.LITTLE_ENDIAN);
173
+ channel.read(chunkBuffer);
174
+ chunkBuffer.position(0);
175
+ return chunkBuffer;
176
+ }
177
+
178
+
179
+ /**
180
+ * The base class Chunk takes care of loading subchunks for
181
+ * all chunks types. It occurs as follows:
182
+ * <ol>
183
+ * <li>The chunk id (short) is read
184
+ * <li>The chunk length(int) is read
185
+ * <li>A subchunk is looked up from the map of publish
186
+ * subchunk types of the current chunk.
187
+ * <li>If it isn't found during the lookup it is skipped.
188
+ * <li>Otherwise it is requested to {@link #pushData}
189
+ * <li>The return value, if there is one, is used to determine
190
+ * where its next subchunk is. A return value of 0 signifies
191
+ * that the next subchunk is nigh.
192
+ * <li>The chunk's subchunks are then loaded.
193
+ * <li>The chunks initialize method is called.
194
+ * </ol>
195
+ */
196
+ protected void loadSubChunks(Chunk parentChunk, int level) throws CannotChopException
197
+ {
198
+ level++;
199
+ while(chunkBuffer.hasRemaining())//hasRemaining() evaluates limit - position.
200
+ {
201
+ chunkID = new Integer(chunkBuffer.getShort());
202
+ Chunk chunk = parentChunk.getSubChunk(chunkID);
203
+
204
+ int currentChunkLength = chunkBuffer.getInt() - 6; //length includes this 6 byte header.
205
+ int finishedPosition = chunkBuffer.position() + currentChunkLength;
206
+ int previousLimit = chunkBuffer.limit();
207
+ chunkBuffer.limit(chunkBuffer.position() + currentChunkLength);
208
+
209
+ if(debug) {
210
+ debug(parentChunk, level, chunkID, currentChunkLength, chunkBuffer.position(), chunkBuffer.limit());
211
+ }
212
+ if(chunk != null && currentChunkLength != 0) {
213
+ try {
214
+ chunk.loadData(this);
215
+ }
216
+ catch(BufferUnderflowException e){
217
+ chunkBuffer.position(finishedPosition);
218
+ chunkBuffer.limit(previousLimit);
219
+ throw new CannotChopException(" tried to read too much data from the buffer. Trying to recover.", e);
220
+ }
221
+ try {
222
+ if(chunkBuffer.hasRemaining()) {
223
+ loadSubChunks(chunk, level);
224
+ }
225
+ chunk.initialize(this);
226
+ }
227
+ catch(CannotChopException e){
228
+ logger.log(Level.SEVERE, chunk.toString() + "Trying to continue");
229
+ }
230
+ }
231
+
232
+ chunkBuffer.position(finishedPosition);
233
+ chunkBuffer.limit(previousLimit);
234
+ }
235
+ }
236
+
237
+ /**
238
+ * Gets the key framer chunk
239
+ * These should be their own objects instead of chunks.
240
+ */
241
+ public KeyFramer getKeyFramer()
242
+ {
243
+ return keyFramer;
244
+ }
245
+
246
+ /**
247
+ * Adds a group to the choppers scene group
248
+ * and sets the current name and group.
249
+ * @param the name of the object to add which
250
+ * will also be the current name of the object
251
+ * the chopper is working with.
252
+ * @param group the current group that the chopper
253
+ * will be adding things too.
254
+ */
255
+ public void addObject(String name, TransformGroup group)
256
+ {
257
+ sceneGroup.addChild(group);
258
+ currentGroup = group;
259
+ currentObjectName = name;
260
+ base.addNamedObject(name, group);
261
+ }
262
+
263
+
264
+
265
+ /**
266
+ * Gets the name of the current object
267
+ * the chopper is working with. The value returned
268
+ * from this generally is either set by a NamedObjectChunk
269
+ * and is the name of the name of the last object added
270
+ * or is the name set by setObjectName.
271
+ * @return the name of the current object being
272
+ * constructed.
273
+ */
274
+ public String getObjectName()
275
+ {
276
+ return currentObjectName;
277
+ }
278
+
279
+
280
+ /**
281
+ * Sets the name of the current object.
282
+ * The name of the current object can also be set
283
+ * with {@link #addObject}
284
+ * @param name the name that the current object should be set to.
285
+ */
286
+ public void setObjectName(String name)
287
+ {
288
+ currentObjectName = name;
289
+ }
290
+
291
+ /**
292
+ * Gets the group for the current object
293
+ * the chopper is working with. The value returned
294
+ * from this generally gets set by a NamedObjectChunk
295
+ * and is the name of the last object added.
296
+ * @return the group for the current object being
297
+ * constructed.
298
+ */
299
+ public TransformGroup getGroup()
300
+ {
301
+ return currentGroup;
302
+ }
303
+
304
+ /**
305
+ * Used to store data that may later be used
306
+ * by another chunk.
307
+ * @param key the look up key.
308
+ * @param data the data to store.
309
+ */
310
+ public void pushData(Object key, Object data)
311
+ {
312
+ dataMap.put(key, data);
313
+ }
314
+
315
+ /**
316
+ * Gets a datum that had been retrieved and stored
317
+ * via {@link #pushData} earlier and removes it.
318
+ * @param key the key used to store the datum earlier.
319
+ */
320
+ public Object popData(Object key)
321
+ {
322
+ Object retVal = dataMap.remove(key);
323
+ return retVal;
324
+ }
325
+
326
+ /**
327
+ * Sets a named object in the loader.
328
+ * @param key the key name of the object
329
+ * @param value the named Object.
330
+ */
331
+ public void setNamedObject(String key, Object value)
332
+ {
333
+ base.addNamedObject(key, value);
334
+ }
335
+
336
+ /**
337
+ * Returns true if there have been lights loaded.
338
+ * @return true if there are lights.
339
+ */
340
+ public boolean hasLights()
341
+ {
342
+ return (base.getLightNodes() != null && base.getLightNodes().length > 0);
343
+ }
344
+
345
+ /**
346
+ * Adds a behavior to the scene base.
347
+ * @param behavior the behavior to add to the scene base.
348
+ */
349
+ public void addBehaviorNode(Behavior behavior)
350
+ {
351
+ base.addBehaviorNode(behavior);
352
+ }
353
+
354
+
355
+ /**
356
+ * Adds a light to the scene base.
357
+ * @param light the light to add to the scene base.
358
+ */
359
+ public void addLightNode(Light light)
360
+ {
361
+ base.addLightNode(light);
362
+ }
363
+
364
+
365
+ /**
366
+ * Adds a camera transform to the scene base.
367
+ * @param viewGroup the transform group to add as a view.
368
+ */
369
+ public void addViewGroup(TransformGroup viewGroup)
370
+ {
371
+ base.addViewGroup(viewGroup);
372
+ }
373
+
374
+ /**
375
+ * Sets a named Object in the loader.
376
+ * @param key the key used as the name for which the object will be returned
377
+ */
378
+ public Object getNamedObject(String key)
379
+ {
380
+ if(key == null)
381
+ return null;
382
+ return base.getNamedObjects().get(key);
383
+ }
384
+
385
+ /**
386
+ * Gets and cast the named object for the
387
+ * key provided. Its an error if its not
388
+ * a transform group.
389
+ */
390
+ public TransformGroup getNamedTransformGroup(String key)
391
+ {
392
+ Object object = getNamedObject(key);
393
+ if(object instanceof TransformGroup)
394
+ {
395
+ return (TransformGroup)object;
396
+ }
397
+ else if (object != null)
398
+ {
399
+ logger.log(Level.INFO, "Retrieving " + key + " which is a named object but not useable because "+
400
+ " its not a transform group. Its a " + object.getClass().getName());
401
+ }
402
+ return null;
403
+ }
404
+
405
+
406
+ /**
407
+ * Gets a long from the chunk Buffer
408
+ */
409
+ public long getLong()
410
+ {
411
+ return chunkBuffer.getLong();
412
+ }
413
+
414
+ /**
415
+ * Reads a short and returns it as a signed
416
+ * int.
417
+ */
418
+ public int getShort()
419
+ {
420
+ return chunkBuffer.getShort();
421
+ }
422
+
423
+ /**
424
+ * Reads a short and returns it as an unsigned
425
+ * int.
426
+ */
427
+ public int getUnsignedShort()
428
+ {
429
+ return chunkBuffer.getShort()&0xFFFF;
430
+ }
431
+
432
+ /**
433
+ * reads a float from the chunkBuffer.
434
+ */
435
+ public float getFloat()
436
+ {
437
+ return chunkBuffer.getFloat();
438
+ }
439
+
440
+ /**
441
+ * Reads 3 floats x,z,y from the chunkbuffer.
442
+ * Since 3ds has z as up and y as pointing in whereas
443
+ * java3d has z as pointing forward and y as pointing up;
444
+ * this returns new Vector3f(x,-z,y)
445
+ *
446
+ */
447
+ public Vector3f getVector()
448
+ {
449
+ return new Vector3f(getPoint());
450
+ }
451
+ /**
452
+ * Reads 3 floats x,z,y from the chunkbuffer.
453
+ * Since 3ds has z as up and y as pointing in whereas
454
+ * java3d has z as pointing forward and y as pointing up;
455
+ * this returns new Point3f(x,-z,y)
456
+ */
457
+ public Point3f getPoint()
458
+ {
459
+ float x = chunkBuffer.getFloat();
460
+ float z = -chunkBuffer.getFloat();
461
+ float y = chunkBuffer.getFloat();
462
+ return new Point3f(x,y,z);
463
+ }
464
+
465
+ /**
466
+ * Reads an int and returns it
467
+ * @return the int read
468
+ */
469
+ public int getInt()
470
+ {
471
+ return chunkBuffer.getInt();
472
+ }
473
+
474
+ /**
475
+ * Reads an int and returns it
476
+ * unsigned, any ints greater than MAX_INT
477
+ * will break.
478
+ */
479
+ public int getUnsignedInt()
480
+ {
481
+ return chunkBuffer.getInt()&0xFFFFFFFF;
482
+ }
483
+
484
+ /**
485
+ * Reads a byte, unsigns it, returns the corresponding int.
486
+ * @return the unsigned int corresponding to the read byte.
487
+ */
488
+ public int getUnsignedByte()
489
+ {
490
+ return chunkBuffer.get()&0xFF;
491
+ }
492
+
493
+ /**
494
+ * Reads a number of bytes corresponding to the
495
+ * number of bytes left in the current chunk and returns an array
496
+ * containing them.
497
+ * @return an array containing all the bytes for the current chunk.
498
+ */
499
+ public byte[] getChunkBytes()
500
+ {
501
+ byte[] retVal = new byte[chunkBuffer.limit() - chunkBuffer.position()];
502
+ get(retVal);
503
+ return retVal;
504
+ }
505
+
506
+ /**
507
+ * Fills bytes with data from the chunk buffer.
508
+ * @param bytes the array to fill with data.
509
+ */
510
+ public void get(byte[] bytes)
511
+ {
512
+ chunkBuffer.get(bytes);
513
+ }
514
+
515
+
516
+ /**
517
+ * Sets the data map used to store values
518
+ * that chunks may need to retrieve later.
519
+ * @param dataMap the hashmap that will be used to store
520
+ * and retrieve values for use by chunks.
521
+ */
522
+ public void setDataMap(HashMap dataMap)
523
+ {
524
+ this.dataMap = dataMap;
525
+ }
526
+
527
+
528
+ /**
529
+ * This reads bytes until it gets 0x00 and returns
530
+ * the corresponding string.
531
+ */
532
+ public String getString()
533
+ {
534
+ StringBuffer stringBuffer = new StringBuffer();
535
+ char charIn = (char)chunkBuffer.get();
536
+ while(charIn != 0x00)
537
+ {
538
+ stringBuffer.append(charIn);
539
+ charIn = (char)chunkBuffer.get();
540
+ }
541
+ return stringBuffer.toString();
542
+ }
543
+
544
+ /**
545
+ * Gets the id of the current chunk.
546
+ * @return id of the current chunk as read
547
+ * from the chunkBuffer. It will be a signed <code>short</code>.
548
+ */
549
+ public Integer getID()
550
+ {
551
+ return chunkID;
552
+ }
553
+
554
+ /**
555
+ * Loads the image to server as a texture.
556
+ * @param textureImageName name of the image that
557
+ * is going to be set to be the texture.
558
+ */
559
+ public Texture createTexture(String textureImageName)
560
+ {
561
+ Image image = loader.getTextureImage(textureImageName);
562
+ if(image == null)
563
+ {
564
+ System.err.println("Cannot load texture image " + textureImageName +
565
+ ". Make sure it is in the directory with the model file. " +
566
+ "If its a bmp make sure JAI is installed.");
567
+ return null;
568
+ }
569
+ try
570
+ {
571
+ TextureLoader textureLoader = new TextureLoader(image, null);
572
+ return textureLoader.getTexture();
573
+ }
574
+ catch(Exception e){
575
+ e.printStackTrace();
576
+ }
577
+ return null;
578
+ }
579
+
580
+ /**
581
+ * prints some handy information... the chunk hierarchy.
582
+ */
583
+ protected void debug(Chunk parentChunk, int level, Integer chunkID, long chunkLength, int position, long limit)
584
+ {
585
+ try {
586
+ for(int i=0; i<level; i++)
587
+ {
588
+ System.out.print(" ");
589
+ }
590
+ Object child = parentChunk.getSubChunk(chunkID);
591
+ int id = ((short)chunkID.intValue()) & 0xFFFF;
592
+ System.out.println(parentChunk + " is " +
593
+ (child==null?"skipping":"LOADING")+
594
+ ": [id=" + Integer.toHexString(id) +
595
+ ", object= <" + parentChunk.getSubChunk(chunkID) +
596
+ ">, chunkLength=" + chunkLength +
597
+ ", position=" + position +
598
+ " limit=" + limit + "]");
599
+ }
600
+ catch(Exception e){
601
+ //We're debugging.. its ok
602
+ e.printStackTrace();
603
+ }
604
+ }
605
+
606
+ /**
607
+ * Prints an exception and exits.
608
+ */
609
+ private void exceptAndExit(Throwable exception)
610
+ {
611
+ logger.log(Level.SEVERE, "\nThe chunk for loadData method read too much or not enough data from the stream." +
612
+ " It needs be skipped or adjusted to read more or less data.");
613
+ exception.printStackTrace();
614
+ System.exit(3);
615
+ }
616
+
617
+ /**
618
+ * Convert the integer to an unsigned number.
619
+ * @param i the integer to convert.
620
+ */
621
+ private static String byteString(int i)
622
+ {
623
+ final char[] digits = {
624
+ '0' , '1' , '2' , '3' , '4' , '5' ,
625
+ '6' , '7' , '8' , '9' , 'a' , 'b' ,
626
+ 'c' , 'd' , 'e' , 'f' };
627
+
628
+ char[] buf = new char[2];
629
+ buf[1] = digits[i & 0xF];
630
+ i >>>= 4;
631
+ buf[0] = digits[i & 0xF];
632
+
633
+ return "0x" + new String(buf).toUpperCase();
634
+ }
635
+}
com/microcrowd/loader/java3d/max3ds/ChunkMap.java
....@@ -0,0 +1,444 @@
1
+/**
2
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
3
+ * Microcrowd.com
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+ *
19
+ * Contact Josh DeFord jdeford@microcrowd.com
20
+ */
21
+
22
+package com.microcrowd.loader.java3d.max3ds;
23
+
24
+import java.util.HashMap;
25
+import com.microcrowd.loader.java3d.max3ds.chunks.AxisChunk;
26
+import com.microcrowd.loader.java3d.max3ds.chunks.BooleanChunk;
27
+import com.microcrowd.loader.java3d.max3ds.chunks.BoundingBoxChunk;
28
+import com.microcrowd.loader.java3d.max3ds.chunks.CameraChunk;
29
+import com.microcrowd.loader.java3d.max3ds.chunks.Chunk;
30
+import com.microcrowd.loader.java3d.max3ds.chunks.ColorChunk;
31
+import com.microcrowd.loader.java3d.max3ds.chunks.FacesDescriptionChunk;
32
+import com.microcrowd.loader.java3d.max3ds.chunks.FacesMaterialChunk;
33
+import com.microcrowd.loader.java3d.max3ds.chunks.FloatChunk;
34
+import com.microcrowd.loader.java3d.max3ds.chunks.FramesChunk;
35
+import com.microcrowd.loader.java3d.max3ds.chunks.FramesDescriptionChunk;
36
+import com.microcrowd.loader.java3d.max3ds.chunks.GlobalColorChunk;
37
+import com.microcrowd.loader.java3d.max3ds.chunks.HierarchyInfoChunk;
38
+import com.microcrowd.loader.java3d.max3ds.chunks.KeyFramerInfoChunk;
39
+import com.microcrowd.loader.java3d.max3ds.chunks.LightChunk;
40
+import com.microcrowd.loader.java3d.max3ds.chunks.MaterialChunk;
41
+import com.microcrowd.loader.java3d.max3ds.chunks.NamedObjectChunk;
42
+import com.microcrowd.loader.java3d.max3ds.chunks.PercentageChunk;
43
+import com.microcrowd.loader.java3d.max3ds.chunks.PivotChunk;
44
+import com.microcrowd.loader.java3d.max3ds.chunks.PositionChunk;
45
+import com.microcrowd.loader.java3d.max3ds.chunks.RotationChunk;
46
+import com.microcrowd.loader.java3d.max3ds.chunks.ScaleChunk;
47
+import com.microcrowd.loader.java3d.max3ds.chunks.SmoothingChunk;
48
+import com.microcrowd.loader.java3d.max3ds.chunks.SpotLightChunk;
49
+import com.microcrowd.loader.java3d.max3ds.chunks.StringChunk;
50
+import com.microcrowd.loader.java3d.max3ds.chunks.TextureChunk;
51
+import com.microcrowd.loader.java3d.max3ds.chunks.Vertex2ListChunk;
52
+import com.microcrowd.loader.java3d.max3ds.chunks.Vertex3ListChunk;
53
+
54
+
55
+/**
56
+ * A Hashmap with the chunk names as values with keys
57
+ * being the chunk id.
58
+ */
59
+public class ChunkMap extends HashMap
60
+{
61
+ private Chunk mainChunk;
62
+
63
+ /** Constant designating a chunk as a frames chunk*/
64
+ public static final Integer FRAMES_CHUNK = new Integer((short)0x0B008);
65
+ /** Constant designating a chunk as a mesh info chunk*/
66
+ //public static final Integer AMBIENT_LIGHT_INFO = new Integer((short)0x0B001);
67
+ public static final Integer MESH_INFO = new Integer((short)0x0B002);
68
+ //public static final Integer CAMERA_INFO = new Integer((short)0x0B003);
69
+ //public static final Integer CAMERA_TARGET_INFO = new Integer((short)0x0B004);
70
+ //public static final Integer OMNI_LIGHT_INFO = new Integer((short)0x0B005);
71
+ //public static final Integer SPOT_LIGHT_TARGET_INFO = new Integer((short)0x0B006);
72
+ public static final Integer SPOT_LIGHT_INFO = new Integer((short)0x0B007);
73
+ /** Key for the name and flags chunk */
74
+ public static final Integer NAME_AND_FLAGS = new Integer((short)0xB010);
75
+ /** Key for the pivot chunk */
76
+ public static final Integer PIVOT = new Integer((short)0xB013);
77
+ /** Indicates a position track chunk **/
78
+ public static final Integer POSITION = new Integer((short)0xB020);
79
+ /** Indicates a scale track chunk */
80
+ public static final Integer SCALE_TRACK= new Integer((short)0xB022);
81
+ /** Indicates a rotation track chunk */
82
+ public static final Integer ROTATION= new Integer((short)0xB021);
83
+ public static final Integer BOUNDING_BOX = new Integer((short)0x0B014);
84
+ /** Indicates a hierarchy info chunk **/
85
+ public static final Integer HIERARCHY_INFO= new Integer((short)0xB030);
86
+ /** Signifies that the light is off **/
87
+ //public static final Integer LIGHT_OFF = new Integer((short)0x4620);
88
+ /** Signifies that the light is attenuated **/
89
+ public static final Integer ATTENUATED = new Integer((short)0x4625);
90
+ public static final Integer RANGE_START = new Integer((short)0x4659);
91
+ public static final Integer RANGE_END = new Integer((short)0x465A);
92
+ public static final Integer MULTIPLIER = new Integer((short)0x465B);
93
+ public static final Integer SPOTLIGHT = new Integer((short)0x4610);
94
+ public static final Integer COLOR = new Integer((short)0x0010);
95
+ public static final Integer VERSION = new Integer((short)0x2);
96
+ public static final Integer EDITOR = new Integer((short)0x3D3D);
97
+ public static final Integer KEYFRAMER = new Integer((short)0xB000);
98
+ /** These are the chunk ids for colors */
99
+ public static final Integer MATERIAL_NAME = new Integer((short)0xA000);
100
+ /** ID of the chunk that will be used to represent the ambient color. **/
101
+ public static final Integer AMBIENT_COLOR = new Integer((short)0xA010);
102
+ /** ID of the chunk that will be used to represent the diffuse color. **/
103
+ public static final Integer DIFFUSE_COLOR = new Integer((short)0xA020);
104
+ /** ID of the chunk that will be used to represent the specular color. **/
105
+ public static final Integer SPECULAR_COLOR = new Integer((short)0xA030);
106
+ /** ID of the chunk that will be used to represent the shinines. **/
107
+ public static final Integer SHININESS = new Integer((short)0xA040);
108
+ //public static final Integer SHININESS = new Integer((short)0xA041);
109
+ /** ID of the chunk that will be used to represent the transparency. **/
110
+ public static final Integer TRANSPARENCY = new Integer((short)0xA050);
111
+ /** ID of the chunk that will be used to represent the two sided. **/
112
+ public static final Integer TWO_SIDED = new Integer((short)0xA081);
113
+ /** ID of the chunk that will be used to represent the texture. **/
114
+ public static final Integer TEXTURE = new Integer((short)0xA200);
115
+ /** ID of the chunk that will be used to represent the self illumination. **/
116
+ /** Represent a mesh object for shapes. */
117
+ public static final Integer MESH = new Integer((short)0x4100);
118
+ /** Represent a camera for viewing */
119
+ public static final Integer CAMERA = new Integer((short)0x4700);
120
+ /** Represent a light */
121
+ public static final Integer LIGHT = new Integer((short)0x4600);
122
+ /** Signifies that the light is off **/
123
+ //public static final Integer LIGHT_OFF = new Integer((short)0x4620);
124
+ //public static final Integer RAYTRACE = new Integer((short)0x4627);
125
+ //public static final Integer SHADOWED = new Integer((short)0x4630);
126
+ //public static final Integer SHADOW_MAP = new Integer((short)0x4641);
127
+ //public static final Integer SHOW_CONE = new Integer((short)0x4650);
128
+ //public static final Integer RECTANGULAR = new Integer((short)0x4651);
129
+ //public static final Integer OVERSHOOT = new Integer((short)0x4652);
130
+ //public static final Integer SPOT_MAP = new Integer((short)0x4653);
131
+ //public static final Integer SPOT_ROLL = new Integer((short)0x4656);
132
+ //public static final Integer RAY_TRACE_BIAS = new Integer((short)0x4658);
133
+ /** the id of a texture name chunk.*/
134
+ public static final Integer TEXTURE_NAME = new Integer((short)0xA300);
135
+ public static final int TEXTURE_TILING = 0xA351;
136
+ public static final int TEXBLUR = 0xA353;
137
+ /** The vertex list from which vertices of a face array will be used. */
138
+ public static final Integer VERTEX_LIST = new Integer((short)0x4110);
139
+ /** reference coordinates into the vertex list which represent texture coordinates. */
140
+ public static final Integer TEXTURE_COORDINATES = new Integer((short)0x4140);
141
+ /** Local coordinate system of the mesh. */
142
+ public static final Integer COORDINATE_AXES = new Integer((short)0x4160);
143
+ /** reference coordinates into the vertex list which represent shape vertex coordinates. */
144
+ public static final Integer FACES_DESCRIPTION = new Integer((short)0x4120);
145
+ public static final Integer MATERIAL = new Integer((short)0xAFFF);
146
+ public static final Integer SCALE = new Integer((short)0x100);
147
+ public static final Integer NAMED_OBJECT = new Integer((short)0x4000);
148
+ /** Key mapping faces material chunk as a child of this chunk */
149
+ public static final Integer FACES_MATERIAL = new Integer((short)0x4130);
150
+ /** Key mapping smoothing chunk as a child of this chunk */
151
+ public static final Integer SMOOTH = new Integer((short)0x4150);
152
+
153
+ /**
154
+ * singleton constructor.
155
+ */
156
+ public ChunkMap(Chunk mainChunk)
157
+ {
158
+ this.mainChunk = mainChunk;
159
+ initializeDataMap();
160
+ }
161
+
162
+ public Chunk get(Integer chunkID)
163
+ {
164
+ return (Chunk)super.get(chunkID);
165
+ }
166
+
167
+ /**
168
+ * looks up the chunk corresponding to chunkID
169
+ * in the chopper's cache. If its not there
170
+ * look it up from the parent chunk provided.
171
+ * @param chunkID the id of the chunk to lookup
172
+ * @return the chunk for chunkID
173
+ public synchronized Chunk getChunk(Chunk parentChunk, Integer chunkID)
174
+ {
175
+ Chunk chunk = (Chunk)get(chunkID);
176
+ if(chunk == null && parentChunk != null)
177
+ {
178
+ chunk = (Chunk)(parentChunk.getChunkMap().get(chunkID)); //look up chunk from its parent.
179
+ put(chunkID, chunk);
180
+ }
181
+ return chunk;
182
+ }
183
+ */
184
+
185
+ /**
186
+ * Called when debugging is turned on. The keys are cast to short so that
187
+ * they are improperly signed since java will be reading improperly signed
188
+ * ids out of the file.
189
+ */
190
+ private void initializeDataMap()
191
+ {
192
+ Chunk keyFramerChunk = new Chunk("KeyFramerChunk");
193
+ Chunk editorChunk = new Chunk("EditorChunk");
194
+ Chunk triangularMeshChunk = new Chunk("TriangularMeshChunk");
195
+
196
+ Chunk facesDescriptionChunk = new FacesDescriptionChunk();
197
+ Chunk framesDescriptionChunk = new FramesDescriptionChunk();
198
+ Chunk textureChunk = new TextureChunk();
199
+ Chunk lightChunk = new LightChunk();
200
+ Chunk namedObjectChunk = new NamedObjectChunk();
201
+ Chunk materialChunk = new MaterialChunk();
202
+ Chunk keyFramerInfoChunk = new KeyFramerInfoChunk();
203
+ Chunk spotLightChunk = new SpotLightChunk();
204
+ Chunk floatChunk = new FloatChunk();
205
+ Chunk framesChunk = new FramesChunk();
206
+ Chunk pivotChunk = new PivotChunk();
207
+ Chunk positionChunk = new PositionChunk();
208
+ Chunk rotationChunk = new RotationChunk();
209
+ Chunk scaleChunk = new ScaleChunk();
210
+ Chunk hierarchyInfoChunk = new HierarchyInfoChunk();
211
+ Chunk boundingBoxChunk = new BoundingBoxChunk();
212
+ Chunk stringChunk = new StringChunk();
213
+ Chunk globalColorChunk = new GlobalColorChunk();
214
+ Chunk booleanChunk = new BooleanChunk();
215
+ Chunk percentageChunk = new PercentageChunk();
216
+ Chunk cameraChunk = new CameraChunk();
217
+ Chunk colorChunk = new ColorChunk();
218
+ Chunk vertex3ListChunk = new Vertex3ListChunk();
219
+ Chunk vertex2ListChunk = new Vertex2ListChunk();
220
+ Chunk axisChunk = new AxisChunk();
221
+ Chunk facesMaterialChunk = new FacesMaterialChunk();
222
+ Chunk smoothingChunk = new SmoothingChunk();
223
+
224
+
225
+ //mainChunk.addSubChunk(VERSION, stringChunk);
226
+ mainChunk.addSubChunk(EDITOR, editorChunk);
227
+ mainChunk.addSubChunk(KEYFRAMER, keyFramerChunk);
228
+
229
+ editorChunk.addSubChunk(MATERIAL, materialChunk);
230
+ editorChunk.addSubChunk(SCALE, floatChunk);
231
+ editorChunk.addSubChunk(NAMED_OBJECT, namedObjectChunk);
232
+
233
+ keyFramerChunk.addSubChunk(FRAMES_CHUNK, framesChunk);
234
+ keyFramerChunk.addSubChunk(MESH_INFO, keyFramerInfoChunk);
235
+ //keyFramerChunk.addSubChunk(AMBIENT_LIGHT_INFO, keyFramerInfoChunk);
236
+ //keyFramerChunk.addSubChunk(CAMERA_INFO, keyFramerInfoChunk);
237
+ //keyFramerChunk.addSubChunk(CAMERA_TARGET_INFO, keyFramerInfoChunk);
238
+ //keyFramerChunk.addSubChunk(OMNI_LIGHT_INFO, keyFramerInfoChunk);
239
+ //keyFramerChunk.addSubChunk(SPOT_LIGHT_TARGET_INFO, keyFramerInfoChunk);
240
+ //keyFramerChunk.addSubChunk(SPOT_LIGHT_INFO, keyFramerInfoChunk);
241
+
242
+ keyFramerInfoChunk.addSubChunk(NAME_AND_FLAGS, framesDescriptionChunk);
243
+ keyFramerInfoChunk.addSubChunk(PIVOT, pivotChunk);
244
+ keyFramerInfoChunk.addSubChunk(POSITION, positionChunk);
245
+ keyFramerInfoChunk.addSubChunk(ROTATION, rotationChunk);
246
+ keyFramerInfoChunk.addSubChunk(SCALE_TRACK, scaleChunk);
247
+ keyFramerInfoChunk.addSubChunk(HIERARCHY_INFO, hierarchyInfoChunk);
248
+ keyFramerInfoChunk.addSubChunk(BOUNDING_BOX, boundingBoxChunk);
249
+
250
+ //spotLightChunk.addSubChunk(LIGHT_OFF, booleanChunk);
251
+ //spotLightChunk.addSubChunk(RAYTRACE, booleanChunk);
252
+ //spotLightChunk.addSubChunk(SHADOWED, booleanChunk);
253
+ //spotLightChunk.addSubChunk(SHOW_CONE, booleanChunk);
254
+ //spotLightChunk.addSubChunk(RECTANGULAR, booleanChunk);
255
+ //spotLightChunk.addSubChunk(SHADOW_MAP, booleanChunk);
256
+ //spotLightChunk.addSubChunk(OVERSHOOT, booleanChunk);
257
+ //spotLightChunk.addSubChunk(SPOT_MAP, booleanChunk);
258
+ //spotLightChunk.addSubChunk(SPOT_ROLL, booleanChunk);
259
+ //spotLightChunk.addSubChunk(RAY_TRACE_BIAS, booleanChunk);
260
+
261
+ materialChunk.addSubChunk(MATERIAL_NAME, stringChunk);
262
+
263
+ materialChunk.addSubChunk(AMBIENT_COLOR, globalColorChunk);
264
+ materialChunk.addSubChunk(DIFFUSE_COLOR, globalColorChunk);
265
+ materialChunk.addSubChunk(SPECULAR_COLOR, globalColorChunk);
266
+ materialChunk.addSubChunk(TEXTURE, textureChunk);
267
+
268
+ materialChunk.addSubChunk(TWO_SIDED, booleanChunk);
269
+
270
+ materialChunk.addSubChunk(SHININESS, percentageChunk);
271
+ materialChunk.addSubChunk(TRANSPARENCY, percentageChunk);
272
+
273
+ namedObjectChunk.addSubChunk(MESH, triangularMeshChunk);
274
+ namedObjectChunk.addSubChunk(CAMERA, cameraChunk);
275
+ namedObjectChunk.addSubChunk(LIGHT, lightChunk);
276
+
277
+ lightChunk.addSubChunk(RANGE_START, floatChunk);
278
+ lightChunk.addSubChunk(COLOR, colorChunk);
279
+ lightChunk.addSubChunk(RANGE_END, floatChunk);
280
+ lightChunk.addSubChunk(MULTIPLIER, floatChunk);
281
+ lightChunk.addSubChunk(SPOTLIGHT, spotLightChunk);
282
+
283
+
284
+ textureChunk.addSubChunk(TEXTURE_NAME, stringChunk);
285
+
286
+ triangularMeshChunk.addSubChunk(VERTEX_LIST, vertex3ListChunk);
287
+ triangularMeshChunk.addSubChunk(TEXTURE_COORDINATES, vertex2ListChunk);
288
+ triangularMeshChunk.addSubChunk(FACES_DESCRIPTION, facesDescriptionChunk);
289
+ triangularMeshChunk.addSubChunk(COORDINATE_AXES, axisChunk);
290
+
291
+ facesDescriptionChunk.addSubChunk(FACES_MATERIAL, facesMaterialChunk);
292
+ facesDescriptionChunk.addSubChunk(SMOOTH, smoothingChunk);
293
+
294
+ /*
295
+ put(new Integer((short)0x0010), "Rgb (float)");
296
+ put(new Integer((short)0x0011), "Rgb (byte)");
297
+ put(new Integer((short)0x0012), "Rgb (byte) gamma corrected");
298
+ put(new Integer((short)0x0013), "Rgb (float) gamma corrected");
299
+ put(new Integer((short)0x0030), "percent (int)");
300
+ put(new Integer((short)0x0031), "percent (float)");
301
+ put(new Integer((short)0x0002), "3DS-Version");
302
+ put(new Integer((short)0x3D3D), "3D editor chunk");
303
+ put(new Integer((short)0x0100), "One unit");
304
+ put(new Integer((short)0x1100), "Background bitmap");
305
+ put(new Integer((short)0x1101), "Use background bitmap");
306
+ put(new Integer((short)0x1200), "Background color");
307
+ put(new Integer((short)0x1201), "Use background color");
308
+ put(new Integer((short)0x1300), "Gradient colors");
309
+ put(new Integer((short)0x1301), "Use gradient");
310
+ put(new Integer((short)0x1400), "Shadow map bias");
311
+ put(new Integer((short)0x1420), "Shadow map size");
312
+ put(new Integer((short)0x1450), "Shadow map sample range");
313
+ put(new Integer((short)0x1460), "Raytrace bias");
314
+ put(new Integer((short)0x1470), "Raytrace on");
315
+ put(new Integer((short)0x2100), "Ambient color");
316
+ put(new Integer((short)0x2200), "Fog");
317
+ put(new Integer((short)0x2210), "fog background");
318
+ put(new Integer((short)0x2201), "Use fog");
319
+ put(new Integer((short)0x2210), "Fog background");
320
+ put(new Integer((short)0x2300), "Distance queue");
321
+ put(new Integer((short)0x2310), "Dim background");
322
+ put(new Integer((short)0x2301), "Use distance queue");
323
+ put(new Integer((short)0x2302), "Layered fog options");
324
+ put(new Integer((short)0x2303), "Use layered fog");
325
+ put(new Integer((short)0x3D3E), "Mesh version");
326
+ put(new Integer((short)0x4000), "Object block");
327
+ put(new Integer((short)0x4010), "Object hidden");
328
+ put(new Integer((short)0x4012), "Object doesn't cast");
329
+ put(new Integer((short)0x4013), "Matte object");
330
+ put(new Integer((short)0x4015), "External process on");
331
+ put(new Integer((short)0x4017), "Object doesn't receive shadows");
332
+ put(new Integer((short)0x4100), "Triangular mesh");
333
+ put(new Integer((short)0x4110), "Vertices list");
334
+ put(new Integer((short)0x4120), "Faces description");
335
+ put(new Integer((short)0x4130), "Faces material list");
336
+ put(new Integer((short)0x4140), "Mapping coordinates list");
337
+ put(new Integer((short)0x4150), "Smoothing group list");
338
+ put(new Integer((short)0x4160), "Local coordinate system");
339
+ put(new Integer((short)0x4165), "Object color in editor");
340
+ put(new Integer((short)0x4181), "External process name");
341
+ put(new Integer((short)0x4182), "External process parameters");
342
+ put(new Integer((short)0x4600), "Light");
343
+ put(new Integer((short)0x4610), "Spotlight");
344
+ put(new Integer((short)0x4627), "Spot raytrace");
345
+ put(new Integer((short)0x4630), "Light shadowed");
346
+ put(new Integer((short)0x4641), "Spot shadow map");
347
+ put(new Integer((short)0x4650), "Spot show cone");
348
+ put(new Integer((short)0x4651), "Spot is rectangular");
349
+ put(new Integer((short)0x4652), "Spot overshoot");
350
+ put(new Integer((short)0x4653), "Spot map");
351
+ put(new Integer((short)0x4656), "Spot roll");
352
+ put(new Integer((short)0x4658), "Spot ray trace bias");
353
+ put(new Integer((short)0x4620), "Light off");
354
+ put(new Integer((short)0x4625), "Attenuation on");
355
+ put(new Integer((short)0x4659), "Range start");
356
+ put(new Integer((short)0x465A), "Range end");
357
+ put(new Integer((short)0x465B), "Multiplier");
358
+ put(new Integer((short)0x4700), "Camera");
359
+ put(new Integer((short)0x7001), "Window settings");
360
+ put(new Integer((short)0x7011), "Window description #2 ...");
361
+ put(new Integer((short)0x7012), "Window description #1 ...");
362
+ put(new Integer((short)0x7020), "Mesh windows ...");
363
+ put(new Integer((short)0xAFFF), "Material block");
364
+ put(new Integer((short)0xA000), "Material name");
365
+ put(new Integer((short)0xA010), "Ambient color");
366
+ put(new Integer((short)0xA020), "Diffuse color");
367
+ put(new Integer((short)0xA030), "Specular color");
368
+ put(new Integer((short)0xA040), "Shininess percent");
369
+ put(new Integer((short)0xA041), "Shininess strength percent");
370
+ put(new Integer((short)0xA050), "Transparency percent");
371
+ put(new Integer((short)0xA052), "Transparency falloff percent");
372
+ put(new Integer((short)0xA053), "Reflection blur percent");
373
+ put(new Integer((short)0xA081), "2 sided");
374
+ put(new Integer((short)0xA083), "Add trans");
375
+ put(new Integer((short)0xA084), "Self illum");
376
+ put(new Integer((short)0xA085), "Wire frame on");
377
+ put(new Integer((short)0xA087), "Wire thickness");
378
+ put(new Integer((short)0xA088), "Face map");
379
+ put(new Integer((short)0xA08A), "In tranc");
380
+ put(new Integer((short)0xA08C), "Soften");
381
+ put(new Integer((short)0xA08E), "Wire in units");
382
+ put(new Integer((short)0xA100), "Render type");
383
+ put(new Integer((short)0xA240), "Transparency falloff percent present");
384
+ put(new Integer((short)0xA250), "Reflection blur percent present");
385
+ put(new Integer((short)0xA252), "Bump map present (true percent)");
386
+ put(new Integer((short)0xA200), "Texture map 1");
387
+ put(new Integer((short)0xA33A), "Texture map 2");
388
+ put(new Integer((short)0xA210), "Opacity map");
389
+ put(new Integer((short)0xA230), "Bump map");
390
+ put(new Integer((short)0xA33C), "Shininess map");
391
+ put(new Integer((short)0xA204), "Specular map");
392
+ put(new Integer((short)0xA33D), "Self illum. map");
393
+ put(new Integer((short)0xA220), "Reflection map");
394
+ put(new Integer((short)0xA33E), "Mask for texture map 1");
395
+ put(new Integer((short)0xA340), "Mask for texture map 2");
396
+ put(new Integer((short)0xA342), "Mask for opacity map");
397
+ put(new Integer((short)0xA344), "Mask for bump map");
398
+ put(new Integer((short)0xA346), "Mask for shininess map");
399
+ put(new Integer((short)0xA348), "Mask for specular map");
400
+ put(new Integer((short)0xA34A), "Mask for self illum. map");
401
+ put(new Integer((short)0xA34C), "Mask for reflection map");
402
+ put(new Integer((short)0xA300), "Mapping filename");
403
+ put(new Integer((short)0xA351), "Mapping parameters");
404
+ put(new Integer((short)0xA353), "Blur percent");
405
+ put(new Integer((short)0xA354), "V scale");
406
+ put(new Integer((short)0xA356), "U scale");
407
+ put(new Integer((short)0xA358), "U offset");
408
+ put(new Integer((short)0xA35A), "V offset");
409
+ put(new Integer((short)0xA35C), "Rotation angle");
410
+ put(new Integer((short)0xA360), "RGB Luma/Alpha tint 1");
411
+ put(new Integer((short)0xA362), "RGB Luma/Alpha tint 2");
412
+ put(new Integer((short)0xA364), "RGB tint R");
413
+ put(new Integer((short)0xA366), "RGB tint G");
414
+ put(new Integer((short)0xA368), "RGB tint B");
415
+ put(new Integer((short)0xB000), "Key Framer");
416
+ put(new Integer((short)0xB001), "Ambient light information block");
417
+ put(new Integer((short)0xB002), "Mesh information block");
418
+ put(new Integer((short)0xB003), "Camera information block");
419
+ put(new Integer((short)0xB004), "Camera target information block");
420
+ put(new Integer((short)0xB005), "Omni light information block");
421
+ put(new Integer((short)0xB006), "Spot light target information block");
422
+ put(new Integer((short)0xB007), "Spot light information block");
423
+ put(new Integer((short)0xB008), "Frames (Start and End)");
424
+ put(new Integer((short)0xB009), "Current Frame");
425
+ put(new Integer((short)0xB00A), "Animation revision, filename and length");
426
+ put(new Integer((short)0xB010), "Object name, parameters and hierarchy father");
427
+ put(new Integer((short)0xB013), "Object pivot point");
428
+ put(new Integer((short)0xB014), "Bounding Box");
429
+ put(new Integer((short)0xB015), "Object morph angle");
430
+ put(new Integer((short)0xB020), "Position track");
431
+ put(new Integer((short)0xB021), "Rotation track");
432
+ put(new Integer((short)0xB022), "Scale track");
433
+ put(new Integer((short)0xB023), "FOV track");
434
+ put(new Integer((short)0xB024), "Roll track");
435
+ put(new Integer((short)0xB025), "Color track");
436
+ put(new Integer((short)0xB026), "Morph track");
437
+ put(new Integer((short)0xB027), "Hotspot track");
438
+ put(new Integer((short)0xB028), "Falloff track");
439
+ put(new Integer((short)0xB029), "Hide track");
440
+ put(new Integer((short)0xB030), "Hierarchy position");
441
+ */
442
+ }
443
+
444
+ }
com/microcrowd/loader/java3d/max3ds/ChunkTester.java
....@@ -0,0 +1,31 @@
1
+/**
2
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
3
+ *
4
+ * Microcrowd.com
5
+ *
6
+ * This library is free software; you can redistribute it and/or
7
+ * modify it under the terms of the GNU Lesser General Public
8
+ * License as published by the Free Software Foundation; either
9
+ * version 2.1 of the License, or (at your option) any later version.
10
+ *
11
+ * This library is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
+ * Lesser General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public
17
+ * License along with this library; if not, write to the Free Software
18
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
+ *
20
+ * Contact Josh DeFord jdeford@microcrowd.com.com
21
+ */
22
+
23
+package com.microcrowd.loader.java3d.max3ds;
24
+
25
+/**
26
+ * Used to test and create test data for chunks.
27
+ */
28
+public class ChunkTester
29
+{
30
+
31
+}
com/microcrowd/loader/java3d/max3ds/DefaultTextureImageLoader.java
....@@ -0,0 +1,103 @@
1
+/**
2
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
3
+ *
4
+ * Microcrowd.com
5
+ *
6
+ * This library is free software; you can redistribute it and/or
7
+ * modify it under the terms of the GNU Lesser General Public
8
+ * License as published by the Free Software Foundation; either
9
+ * version 2.1 of the License, or (at your option) any later version.
10
+ *
11
+ * This library is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
+ * Lesser General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public
17
+ * License along with this library; if not, write to the Free Software
18
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
+ *
20
+ * Contact Josh DeFord jdeford@realvue.com
21
+ */
22
+package com.microcrowd.loader.java3d.max3ds;
23
+
24
+import java.awt.Image;
25
+import java.io.File;
26
+import java.io.FileInputStream;
27
+import java.io.FileNotFoundException;
28
+import java.io.InputStream;
29
+import java.net.URL;
30
+import javax.imageio.ImageIO;
31
+
32
+/**
33
+ * General purpose implementation of TextureImageLoader.
34
+ * Gets the base path from loader and prepends it to the
35
+ * file name to load an image.
36
+ */
37
+public class DefaultTextureImageLoader implements TextureImageLoader
38
+{
39
+
40
+ private Loader3DS loader;
41
+
42
+ /**
43
+ * Constructs an image loader that will resolve image
44
+ * locations to the base path of the loader provided.
45
+ * @param the loader that will specify the base path
46
+ * used to retrieve images.
47
+ */
48
+ public DefaultTextureImageLoader(Loader3DS loader)
49
+ {
50
+ this.loader = loader;
51
+ }
52
+
53
+
54
+ /**
55
+ * Gets the image to be loaded as a texture.
56
+ * @param imageName the name of the image to load.
57
+ * @return image to be used.
58
+ */
59
+ public Image getTextureImage(String imageName)
60
+ {
61
+ File file = null;
62
+ InputStream in = null;
63
+ if(loader.fromUrl())
64
+ {
65
+ try
66
+ {
67
+ in = new URL(loader.getBaseUrl() + imageName).openStream();
68
+ return ImageIO.read(in);
69
+ }
70
+ catch (FileNotFoundException e)
71
+ {
72
+ throw new IllegalArgumentException(" Can't load texture: " + imageName +
73
+ " Make sure it is located in the " +
74
+ " same server and directory with the model file."+
75
+ " the loader's base path is: " + loader.getBaseUrl());
76
+ }
77
+ catch (Exception e)
78
+ {
79
+ e.printStackTrace();
80
+ throw new IllegalArgumentException(" Can't load texture: " + imageName +
81
+ " Make sure it is located in the " +
82
+ " same server and directory with the model file."+
83
+ " the loader's base path is: " + loader.getBaseUrl());
84
+ }
85
+ }
86
+ else
87
+ {
88
+ try
89
+ {
90
+ in = new FileInputStream(new File(loader.getBasePath() + imageName));
91
+ return ImageIO.read(in);
92
+ }
93
+ catch (Exception e)
94
+ {
95
+ e.printStackTrace();
96
+ throw new IllegalArgumentException(" Can't load texture: " + imageName +
97
+ " Make sure it is located in the " +
98
+ " same server and directory with the model file."+
99
+ " the loader's base path is: " + loader.getBasePath());
100
+ }
101
+ }
102
+ }
103
+}
com/microcrowd/loader/java3d/max3ds/Loader3DS.java
....@@ -0,0 +1,317 @@
1
+/**
2
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
3
+ * Microcrowd.com
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+ *
19
+ * Contact Josh DeFord jdeford@microcrowd.com
20
+ */
21
+
22
+package com.microcrowd.loader.java3d.max3ds;
23
+
24
+import java.awt.Image;
25
+import java.io.File;
26
+import java.io.FileInputStream;
27
+import java.io.FileNotFoundException;
28
+import java.io.IOException;
29
+import java.io.InputStream;
30
+import java.io.Reader;
31
+import java.net.MalformedURLException;
32
+import java.net.URL;
33
+import java.net.URLConnection;
34
+import javax.media.j3d.BoundingSphere;
35
+import javax.media.j3d.Group;
36
+import javax.media.j3d.PointLight;
37
+import javax.media.j3d.Transform3D;
38
+import javax.media.j3d.TransformGroup;
39
+import javax.vecmath.Point3d;
40
+import com.sun.j3d.loaders.LoaderBase;
41
+import com.sun.j3d.loaders.Scene;
42
+import com.sun.j3d.loaders.SceneBase;
43
+
44
+/**
45
+ * Used to load a 3ds studio max file. This will sequentially read a 3ds file,
46
+ * load or skip chunks and subchunks and initialize the data for the chunks.
47
+ * A {@link ChunkChopper} is a singleton flyweight factory responsible for
48
+ * chopping the data up and sending it to the corresponding chunks(which are
49
+ * flyweights ala the flyweight pattern) for processing.
50
+ *
51
+ * <p>
52
+ * Features not supported; unknown chunks are skipped.
53
+ * </p>
54
+ */
55
+public class Loader3DS extends LoaderBase
56
+{
57
+ private boolean dataMapInitialized;
58
+
59
+ private TextureImageLoader textureImageLoader;
60
+ private boolean fromUrl;
61
+
62
+ public Loader3DS()
63
+ {
64
+ //turnOnDebug();
65
+ }
66
+
67
+ /**
68
+ * Setting this will initialize a lot of debugging code that has lots of
69
+ * overhead.
70
+ */
71
+ private boolean debugMode;
72
+
73
+ /**
74
+ * This is not supported
75
+ *
76
+ * @param reader loads a model from a reader
77
+ *
78
+ * @return nothing, this isn't implemented.
79
+ *
80
+ * @throws FileNotFoundException
81
+ * @throws UnsupportedOperationException
82
+ */
83
+ public Scene load(Reader reader) throws FileNotFoundException
84
+ {
85
+ throw new UnsupportedOperationException("Not supported for 3DS");
86
+ }
87
+
88
+ /**
89
+ * Loads the model by parsing the file, modelPath and creating a 3D Scene.
90
+ *
91
+ * @param modelPath the path of the 3ds file.
92
+ *
93
+ * @return a loaded scene
94
+ *
95
+ * @throws FileNotFoundException if the file can't be located.
96
+ */
97
+ public Scene load(String modelPath) throws FileNotFoundException
98
+ {
99
+ InputStream fileIn = null;
100
+ setBasePathFromFilename(modelPath);
101
+
102
+ try {
103
+ File modelFile = getFile(modelPath);
104
+ fileIn = new FileInputStream(modelFile);
105
+ return parseChunks(fileIn, (int)modelFile.length());
106
+ } finally {
107
+ try {
108
+ fileIn.close();
109
+ } catch (Exception e) {
110
+ e.printStackTrace();
111
+ //Don't care about exceptions at this point.
112
+ }
113
+ }
114
+ }
115
+
116
+ private void setBaseUrlFromUrl(URL url) throws FileNotFoundException
117
+ {
118
+ String u = url.toString();
119
+ String s;
120
+ if (u.lastIndexOf('/') == -1) {
121
+ s = url.getProtocol() + ":";
122
+ } else {
123
+ s = u.substring(0, u.lastIndexOf('/') + 1);
124
+ }
125
+ try {
126
+ setBaseUrl(new URL(s));
127
+ }
128
+ catch (MalformedURLException e) {
129
+ throw new FileNotFoundException(e.getMessage());
130
+ }
131
+ }
132
+
133
+ /*
134
+ * Takes a file name and sets the base path to the directory
135
+ * containing that file.
136
+ */
137
+ private void setBasePathFromFilename(String fileName)
138
+ {
139
+ if (fileName.lastIndexOf(java.io.File.separator) == -1) {
140
+ // No path given - current directory
141
+ setBasePath("." + java.io.File.separator);
142
+ } else {
143
+ setBasePath(fileName.substring(0, fileName.lastIndexOf(java.io.File.separator)));
144
+ }
145
+ }
146
+
147
+ /**
148
+ * Set the path where files associated with this .obj file are
149
+ * located.
150
+ * Only needs to be called to set it to a different directory
151
+ * from that containing the .obj file.
152
+ */
153
+ public void setBasePath(String pathName)
154
+ {
155
+ String basePath = pathName;
156
+ if (basePath == null || basePath == "")
157
+ basePath = "." + java.io.File.separator;
158
+ basePath = basePath.replace('/', java.io.File.separatorChar);
159
+ basePath = basePath.replace('\\', java.io.File.separatorChar);
160
+ if (!basePath.endsWith(java.io.File.separator))
161
+ basePath = basePath + java.io.File.separator;
162
+ super.setBasePath(basePath);
163
+ }
164
+
165
+ /**
166
+ * Returns true if this loader is loading files
167
+ * from a url.
168
+ */
169
+ public boolean fromUrl()
170
+ {
171
+ return fromUrl;
172
+ }
173
+
174
+ /**
175
+ * gets an image with the specified name.
176
+ * This uses a DefaultTextureImageLoader
177
+ * to load the image if one hasn't been set for
178
+ * this loader.
179
+ * @param imageName name of image to load.
180
+ * @return image corresponding to imageName
181
+ */
182
+ public Image getTextureImage(String imageName)
183
+ {
184
+ try {
185
+ if(textureImageLoader == null)
186
+ {
187
+ textureImageLoader = new DefaultTextureImageLoader(this);
188
+ }
189
+ return textureImageLoader.getTextureImage(imageName);
190
+ }
191
+ catch (IllegalArgumentException e)
192
+ {
193
+ System.out.println(e.getMessage());
194
+ }
195
+ catch (Exception e)
196
+ {
197
+ e.printStackTrace();
198
+ }
199
+ return null;
200
+ }
201
+
202
+ /**
203
+ * Sets the TextureImageLoader to be used
204
+ * when texture images are needed.
205
+ * @param loader the TextureImageLoader that will be used to load images.
206
+ */
207
+ public void setTextureImageLoader(TextureImageLoader loader)
208
+ {
209
+ textureImageLoader = loader;
210
+ }
211
+
212
+ /**
213
+ * Gets a chunk chopper to do all the dirty work.
214
+ *
215
+ * @param inputStream the stream containing the model.
216
+ * @param modelSize size of the model file.
217
+ *
218
+ * @return a java3d scene built from input.
219
+ */
220
+ protected Scene parseChunks(InputStream inputStream, int modelSize)
221
+ {
222
+ ChunkChopper chopper = new ChunkChopper();
223
+ SceneBase base = chopper.loadSceneBase(inputStream, this, modelSize);
224
+ if(!chopper.hasLights())
225
+ {
226
+ addDefaultLights(base.getSceneGroup());
227
+ addDefaultLights(chopper.getGroup());
228
+ }
229
+ return base;
230
+ }
231
+
232
+ /**
233
+ * Adds defaultlights to the group provided
234
+ * similar to the ones 3ds max adds when there are none in the scene.
235
+ * @param group to add the lighting to.
236
+ */
237
+ public static void addDefaultLights(Group group)
238
+ {
239
+ PointLight light1 = new PointLight();
240
+ PointLight light2 = new PointLight();
241
+ light1.setInfluencingBounds(new BoundingSphere(new Point3d(0,0,0), 3000));
242
+ light2.setInfluencingBounds(new BoundingSphere(new Point3d(0,0,0), 3000));
243
+
244
+ Transform3D t1 = new Transform3D(new float[]{1.0f, 0.0f, 0.0f, -900f,
245
+ 0.0f, 1.0f, 0.0f, 1500f,
246
+ 0.0f, 0.0f, 1.0f, 1000f,
247
+ 0.0f, 0.0f, 0.0f, 1.0f});
248
+ Transform3D t2 = new Transform3D(new float[]{1.0f, 0.0f, 0.0f, 900f,
249
+ 0.0f, 1.0f, 0.0f, -1500f,
250
+ 0.0f, 0.0f, 1.0f, -1000f,
251
+ 0.0f, 0.0f, 0.0f, 1.0f});
252
+ TransformGroup group1 = new TransformGroup(t1);
253
+ TransformGroup group2 = new TransformGroup(t2);
254
+ group1.addChild(light1);
255
+ group2.addChild(light2);
256
+ group.addChild(group1);
257
+ group.addChild(group2);
258
+ }
259
+
260
+ /**
261
+ * Retrieves a file with a given name.
262
+ *
263
+ * @param fileName name of file to retrieve.
264
+ *
265
+ * @return retrieved file.
266
+ */
267
+ private File getFile(String fileName)
268
+ {
269
+ File file = null;
270
+ try {
271
+ file = new File(fileName);
272
+ if (!file.exists()) {
273
+ throw new IOException(fileName + " doesn't exist");
274
+ }
275
+ } catch (IOException ioe) {
276
+ ioe.printStackTrace();
277
+ }
278
+
279
+ return file;
280
+ }
281
+
282
+ /**
283
+ * throws UnsupportedOperationException
284
+ *
285
+ * @param url url of model to be loaded.
286
+ *
287
+ * @return a java3d scene represented in url
288
+ *
289
+ * @throws FileNotFoundException if file couldn't be found.
290
+ */
291
+ public Scene load(URL url) throws FileNotFoundException
292
+ {
293
+ fromUrl = true;
294
+ try {
295
+ URLConnection connection = url.openConnection();
296
+ if (baseUrl == null)
297
+ setBaseUrlFromUrl(url);
298
+
299
+ return parseChunks(connection.getInputStream(), connection.getContentLength());
300
+ } catch (Exception e) {
301
+ e.printStackTrace();
302
+ throw new IllegalArgumentException("Url " + url + " cannot be loaded");
303
+
304
+ }
305
+ }
306
+
307
+ /**
308
+ * Turn on debug mode for all 3ds xml.
309
+ */
310
+ public void turnOnDebug()
311
+ {
312
+ if (!debugMode) {
313
+ ChunkChopper.debug = true;
314
+ debugMode = true;
315
+ }
316
+ }
317
+}
com/microcrowd/loader/java3d/max3ds/Main.java
....@@ -0,0 +1,454 @@
1
+/**
2
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
3
+ * Microcrowd.com
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+ *
19
+ * Contact Josh DeFord jdeford@microcrowd.com
20
+ */
21
+
22
+package com.microcrowd.loader.java3d.max3ds;
23
+
24
+import java.applet.Applet;
25
+import java.awt.BorderLayout;
26
+import java.awt.GraphicsDevice;
27
+import java.awt.GraphicsEnvironment;
28
+import java.awt.event.ActionEvent;
29
+import java.awt.event.ActionListener;
30
+import java.io.File;
31
+import java.io.IOException;
32
+import java.net.MalformedURLException;
33
+import java.net.URL;
34
+import javax.media.j3d.Behavior;
35
+import javax.media.j3d.BoundingSphere;
36
+import javax.media.j3d.BranchGroup;
37
+import javax.media.j3d.Canvas3D;
38
+import javax.media.j3d.GraphicsConfigTemplate3D;
39
+import javax.media.j3d.Interpolator;
40
+import javax.media.j3d.Locale;
41
+import javax.media.j3d.PhysicalBody;
42
+import javax.media.j3d.PhysicalEnvironment;
43
+import javax.media.j3d.RotPosPathInterpolator;
44
+import javax.media.j3d.Transform3D;
45
+import javax.media.j3d.TransformGroup;
46
+import javax.media.j3d.TransformInterpolator;
47
+import javax.media.j3d.View;
48
+import javax.media.j3d.ViewPlatform;
49
+import javax.media.j3d.VirtualUniverse;
50
+import javax.swing.JFileChooser;
51
+import javax.swing.JMenu;
52
+import javax.swing.JMenuBar;
53
+import javax.swing.JMenuItem;
54
+import javax.swing.filechooser.FileFilter;
55
+import javax.vecmath.Point3d;
56
+import javax.vecmath.Point3f;
57
+import javax.vecmath.Quat4f;
58
+import com.sun.j3d.loaders.Scene;
59
+import com.sun.j3d.utils.applet.MainFrame;
60
+import com.sun.j3d.utils.behaviors.keyboard.KeyNavigatorBehavior;
61
+
62
+
63
+/**
64
+ * Provides an example of loader usage with key navigation.
65
+ * If loaded as an applet expects a 'url' parameter tag which
66
+ * must be specified as a fully qualified url. If there isn't a
67
+ * url tag it looks for an applet parameter called filename.
68
+ * If this is run from the command line it will try to load
69
+ * the file passed in at the prompt, unless a command line argument
70
+ * 'url' is the first argument. Then it will load the url represented
71
+ * as the second command argument.
72
+ */
73
+public class Main extends Applet
74
+{
75
+ private BoundingSphere bounds = new BoundingSphere(new Point3d(0.0,0.0,0.0),3000.0);
76
+ private Canvas3D canvas;
77
+ private String modelLocation;
78
+ private static final String DEFAULT_MODEL = "bounce.3DS";
79
+ private BranchGroup universeBranch;
80
+
81
+ /**
82
+ * If loaded from the command line a modelFile must be provided.
83
+ * args are <filename> or url <url>
84
+ */
85
+ public static void main(String args[])
86
+ {
87
+ Main self = new Main();
88
+ if(args.length > 0)
89
+ self.modelLocation = args[0];
90
+
91
+ MainFrame mainFrame = new MainFrame(self, 750, 550);
92
+ }
93
+
94
+ /**
95
+ * Initializes applet. If this is loaded from a command
96
+ * line the model is loaded from the parameters provided.
97
+ * If it is loaded from an applet the parameter tag 'model'
98
+ * is checked for a path to a model.
99
+ */
100
+ public void init()
101
+ {
102
+ try
103
+ {
104
+ URL location = null;
105
+ if(modelLocation == null)
106
+ {
107
+ location = findAFile(DEFAULT_MODEL);
108
+ }
109
+ else
110
+ {
111
+ location = findAFile(modelLocation);
112
+ }
113
+
114
+ if(location == null)
115
+ throw new IllegalArgumentException("No model was found when attempting to retrieve " +
116
+ (modelLocation == null ? DEFAULT_MODEL : modelLocation));
117
+
118
+ GraphicsConfigTemplate3D config = new GraphicsConfigTemplate3D();
119
+ config.setSceneAntialiasing(GraphicsConfigTemplate3D.PREFERRED);
120
+ GraphicsDevice gd[] = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices();
121
+ canvas = new Canvas3D(gd[0].getBestConfiguration(config));
122
+
123
+ setLayout(new BorderLayout());
124
+ add("Center", canvas);
125
+
126
+ JMenuBar menuBar = new JMenuBar();
127
+ JMenu fileMenu = new JMenu("File");
128
+ JMenuItem menuItem = new JMenuItem("Open");
129
+ add(menuBar, "North");
130
+ menuBar.add(fileMenu);
131
+ fileMenu.add(menuItem);
132
+ menuItem.addActionListener(new BrowseListener());
133
+
134
+ View view = new View();
135
+
136
+ Scene scene = getScene(location);
137
+ universeBranch = createUniverse(view, scene);
138
+ view.addCanvas3D(canvas);
139
+
140
+ addSceneToBranch(universeBranch, scene);
141
+ }
142
+ catch(Exception e){
143
+ e.printStackTrace();
144
+ usage(e.getMessage());
145
+ }
146
+ }
147
+
148
+ /**
149
+ * Adds the scene to the branch and turns on the scene's
150
+ * behaviors.
151
+ */
152
+ private void addSceneToBranch(BranchGroup branch, Scene scene)
153
+ {
154
+ turnOnBehaviors(scene.getBehaviorNodes());
155
+ BranchGroup modelGroup = scene.getSceneGroup();
156
+ modelGroup.compile();
157
+ branch.addChild(modelGroup);
158
+ }
159
+
160
+ /**
161
+ * This is called during initialization of the applet,
162
+ */
163
+ public void Main()
164
+ {
165
+ }
166
+
167
+ /**
168
+ * load the scene.
169
+ */
170
+ public Scene getScene(URL location)
171
+ {
172
+ Scene scene = null;
173
+
174
+ try
175
+ {
176
+ return new Loader3DS().load(location);
177
+ }
178
+ catch(IOException e){
179
+ e.printStackTrace();
180
+ usage(e.getMessage());
181
+ }
182
+ return null;
183
+ }
184
+
185
+
186
+ /**
187
+ * Turns on all the behaviors provided.
188
+ * @param bahaviors the behaviors to enable.
189
+ */
190
+ public void turnOnBehaviors(Behavior[] behaviors)
191
+ {
192
+ if(behaviors == null)
193
+ return;
194
+ for(int i=0; i < behaviors.length; i++)
195
+ {
196
+
197
+ behaviors[i].setEnable(true);
198
+ if(behaviors[i] instanceof Interpolator)
199
+ {
200
+ ((Interpolator)behaviors[i]).setSchedulingBounds(new BoundingSphere(new Point3d(), 3000));
201
+ }
202
+ if(behaviors[i] instanceof TransformInterpolator)
203
+ {
204
+ ((TransformInterpolator)behaviors[i]).getTarget().setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
205
+ }
206
+ }
207
+ }
208
+
209
+ /**
210
+ * Adds an interpolator that will be added to
211
+ * the view transform so that it may be used to
212
+ * switched cameras later.
213
+ * @param target the target that the interpolator will operate on
214
+ */
215
+ private void addCameraInterpolator(TransformGroup target)
216
+ {
217
+ Interpolator cameraInterpolator = new RotPosPathInterpolator(
218
+ null, target, new Transform3D(), new float[]{0,1},
219
+ new Quat4f[]{new Quat4f(), new Quat4f()}, new Point3f[]{new Point3f(), new Point3f()});
220
+ cameraInterpolator.setSchedulingBounds(bounds);
221
+ target.addChild(cameraInterpolator);
222
+ }
223
+ /**
224
+ * Constructs a scene graph.
225
+ * <ol>
226
+ * <li>Creates a branch group
227
+ * <li>Adds the parent transform group to it.
228
+ * </ol>
229
+ */
230
+ public BranchGroup createSceneGraph() {
231
+ BranchGroup root = new BranchGroup();
232
+ TransformGroup parentGroup = new TransformGroup();
233
+
234
+ parentGroup.setCapability(TransformGroup.ENABLE_PICK_REPORTING);
235
+ parentGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
236
+ parentGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
237
+ parentGroup.setCapability(TransformGroup.ALLOW_CHILDREN_READ);
238
+ parentGroup.setCapability(TransformGroup.ALLOW_CHILDREN_WRITE);
239
+ parentGroup.setCapability(TransformGroup.ALLOW_CHILDREN_EXTEND);
240
+
241
+ root.addChild(parentGroup);
242
+
243
+ return root;
244
+ }
245
+
246
+ /**
247
+ * Creates a universe with a locale turns the scene graph.
248
+ * Builds a scene branch group and adds it to the locale.
249
+ * Builds a view platform that uses the provided view and adds
250
+ * that to the locale.
251
+ * @param view the view to use in the view platform
252
+ * @param scene the scene to grab a camera from as a default view
253
+ *
254
+ * @return the root group of the scene branch of the universe. This
255
+ * is what other groups for display are added to.
256
+ */
257
+ public BranchGroup createUniverse(View view, Scene scene)
258
+ {
259
+ VirtualUniverse universe = new VirtualUniverse();
260
+ Locale locale = new Locale(universe);
261
+ BranchGroup sceneBranch = createSceneGraph();
262
+ BranchGroup viewBranchGroup = new BranchGroup();
263
+ sceneBranch.setCapability(BranchGroup.ALLOW_CHILDREN_EXTEND);
264
+ viewBranchGroup.setCapability(BranchGroup.ALLOW_CHILDREN_EXTEND);
265
+ ViewPlatform platform = new ViewPlatform();
266
+
267
+ TransformGroup viewTransformGroup = new TransformGroup();
268
+ viewTransformGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
269
+ viewTransformGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
270
+ viewTransformGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
271
+
272
+ TransformGroup[] viewGroups = scene.getViewGroups();
273
+ Transform3D viewTransform = new Transform3D();
274
+ if(viewGroups != null && viewGroups.length > 0)
275
+ {
276
+ viewGroups[0].getTransform(viewTransform);
277
+ }
278
+
279
+ addViewKeyBehavior(viewTransformGroup);
280
+ viewTransformGroup.setTransform(viewTransform);
281
+
282
+ addCameraInterpolator(viewTransformGroup);
283
+ viewTransformGroup.addChild(platform);
284
+ viewBranchGroup.addChild(viewTransformGroup);
285
+
286
+ platform.setViewAttachPolicy(View.RELATIVE_TO_FIELD_OF_VIEW);
287
+ platform.setActivationRadius(100);
288
+
289
+ configureView(platform, view);
290
+ sceneBranch.setCapability(BranchGroup.ALLOW_DETACH);
291
+
292
+ viewBranchGroup.compile();
293
+ sceneBranch.compile();
294
+ locale.addBranchGraph(viewBranchGroup);
295
+ locale.addBranchGraph(sceneBranch);
296
+ return sceneBranch;
297
+ }
298
+
299
+ /**
300
+ * Adds a behavior to the view that listens to the canvas.
301
+ * This allows 1st person navigation.
302
+ */
303
+ public void addViewKeyBehavior(TransformGroup viewTransformGroup)
304
+ {
305
+ KeyNavigatorBehavior keyBehavior = new KeyNavigatorBehavior(canvas, viewTransformGroup);
306
+ keyBehavior.setSchedulingBounds(bounds);
307
+ //keyBehavior.setMovementRate(100.0f);
308
+ viewTransformGroup.addChild(keyBehavior);
309
+ }
310
+
311
+ /**
312
+ * Creates a physical environment and physical body and
313
+ * adds it them the view which is configured to use
314
+ * a regular screen display for configuration. The view is
315
+ * attached to the platform.
316
+ * @param platform the platform which will have the view attached to it.
317
+ * @param view the view to which the body and environment will be added.
318
+ * canvas 3d added to it.
319
+ */
320
+ protected void configureView(ViewPlatform platform, View view)
321
+ {
322
+ PhysicalBody body = new PhysicalBody();
323
+ PhysicalEnvironment environment = new PhysicalEnvironment();
324
+
325
+ view.setPhysicalEnvironment(environment);
326
+ view.setPhysicalBody(body);
327
+ view.attachViewPlatform(platform);
328
+ view.setBackClipDistance(1000.0);
329
+ view.setFrontClipDistance(1.0);
330
+
331
+
332
+ }
333
+
334
+ public static void usage()
335
+ {
336
+ usage("");
337
+ }
338
+
339
+ public static void usage(String message)
340
+ {
341
+ System.out.println(message);
342
+ System.out.println("This is a sample program for the java3ds loader");
343
+ System.out.println("usage java -jar Loader3DS <model> where model is the 3ds file");
344
+ System.out.println("Textures for the file should be in the same directory as the model");
345
+ System.out.println("If this is being run as an applet a parameter named model (a relative url) may be provided");
346
+ System.exit(1);
347
+ }
348
+
349
+ /**
350
+ * Looks for a file to load. If one
351
+ * cannot be found looks for and loads
352
+ * the default one.
353
+ * @param name, or path of the file to find
354
+ * looks for the following:
355
+ * <ol>
356
+ * <li>a file with the path of fileName
357
+ * <li>a resource in the classpath with fileName
358
+ * <li>a resource in the classpath corresponding to
359
+ * the default file.
360
+ * <li>a url specified in the applet parameter &quot;model&quot;
361
+ * </ol>
362
+ *
363
+ **/
364
+ private URL findAFile(String fileName)
365
+ {
366
+ URL location = null;
367
+ if(fileName != null)
368
+ {
369
+ try
370
+ {
371
+ File file = new File(fileName);
372
+ if (file.exists())
373
+ {
374
+ return file.toURL();
375
+ }
376
+ }
377
+ catch(IOException e)
378
+ {
379
+ e.printStackTrace();
380
+ usage(e.getMessage());
381
+ }
382
+ }
383
+
384
+ if(fileName != null)
385
+ {
386
+ location = Main.class.getClassLoader().getResource(fileName);
387
+ }
388
+ if(location != null)
389
+ {
390
+ return location;
391
+ }
392
+
393
+ String relativeURL = getParameter("model");
394
+ if(relativeURL != null)
395
+ {
396
+ try
397
+ {
398
+ URL codeBase = getCodeBase();
399
+ return new URL(codeBase.toString() + relativeURL);
400
+ }
401
+ catch(MalformedURLException e){
402
+ e.printStackTrace();
403
+ usage(e.getMessage());
404
+ }
405
+ }
406
+
407
+
408
+ return location;
409
+ }
410
+
411
+ private class BrowseListener implements ActionListener
412
+ {
413
+ public void actionPerformed(ActionEvent event)
414
+ {
415
+ File file = null;
416
+ try {
417
+ JFileChooser chooser = new JFileChooser();
418
+ Filter3DS filter = new Filter3DS();
419
+ chooser.setFileFilter(filter);
420
+ chooser.showDialog(Main.this, "wee");
421
+ file = chooser.getSelectedFile();
422
+ if(file == null)
423
+ return;
424
+ Scene scene = getScene(file.toURL());
425
+ addSceneToBranch(universeBranch, scene);
426
+ }
427
+ catch(Exception e){
428
+ e.printStackTrace();
429
+ System.out.println("file not loadable " + file);
430
+ }
431
+ }
432
+ }
433
+
434
+ private class Filter3DS extends FileFilter
435
+ {
436
+ public String getDescription()
437
+ {
438
+ return "3DS Files";
439
+ }
440
+ public boolean accept(File file)
441
+ {
442
+ if (file.isDirectory())
443
+ return true;
444
+ String fileName = file.getName();
445
+ if(fileName.length() < 4)
446
+ return false;
447
+
448
+ String extension = fileName.substring(fileName.length() - 3, fileName.length());
449
+ if(extension.equalsIgnoreCase("3ds"))
450
+ return true;
451
+ return false;
452
+ }
453
+ }
454
+}
com/microcrowd/loader/java3d/max3ds/TextureImageLoader.java
....@@ -0,0 +1,42 @@
1
+/**
2
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
3
+ * Microcrowd.com
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+ *
19
+ * Contact Josh DeFord jdeford@microcrowd.com
20
+ */
21
+package com.microcrowd.loader.java3d.max3ds;
22
+
23
+import java.awt.Image;
24
+
25
+/**
26
+ * Interface specifying a lookup for images to be loaded
27
+ * in textures. Implementations using this loader may need
28
+ * to use different methods to resolve images. In these
29
+ * cases a class should be created that implements
30
+ * this interface. For general purpose applications
31
+ * DefaultTextureImageLoader should be used.
32
+ */
33
+public interface TextureImageLoader
34
+{
35
+
36
+ /**
37
+ * Gets the image to be loaded as a texture.
38
+ * @param imageName the name of the image with which it will be
39
+ * looked up.
40
+ */
41
+ public Image getTextureImage(String imageaName) throws Exception;
42
+}
com/microcrowd/loader/java3d/max3ds/chunks/AxisChunk.java
....@@ -0,0 +1,83 @@
1
+/**
2
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
3
+ * Microcrowd
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+ *
19
+ * Contact Josh DeFord jdeford@microcrowd.com
20
+ */
21
+
22
+package com.microcrowd.loader.java3d.max3ds.chunks;
23
+
24
+import javax.media.j3d.Transform3D;
25
+import javax.vecmath.Point3f;
26
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
27
+
28
+/**
29
+ * Extracts the local coordinate that will act
30
+ * as a shape's axis that will be used by the mesh
31
+ * info chunk.
32
+ */
33
+public class AxisChunk extends Chunk
34
+{
35
+ private float value;
36
+
37
+ /**
38
+ * Loads the local coordinate system for the current mesh.
39
+ *
40
+ * @param chopper the ChunkChopper containing the state of the parser.
41
+ *
42
+ * The location of the local coordinate system is defined relative to
43
+ * positions and rotations at frame 0. But the orientation is absolutely
44
+ * defined.
45
+ *
46
+ * With either 3x3 or 4x4 rotation, translation, there
47
+ * is a simple relationship between each matrix and the resulting coordinate
48
+ * system. The first three columns of the matrix define the direction vector of the
49
+ * X, Y and Z axii respectively.
50
+ * If a 4x4 matrix is defined as:
51
+ * <code>
52
+ * | A B C D |
53
+ * M = | E F G H |
54
+ * | I J K L |
55
+ * | M N O P |
56
+ * </code>
57
+ * Then the direction vector for each axis is as follows:
58
+ *
59
+ * <code>
60
+ * X-axis = [ A E I ]
61
+ * Y-axis = [ B F J ]
62
+ * Z-axis = [ C G K ]
63
+ * </code>
64
+ *
65
+ * @return the actual number of bytes read.
66
+ */
67
+ public void loadData(ChunkChopper chopper)
68
+ {
69
+ Point3f xAxis = new Point3f();
70
+ xAxis = chopper.getPoint();
71
+ Point3f zAxis = chopper.getPoint();
72
+ Point3f yAxis = chopper.getPoint();
73
+ Point3f origin = chopper.getPoint();
74
+
75
+ Transform3D transform = new Transform3D(new double[]{
76
+ xAxis.x, xAxis.y, xAxis.z, origin.x,
77
+ yAxis.x, yAxis.y, yAxis.z, origin.y,
78
+ -zAxis.x, -zAxis.y, -zAxis.z, origin.z,
79
+ 0,0,0,1});
80
+ String meshName = chopper.getObjectName();
81
+ chopper.getKeyFramer().setCoordinateSystem(meshName, transform);
82
+ }
83
+}
com/microcrowd/loader/java3d/max3ds/chunks/BooleanChunk.java
....@@ -0,0 +1,46 @@
1
+/**
2
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
3
+ * Microcrowd.com
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+ *
19
+ * Contact Josh DeFord jdeford@microcrowd.com
20
+ */
21
+
22
+package com.microcrowd.loader.java3d.max3ds.chunks;
23
+
24
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
25
+
26
+/**
27
+ * A boolean chunk is true if it is present otherwise
28
+ * there is no chunk and that represents false. This chunk
29
+ * will set chopper data to Boolean true with a key that is the id of the chunk.
30
+ * These have no subchunks. Only String data.
31
+ */
32
+public class BooleanChunk extends Chunk
33
+{
34
+ /**
35
+ * If this method is being called then
36
+ * a boolean true will be set on the chunk chopper
37
+ * with a key that is the id of this chunk.
38
+ *
39
+ * @param chopper the chopper on which the boolean true data is to be set
40
+ *
41
+ */
42
+ public void loadData(ChunkChopper chopper)
43
+ {
44
+ chopper.pushData(chopper.getID(), new Boolean(true));
45
+ }
46
+}
com/microcrowd/loader/java3d/max3ds/chunks/BoundingBoxChunk.java
....@@ -0,0 +1,55 @@
1
+/**
2
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
3
+ * Microcrowd.com
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+ *
19
+ * Contact Josh DeFord jdeford@microcrowd.com
20
+ */
21
+
22
+package com.microcrowd.loader.java3d.max3ds.chunks;
23
+
24
+import javax.media.j3d.BoundingBox;
25
+import javax.vecmath.Point3d;
26
+import javax.vecmath.Point3f;
27
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
28
+
29
+/**
30
+ * Loads the bounding box for keyframer of mesh. The pivot
31
+ * is relative to it.
32
+ * {@see KeyFramerInfoChunk} for more information about using
33
+ * animations from a 3ds file
34
+ */
35
+public class BoundingBoxChunk extends Chunk
36
+{
37
+ /**
38
+ * Gets the bounding box and associates it with the current mes.
39
+ * @param chopper the ChunkChopper containing the state of the parser.
40
+ */
41
+ public void loadData(ChunkChopper chopper)
42
+ {
43
+ Point3f min = chopper.getPoint();
44
+ Point3f max = chopper.getPoint();
45
+ BoundingBox box = new BoundingBox(new Point3d(min), new Point3d(max));
46
+
47
+ Point3f center = new Point3f(max.x - min.x,
48
+ max.y - min.y,
49
+ max.z - min.z);
50
+
51
+ //chopper.getKeyFramer().setBoundingBox(box);
52
+ chopper.getKeyFramer().setPivotCenter(center);
53
+ }
54
+
55
+}
com/microcrowd/loader/java3d/max3ds/chunks/CameraChunk.java
....@@ -0,0 +1,65 @@
1
+/**
2
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
3
+ * Microcrowd.com
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+ *
19
+ * Contact Josh DeFord jdeford@microcrowd.com
20
+ */
21
+
22
+package com.microcrowd.loader.java3d.max3ds.chunks;
23
+
24
+import javax.media.j3d.Transform3D;
25
+import javax.media.j3d.TransformGroup;
26
+import javax.vecmath.Point3d;
27
+import javax.vecmath.Vector3d;
28
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
29
+/**
30
+ * Loads percentage values from binary data representing them.
31
+ */
32
+public class CameraChunk extends Chunk
33
+{
34
+ /**
35
+ * Reads the position and target vectors and subtracts them to get
36
+ * an axis of rotation. Translate a transform to position and rotate
37
+ * on the axis of rotation to point at the target. The angle
38
+ * between the z axis and the axis of rotation is the angle used to
39
+ * rotate. The translated and rotated vector is stored it the
40
+ * chopper as a named object since camera chunks are named.
41
+ */
42
+ public void loadData(ChunkChopper chopper)
43
+ {
44
+ Vector3d yVector = new Vector3d(0,1,0);
45
+ Point3d position = new Point3d(chopper.getPoint());
46
+ Point3d target = new Point3d(chopper.getPoint());
47
+ float bank = chopper.getFloat();
48
+ float lens = chopper.getFloat();
49
+
50
+ //This is the vector for the direction
51
+ //of the camera. Represented as a line
52
+ //from target to position. We'll use it
53
+ //as an axis when we bank.
54
+ //Vector3d cameraDirection = new Vector3d();
55
+ //cameraDirection.sub(target,position);
56
+ //AxisAngle4f bankAxisAngle = new AxisAngle4f(cameraDirection, bankAngle);
57
+
58
+
59
+ Transform3D transform = new Transform3D();
60
+ transform.lookAt(position, target, yVector);
61
+ transform.invert();
62
+ ((TransformGroup)chopper.getGroup()).setTransform(transform);
63
+ chopper.addViewGroup(chopper.getGroup());
64
+ }
65
+}
com/microcrowd/loader/java3d/max3ds/chunks/Chunk.java
....@@ -0,0 +1,139 @@
1
+/**
2
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
3
+ * Microcrowd.com
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+ *
19
+ * Contact Josh DeFord jdeford@microcrowd.com
20
+ */
21
+
22
+package com.microcrowd.loader.java3d.max3ds.chunks;
23
+
24
+import java.util.HashMap;
25
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
26
+
27
+/**
28
+ * The base class for all chunks. Chunks are flyweights and should be managed
29
+ * by {@link ChunkChopper} Every chunk should know how many bytes of data(or
30
+ * be able figure out) to read before its subchunks are found. Chunks that only have
31
+ * subchunks need not overrided loadData.
32
+ * Chunks may store data for later use in loadData with {@link pushData}
33
+ * If a chunk needs to initialize components with from subchunks, that data
34
+ * can be retrieved with {@link ChunkChopper#popData} inside the {@link
35
+ * #initialize} method. {@link #loadData} is called at the beginning of the
36
+ * loading process, before any data or subchunks have been loaded(the chunk
37
+ * itself must load its data).
38
+ * <p>
39
+ * During loadData, if the length of data before subchunks is unknown,
40
+ * {@link ChunkChopper#getChunkBytes} may be called and all the data
41
+ * for the chunk(including subchunks) will be read and returned.
42
+ */
43
+public class Chunk
44
+{
45
+ private HashMap subChunkMap = new HashMap();
46
+ private String name;
47
+ private String description;
48
+
49
+ /**
50
+ * default no-arg constructror.
51
+ */
52
+ public Chunk(String chunkName)
53
+ {
54
+ name = chunkName;
55
+ }
56
+
57
+ /**
58
+ * default no-arg constructror.
59
+ */
60
+ public Chunk()
61
+ {
62
+ }
63
+
64
+ public void addSubChunk(Integer id, Chunk subChunk)
65
+ {
66
+ subChunkMap.put(id, subChunk);
67
+ }
68
+
69
+ public Chunk getSubChunk(Integer id)
70
+ {
71
+ return (Chunk)subChunkMap.get(id);
72
+ }
73
+
74
+ /**
75
+ * This method is called after all the current chunks subchunks are
76
+ * loaded. Any data stored by those subchunks may be retrieved via {@link
77
+ * ChunkChopper#popData}
78
+ * The default implementation does nothing.
79
+ *
80
+ * @param chopper may contain data loaded by subchunks.
81
+ */
82
+ public void initialize(ChunkChopper chopper)
83
+ {
84
+ }
85
+
86
+ /**
87
+ * This is called by the chunk chopper before any of the chunk's
88
+ * subchunks are loaded. Any data loaded that may need to be
89
+ * used later by superchunks should be stored in
90
+ * the chunk chopper via {@link ChunkChopper#popData}
91
+ * The default implementation does nothing.
92
+ * @param chopper may contain data loaded by subchunks.
93
+ */
94
+ public void loadData(ChunkChopper chopper)
95
+ {
96
+ }
97
+
98
+ /**
99
+ * Sets nice human readable name for the chunk.
100
+ * @param name to use for display of this chunk.
101
+ */
102
+ public final void setName(String name)
103
+ {
104
+ this.name = name;
105
+ }
106
+
107
+ /**
108
+ * Gets a human readable name for the chunk.
109
+ * @return name used to display the chunk.
110
+ */
111
+ public final String getName()
112
+ {
113
+ return name;
114
+ }
115
+
116
+ public final String getDescription()
117
+ {
118
+ return description;
119
+ }
120
+
121
+ public final void setDescription(String desc)
122
+ {
123
+ description = desc;
124
+ }
125
+
126
+ /**
127
+ * Returns the name of this chunk.
128
+ * If the name is null then it just
129
+ * returns the unqualified class name.
130
+ */
131
+ public String toString()
132
+ {
133
+ if (getName() != null)
134
+ return getName();
135
+ String className = getClass().getName();
136
+ return className.substring(className.lastIndexOf('.') + 1,
137
+ className.length());
138
+ }
139
+}
com/microcrowd/loader/java3d/max3ds/chunks/ColorChunk.java
....@@ -0,0 +1,82 @@
1
+/**
2
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
3
+ * Microcrowd.com
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+ *
19
+ * Contact Josh DeFord jdeford@microcrowd.com
20
+ */
21
+
22
+package com.microcrowd.loader.java3d.max3ds.chunks;
23
+
24
+import javax.vecmath.Color3f;
25
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
26
+
27
+/**
28
+ * Loads colors from binary data representing them.
29
+ */
30
+public class ColorChunk extends Chunk
31
+{
32
+ protected int currentColorType;
33
+
34
+ private static final int FLOAT_COLOR = 0x10;
35
+ private static final int BYTE_COLOR = 0x11;
36
+ private static final int BYTE_COLOR_GAMMA = 0x12;
37
+ private static final int FLOAT_COLOR_GAMMA = 0x13;
38
+
39
+ /**
40
+ * Based on the color type retrieved
41
+ * from {@link #getColorType} loads
42
+ * an rgb or float color and pushes
43
+ * it onto the chunk chopper.
44
+ *
45
+ * @param chopper the chopper that will store the color data.
46
+ */
47
+ public void loadData(ChunkChopper chopper)
48
+ {
49
+ int colorType = getColorType(chopper);
50
+ if (colorType == BYTE_COLOR)
51
+ {
52
+ float r = (chopper.getUnsignedByte()) / 255f;
53
+ float g = (chopper.getUnsignedByte()) / 255f;
54
+ float b = (chopper.getUnsignedByte()) / 255f;
55
+ Color3f color = new Color3f(r, g, b);
56
+ chopper.pushData(chopper.getID(), color);
57
+ }
58
+ else if (colorType == FLOAT_COLOR)
59
+ {
60
+ Color3f color = new Color3f(chopper.getFloat(), chopper.getFloat(), chopper.getFloat());
61
+ chopper.pushData(chopper.getID(), color);
62
+ }
63
+ else
64
+ {
65
+ throw new IllegalArgumentException("Only RGB colors are enabled. ChunkID="
66
+ + Integer.toHexString((byte)chopper.getID().intValue())
67
+ + " Color type = " + Integer.toHexString((byte)colorType));
68
+ }
69
+ }
70
+
71
+ /**
72
+ * Gets the color type for this chunk.
73
+ * @param chopper with the information the
74
+ * chunk may use to determine color type
75
+ * @return the color type for the chunk retrieved
76
+ * from the chopper using this chunks id.
77
+ */
78
+ protected int getColorType(ChunkChopper chopper)
79
+ {
80
+ return chopper.getID().intValue();
81
+ }
82
+}
com/microcrowd/loader/java3d/max3ds/chunks/FacesDescriptionChunk.java
....@@ -0,0 +1,322 @@
1
+/**
2
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
3
+ * Microcrowd.com
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+ *
19
+ * Contact Josh DeFord jdeford@microcrowd.com
20
+ */
21
+
22
+package com.microcrowd.loader.java3d.max3ds.chunks;
23
+
24
+import java.util.HashMap;
25
+import java.util.HashSet;
26
+import java.util.Iterator;
27
+import java.util.Set;
28
+import javax.media.j3d.Appearance;
29
+import javax.media.j3d.Geometry;
30
+import javax.media.j3d.Material;
31
+import javax.media.j3d.Shape3D;
32
+import javax.media.j3d.TransformGroup;
33
+import javax.vecmath.Color3f;
34
+import javax.vecmath.Point3f;
35
+import javax.vecmath.TexCoord2f;
36
+import javax.vecmath.Vector3f;
37
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
38
+import com.microcrowd.loader.java3d.max3ds.ChunkMap;
39
+import com.sun.j3d.utils.geometry.GeometryInfo;
40
+import com.sun.j3d.utils.geometry.NormalGenerator;
41
+import com.sun.j3d.utils.geometry.Stripifier;
42
+
43
+/**
44
+ * This chunk describes all the triangles that make up a mesh.
45
+ * Each triangle is defined in terms of three indexes each of which
46
+ * is a point reference to a vertex in the vertex list loaded
47
+ * by the triangular mesh chunk.
48
+ * After loading the Smoothing chunk the normals for the mesh
49
+ * are generated accordingly.
50
+ */
51
+public class FacesDescriptionChunk extends Chunk
52
+{
53
+ public static final Appearance DEFAULT_APPEARANCE;
54
+
55
+ private Point3f[] currentVertices;
56
+ private TexCoord2f[] textureTriangles;
57
+ private PointMapper shareMap;
58
+
59
+ static {
60
+ DEFAULT_APPEARANCE= new Appearance();
61
+ Material defaultMaterial = new Material();
62
+ defaultMaterial.setAmbientColor(new Color3f(.5f, .5f, .5f));
63
+ //defaultMaterial.setDiffuseColor(new Color3f(.5f, .5f, .5f));
64
+ //defaultMaterial.setSpecularColor(new Color3f(.5f, .5f, .5f));
65
+ DEFAULT_APPEARANCE.setMaterial(defaultMaterial);
66
+ }
67
+
68
+
69
+
70
+ /**
71
+ * Maintains a two way mapping between coordinates
72
+ * and vertices. A coordinate to vertex is one to many
73
+ * Vertex to coordinate is one to one.
74
+ * In this class we maintain the definition that a coordinate
75
+ * is a point in 3D space and a vertex is a coordinate serving
76
+ * as one of three defining a face.
77
+ */
78
+ private class PointMapper extends HashMap
79
+ {
80
+ private Set[] coordinateSet;
81
+ /**
82
+ * Constructs a PointMapper with a
83
+ * the number of coordinates initialized to size.
84
+ * @param size the number of coordinates in the set.
85
+ */
86
+ public PointMapper(int size)
87
+ {
88
+ coordinateSet = new Set[size];
89
+ }
90
+
91
+ /**
92
+ * Adds an index for a coordinate to the set of vertices mapped
93
+ * to that coordinate. All coordinates may have one or more vertices
94
+ * that use them.
95
+ * @param coordinate the coordinate being mapped to the vertexNum
96
+ * @param vertexNum the number of the vertex using the coordinate
97
+ */
98
+ public void addCoordinate(Point3f coordinate, int vertexNum)
99
+ {
100
+ Set sharedCoordinates = (Set)get(coordinate);
101
+ if(sharedCoordinates == null)
102
+ {
103
+ sharedCoordinates = new HashSet();
104
+ put(coordinate, sharedCoordinates);
105
+ }
106
+ sharedCoordinates.add(new Integer(vertexNum));
107
+ coordinateSet[vertexNum] = sharedCoordinates;
108
+ }
109
+
110
+ /**
111
+ * Gets all the coordinates for a particular vertex that
112
+ * also share that vertex after the smoothing groups have been
113
+ * accounted for. Any coordinates that are not both shared
114
+ * by the vertex and do not share a smoothing group with the coordinate
115
+ * will not be returned.
116
+ * @param coordinateNum the number of the coordinate to get the set
117
+ * of vertices for that share it.
118
+ * @param smoothGroups the group of coordinates used to filter out the
119
+ * non-shared vertices.
120
+ */
121
+ public Set getSharedCoordinates(int coordinateNum, int[] smoothGroups)
122
+ {
123
+ Set returnSet = new HashSet();
124
+ Set sharingVertices = coordinateSet[coordinateNum];
125
+ Iterator vertices = sharingVertices.iterator();
126
+ int coordinateMask = smoothGroups[coordinateNum];
127
+ while(vertices.hasNext())
128
+ {
129
+ Integer vertex = (Integer)vertices.next();
130
+ int nextMask = smoothGroups[vertex.intValue()];
131
+ if((nextMask & coordinateMask) != 0)
132
+ {
133
+ returnSet.add(vertex);
134
+ }
135
+ }
136
+ return returnSet;
137
+ }
138
+ }
139
+
140
+ /**
141
+ * Reads the number of faces from the ChunkChopper.
142
+ * For each face read three shorts representing
143
+ * indices of vertices loaded by the TriangularMeshChunk
144
+ *
145
+ * @param chopper chopper the has the data
146
+ */
147
+ public void loadData(ChunkChopper chopper)
148
+ {
149
+ int numFaces = chopper.getUnsignedShort();
150
+ shareMap = new PointMapper(numFaces*3);
151
+ Point3f[] coordinates = (Point3f[])chopper.popData(ChunkMap.VERTEX_LIST);
152
+ TexCoord2f[] texturePoints = (TexCoord2f[])chopper.popData(ChunkMap.TEXTURE_COORDINATES);
153
+
154
+ currentVertices = new Point3f[numFaces * 3];
155
+ chopper.pushData(chopper.getID(), currentVertices);
156
+ if (texturePoints != null)
157
+ {
158
+ textureTriangles = new TexCoord2f[numFaces * 3];
159
+ }
160
+
161
+ for (int i = 0; i < numFaces; i++) {
162
+ int vertexIndex = i * 3;
163
+ int index0 = chopper.getUnsignedShort();
164
+ int index1 = chopper.getUnsignedShort();
165
+ int index2 = chopper.getUnsignedShort();
166
+
167
+ currentVertices[vertexIndex] = coordinates[index0];
168
+ currentVertices[vertexIndex + 1] = coordinates[index1];
169
+ currentVertices[vertexIndex + 2] = coordinates[index2];
170
+
171
+ shareMap.addCoordinate(coordinates[index0], vertexIndex);
172
+ shareMap.addCoordinate(coordinates[index1], vertexIndex+1);
173
+ shareMap.addCoordinate(coordinates[index2], vertexIndex+2);
174
+
175
+
176
+ if (textureTriangles != null) {
177
+ textureTriangles[vertexIndex] = texturePoints[index0];
178
+ textureTriangles[vertexIndex + 1] = texturePoints[index1];
179
+ textureTriangles[vertexIndex + 2] = texturePoints[index2];
180
+ }
181
+
182
+ //This is a bit masked value that is used to determine which edges are visible... not needed.
183
+ chopper.getUnsignedShort();
184
+ }
185
+ }
186
+
187
+ /**
188
+ * Loads a mesh onto the scene graph with the specified data
189
+ * from subchunks.
190
+ * If there is no material, this will put a default
191
+ * material on the shape.
192
+ */
193
+ public void initialize(ChunkChopper chopper)
194
+ {
195
+ final String materialName = (String)chopper.popData(ChunkMap.FACES_MATERIAL);
196
+ final int[] smoothGroups = (int[])chopper.popData(ChunkMap.SMOOTH);
197
+ Shape3D shape = new Shape3D();
198
+ GeometryInfo geometryInfo = new GeometryInfo(GeometryInfo.TRIANGLE_ARRAY);
199
+
200
+ geometryInfo.setCoordinates(currentVertices);
201
+ TransformGroup transformGroup = (TransformGroup)chopper.getGroup();
202
+ transformGroup.addChild(shape);
203
+
204
+ if (textureTriangles != null)
205
+ {
206
+ geometryInfo.setTextureCoordinateParams(1, 2);
207
+ geometryInfo.setTextureCoordinates(0, textureTriangles);
208
+ }
209
+
210
+ if(materialName != null)
211
+ {
212
+ shape.setAppearance((Appearance)chopper.getNamedObject(materialName));
213
+ }
214
+ else
215
+ {
216
+ shape.setAppearance(DEFAULT_APPEARANCE);
217
+ }
218
+ if(smoothGroups == null)
219
+ {
220
+ NormalGenerator normalGenerator = new NormalGenerator();
221
+ geometryInfo.recomputeIndices();
222
+ normalGenerator.generateNormals(geometryInfo);
223
+ }
224
+ else
225
+ {
226
+ Vector3f[] normals = generateNormals(currentVertices);
227
+ Vector3f[] smoothNormals = smoothNormals(normals, shareMap, smoothGroups);
228
+ geometryInfo.setNormals(smoothNormals);
229
+ }
230
+
231
+ new Stripifier().stripify(geometryInfo);
232
+ shape.setGeometry(geometryInfo.getGeometryArray());
233
+ shape.setCapability(Geometry.ALLOW_INTERSECT);
234
+ com.sun.j3d.utils.picking.PickTool.setCapabilities(shape, com.sun.j3d.utils.picking.PickTool.INTERSECT_FULL);
235
+
236
+ currentVertices=null;
237
+ textureTriangles=null;
238
+ }
239
+
240
+ /**
241
+ * Takes all the normals for all the vertices and averages them with
242
+ * normals with which they share a coordinate and at least one smooth group.
243
+ * @param currentNormals the normals for each face.
244
+ * @param sharedPoints the point mapper that will choose which points are
245
+ * and which are not shared.
246
+ * @param smoothGroups the indexed list of group masks loaded by the smooth chunk.
247
+ * @return normals averaged among the shared vertices in their smoothing groups.
248
+ */
249
+ public Vector3f[] smoothNormals(Vector3f[] currentNormals, PointMapper sharedPoints, int[] smoothGroups)
250
+ {
251
+ Vector3f[] smoothNormals = new Vector3f[currentNormals.length];
252
+ for(int i=0; i < currentNormals.length; i++)
253
+ {
254
+ Set otherPoints = sharedPoints.getSharedCoordinates(i, smoothGroups);
255
+ if(otherPoints != null)
256
+ {
257
+ Vector3f[] sharedNormals = new Vector3f[otherPoints.size()];
258
+ Iterator pointIterator = otherPoints.iterator();
259
+ for(int j = 0; j < sharedNormals.length; j++)
260
+ {
261
+ sharedNormals[j] = currentNormals[((Integer)pointIterator.next()).intValue()];
262
+ }
263
+ smoothNormals[i] = averageNormals(sharedNormals);
264
+ }
265
+ else
266
+ {
267
+ smoothNormals[i] = currentNormals[i];
268
+ }
269
+ }
270
+ return smoothNormals;
271
+ }
272
+
273
+ /**
274
+ * Averages the normals provided in order to provide
275
+ * smooth, noncreased appearances for meshes.
276
+ * @param normals the normals that should be averaged
277
+ * @return a normalized normal that can be used in place
278
+ * of all the normals provided.
279
+ */
280
+ public Vector3f averageNormals(Vector3f[] normals)
281
+ {
282
+ Vector3f newNormal = new Vector3f();
283
+ for(int i=0; i < normals.length; i++)
284
+ {
285
+ newNormal.add(normals[i]);
286
+ }
287
+ newNormal.normalize();
288
+ return newNormal;
289
+ }
290
+
291
+ /**
292
+ * Generates normals for each vertex of each
293
+ * face that are absolutely normal to the face.
294
+ * @param point0 The first point of the face
295
+ * @param point1 The second point of the face
296
+ * @param point2 The third point of the face
297
+ * @return the three normals that should be
298
+ * used for the triangle represented by the parameters.
299
+ */
300
+ private Vector3f[] generateNormals(Point3f points[])
301
+ {
302
+ Vector3f[] normals = new Vector3f[points.length];
303
+ for(int i=0; i < normals.length;)
304
+ {
305
+ Vector3f normal = new Vector3f();
306
+ Vector3f v1 = new Vector3f();
307
+ Vector3f v2 = new Vector3f();
308
+
309
+ v1.sub(points[i+1], points[i]);
310
+ v2.sub(points[i+2], points[i]);
311
+ normal.cross(v1, v2);
312
+ normal.normalize();
313
+
314
+
315
+ normals[i++] = new Vector3f(normal);
316
+ normals[i++] = new Vector3f(normal);
317
+ normals[i++] = new Vector3f(normal);
318
+ }
319
+
320
+ return normals;
321
+ }
322
+}
com/microcrowd/loader/java3d/max3ds/chunks/FacesMaterialChunk.java
....@@ -0,0 +1,59 @@
1
+/**
2
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
3
+ *
4
+ * Microcrowd.com
5
+ *
6
+ * This library is free software; you can redistribute it and/or
7
+ * modify it under the terms of the GNU Lesser General Public
8
+ * License as published by the Free Software Foundation; either
9
+ * version 2.1 of the License, or (at your option) any later version.
10
+ *
11
+ * This library is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
+ * Lesser General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public
17
+ * License along with this library; if not, write to the Free Software
18
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
+ *
20
+ * Contact Josh DeFord jdeford@microcrowd.com
21
+ */
22
+package com.microcrowd.loader.java3d.max3ds.chunks;
23
+
24
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
25
+
26
+/**
27
+ * FacesMaterialsChunk contains the materials information
28
+ * from the 3ds file. It contains information pertaining to
29
+ * which faces of a mesh have materials on them and the
30
+ * texture coordinates for texture mapping.
31
+ * Right now, its just putting the name of the material
32
+ * that needs to be applied to the mesh under construction.
33
+ *
34
+ * @author jdeford
35
+ */
36
+public class FacesMaterialChunk extends Chunk
37
+{
38
+ /**
39
+ * Loads the texture coordinates for a mesh,
40
+ *
41
+ * @param chopper the ChunkChopper containing the state of the parser.
42
+ */
43
+ public void loadData(ChunkChopper chopper)
44
+ {
45
+ final String materialName = chopper.getString();
46
+ int numFaces = chopper.getUnsignedShort();
47
+ if (numFaces > 0)
48
+ {
49
+ for (int j = 0; j < numFaces; j++)
50
+ {
51
+ int index = j * 3;
52
+ int position = chopper.getUnsignedShort() * 3;
53
+ }
54
+ }
55
+
56
+ chopper.pushData(chopper.getID(), materialName);
57
+ }
58
+}
59
+
com/microcrowd/loader/java3d/max3ds/chunks/FloatChunk.java
....@@ -0,0 +1,47 @@
1
+/**
2
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
3
+ * Microcrowd.com
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+ *
19
+ * Contact Josh DeFord jdeford@microcrowd.com
20
+ */
21
+
22
+package com.microcrowd.loader.java3d.max3ds.chunks;
23
+
24
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
25
+
26
+/**
27
+ * These have no subchunks. Only data.
28
+ * Any objects that have a float chunk
29
+ * as a sub chunk may retrieve the float
30
+ * value from {@link ChunkChopper.popData()}
31
+ * using the current chunk id as an argument.
32
+ */
33
+public class FloatChunk extends Chunk
34
+{
35
+ /**
36
+ * Loads a Float value into the chopper
37
+ * for use later when parent chunks are
38
+ * initializing
39
+ *
40
+ * @param chopper the chopper in which the float
41
+ * chunk will be stored by the id of this chunk.
42
+ */
43
+ public void loadData(ChunkChopper chopper)
44
+ {
45
+ chopper.pushData(chopper.getID(), new Float(chopper.getFloat()));
46
+ }
47
+}
com/microcrowd/loader/java3d/max3ds/chunks/FramesChunk.java
....@@ -0,0 +1,45 @@
1
+/**
2
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
3
+ * Microcrowd.com
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+ *
19
+ * Contact Josh DeFord jdeford@microcrowd.com
20
+ */
21
+
22
+package com.microcrowd.loader.java3d.max3ds.chunks;
23
+
24
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
25
+
26
+/**
27
+ * This chunk specifies the beginning and end frames.
28
+ *
29
+ * @author jdeford
30
+ */
31
+public class FramesChunk extends Chunk
32
+{
33
+ /**
34
+ * Reads two ints. Start frame and stop frame.
35
+ *
36
+ * @param chopper the chopper that may be used to store the starting and
37
+ * stopping frames.
38
+ *
39
+ */
40
+ public void loadData(ChunkChopper chopper)
41
+ {
42
+ long start = chopper.getUnsignedInt();
43
+ long stop = chopper.getUnsignedInt();
44
+ }
45
+}
com/microcrowd/loader/java3d/max3ds/chunks/FramesDescriptionChunk.java
....@@ -0,0 +1,59 @@
1
+/**
2
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
3
+ * Microcrowd.com
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+ *
19
+ * Contact Josh DeFord jdeford@microcrowd.com
20
+ */
21
+
22
+package com.microcrowd.loader.java3d.max3ds.chunks;
23
+
24
+
25
+import javax.media.j3d.TransformGroup;
26
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
27
+import com.microcrowd.loader.java3d.max3ds.data.KeyFramer;
28
+/**
29
+ * This chunk contains the name of the object
30
+ * the frames belong to and the parameters and
31
+ * hierarchy information for it.
32
+ */
33
+public class FramesDescriptionChunk extends Chunk
34
+{
35
+ /**
36
+ * reads the name of the object for these frames
37
+ * and stores it in the chopper.
38
+ *
39
+ * @param chopper the chopper used to store the transient data
40
+ * for this chunk.
41
+ */
42
+ public void loadData(ChunkChopper chopper)
43
+ {
44
+ KeyFramer keyFramer = chopper.getKeyFramer();
45
+ String objectName = chopper.getString();
46
+ chopper.setObjectName(objectName);
47
+ chopper.getUnsignedShort();
48
+ chopper.getUnsignedShort();
49
+ int fatherID = chopper.getShort();
50
+ TransformGroup transformGroup = chopper.getNamedTransformGroup(objectName);
51
+ if(transformGroup == null)//its a dummy transformGroup.
52
+ {
53
+ transformGroup = new TransformGroup();
54
+ keyFramer.setDummyObject(transformGroup);
55
+ }
56
+
57
+ keyFramer.addFather(fatherID, transformGroup);
58
+ }
59
+}
com/microcrowd/loader/java3d/max3ds/chunks/GlobalColorChunk.java
....@@ -0,0 +1,45 @@
1
+/**
2
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
3
+ * Microcrowd.com
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+ *
19
+ * Contact Josh DeFord jdeford@microcrowd.com
20
+ */
21
+
22
+package com.microcrowd.loader.java3d.max3ds.chunks;
23
+
24
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
25
+
26
+/**
27
+ * Loads colors from binary data representing them.
28
+ * Its a global in the manner that it reads its own
29
+ * header information.
30
+ */
31
+public class GlobalColorChunk extends ColorChunk
32
+{
33
+ /**
34
+ * Gets the color type for this chunk.
35
+ * @param chopper with the information the
36
+ * chunk may use to determine color type
37
+ * @return the color type for the chunk.
38
+ */
39
+ protected int getColorType(ChunkChopper chopper)
40
+ {
41
+ int type = chopper.getUnsignedShort();
42
+ int colorLength = chopper.getUnsignedInt();
43
+ return type;
44
+ }
45
+}
com/microcrowd/loader/java3d/max3ds/chunks/HierarchyInfoChunk.java
....@@ -0,0 +1,46 @@
1
+/**
2
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
3
+ * Microcrowd.com
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+ *
19
+ * Contact Josh DeFord jdeford@microcrowd.com
20
+ */
21
+package com.microcrowd.loader.java3d.max3ds.chunks;
22
+
23
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
24
+
25
+/**
26
+ * A HierarchyInfoChunk stores information about
27
+ * where an object belong in a hierarchy of object that
28
+ * have animations which may or may not be related.
29
+ * Each object, including dummy objects, have an identifier
30
+ * used to specify them as hierarchical parents of other
31
+ * objects for the purpose of key framing.
32
+ *
33
+ * @author Josh DeFord
34
+ */
35
+public class HierarchyInfoChunk extends Chunk
36
+{
37
+ /**
38
+ * Loads a word of data that describes the parent.
39
+ */
40
+ public void loadData(ChunkChopper chopper)
41
+ {
42
+ int hierarchyIdentifier = chopper.getShort();
43
+ chopper.getKeyFramer().setID(hierarchyIdentifier);
44
+ }
45
+
46
+}
com/microcrowd/loader/java3d/max3ds/chunks/KeyFramerInfoChunk.java
....@@ -0,0 +1,68 @@
1
+/**
2
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
3
+ * Microcrowd.com
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+ *
19
+ * Contact Josh DeFord jdeford@microcrowd.com
20
+ */
21
+package com.microcrowd.loader.java3d.max3ds.chunks;
22
+
23
+import javax.media.j3d.Behavior;
24
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
25
+
26
+/**
27
+ * A KeyFramerInfoChunk stores information about things
28
+ * that happen to meshes: Position information, rotation
29
+ * information, scale information, pivot information
30
+ * and frame information.
31
+ * Together with the frames chunk thes are used
32
+ * display animation behaviors.
33
+ *
34
+ * @author Josh DeFord
35
+ */
36
+public class KeyFramerInfoChunk extends Chunk
37
+{
38
+
39
+ /**
40
+ * Retrieves the named object for the current key framer
41
+ * inserts the rotation, position and pivot transformations for frame 0
42
+ * and assigns the coordinate system to it.
43
+ *
44
+ * The inverse of the local coordinate system converts from 3ds
45
+ * semi-absolute coordinates (what is in the file) to local coordinates.
46
+ *
47
+ * Then these local coordinates are converted with matrix
48
+ * that will instantiate them to absolute coordinates:
49
+ * Xabs = sx a1 (Xl-Px) + sy a2 (Yl-Py) + sz a3 (Zl-Pz) + Tx
50
+ * Yabs = sx b1 (Xl-Px) + sy b2 (Yl-Py) + sz b3 (Zl-Pz) + Ty
51
+ * Zabs = sx c1 (Xl-Px) + sy c2 (Yl-Py) + sz c3 (Zl-Pz) + Tz
52
+ * Where:
53
+ * (Xabs,Yabs,Zabs) = absolute coordinate
54
+ * (Px,Py,Pz) = mesh pivot (constant)
55
+ * (X1,Y1,Z1) = local coordinates
56
+ *
57
+ * @param chopper the ChunkChopper containing the current state of the parser.
58
+ */
59
+ public void initialize(ChunkChopper chopper)
60
+ {
61
+ String meshName = (String)chopper.getObjectName();
62
+ Behavior frameBehavior = chopper.getKeyFramer().createBehavior(meshName,
63
+ chopper.getNamedTransformGroup(meshName),
64
+ chopper.getNamedObject(meshName));
65
+ if(frameBehavior != null)
66
+ chopper.addBehaviorNode(frameBehavior);
67
+ }
68
+}
com/microcrowd/loader/java3d/max3ds/chunks/LightChunk.java
....@@ -0,0 +1,80 @@
1
+/**
2
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
3
+ * Microcrowd.com
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+ *
19
+ * Contact Josh DeFord jdeford@microcrowd.com
20
+ */
21
+package com.microcrowd.loader.java3d.max3ds.chunks;
22
+
23
+import javax.media.j3d.BoundingSphere;
24
+import javax.media.j3d.PointLight;
25
+import javax.media.j3d.Transform3D;
26
+import javax.media.j3d.TransformGroup;
27
+import javax.vecmath.Color3f;
28
+import javax.vecmath.Point3d;
29
+import javax.vecmath.Vector3f;
30
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
31
+import com.microcrowd.loader.java3d.max3ds.ChunkMap;
32
+/**
33
+ * Lights to be placed in a scene.
34
+ * Only point lights and target spot lights are supported.
35
+ * All the default parameters are used for lights as well.
36
+ * Only position is specified.
37
+ */
38
+public class LightChunk extends Chunk
39
+{
40
+ private Vector3f currentPosition;
41
+
42
+ /**
43
+ * This is called by the chunk chopper before any of the chunk's
44
+ * subchunks are loaded. Any data loaded that may need to be
45
+ * used later by superchunks should be stored in
46
+ * the chunk chopper via {@link ChunkChopper#pushData}
47
+ *
48
+ * @param chopper used to store the position of the light.
49
+ */
50
+ public void loadData(ChunkChopper chopper)
51
+ {
52
+ currentPosition = chopper.getVector();
53
+ TransformGroup group = chopper.getGroup();
54
+ Transform3D transform = new Transform3D();
55
+ group.getTransform(transform);
56
+ transform.setTranslation(currentPosition);
57
+ group.setTransform(transform);
58
+ chopper.pushData(chopper.getID(), currentPosition);
59
+ }
60
+
61
+ /**
62
+ * Gets the data put into the chopper by the subchunks
63
+ * and creates a light, adding it to the scene as a named object.
64
+ * @param chopper the ChunkChopper containing sub chunk data.
65
+ */
66
+ public void initialize(ChunkChopper chopper)
67
+ {
68
+ Color3f color = (Color3f)chopper.popData(ChunkMap.COLOR);
69
+ PointLight light = (PointLight)chopper.popData(ChunkMap.SPOTLIGHT);
70
+ if(light == null)
71
+ {
72
+ light = new PointLight();
73
+ chopper.addLightNode(light);
74
+ }
75
+
76
+ light.setColor(color);
77
+ light.setInfluencingBounds(new BoundingSphere(new Point3d(0,0,0), 3000));
78
+ chopper.getGroup().addChild(light);
79
+ }
80
+}
com/microcrowd/loader/java3d/max3ds/chunks/MaterialChunk.java
....@@ -0,0 +1,121 @@
1
+/**
2
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
3
+ * Microcrowd
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+ *
19
+ * Contact Josh DeFord jdeford@microcrowd.com
20
+ */
21
+
22
+package com.microcrowd.loader.java3d.max3ds.chunks;
23
+
24
+import javax.media.j3d.Appearance;
25
+import javax.media.j3d.Material;
26
+import javax.media.j3d.PolygonAttributes;
27
+import javax.media.j3d.Texture;
28
+import javax.media.j3d.TransparencyAttributes;
29
+import javax.vecmath.Color3f;
30
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
31
+import com.microcrowd.loader.java3d.max3ds.ChunkMap;
32
+
33
+
34
+
35
+/**
36
+ * Loads material chunks with ambient, diffuse and specular colors,
37
+ * shininess, transparency, two sidedness and texture.
38
+ */
39
+public class MaterialChunk extends Chunk
40
+{
41
+
42
+ //public static final Integer SELF_ILLUMINATED = new Integer((short)0xA084);
43
+
44
+
45
+ /**
46
+ * This will set the ambient, diffuse and specular
47
+ * colors as well as the textures, two sidedness
48
+ * and transparency of the material.
49
+ *
50
+ * @param chopper the chopper containing the data
51
+ * needed to set the attributes.
52
+ */
53
+ public void initialize(ChunkChopper chopper)
54
+ {
55
+ Appearance appearance = new Appearance();
56
+ Material material = new Material();
57
+
58
+ Color3f ambientColor = (Color3f)chopper.popData(ChunkMap.AMBIENT_COLOR);
59
+ if (ambientColor != null) {
60
+ material.setAmbientColor(ambientColor);
61
+ }
62
+
63
+ Color3f color = (Color3f)chopper.popData(ChunkMap.DIFFUSE_COLOR);
64
+ if (color != null) {
65
+ material.setDiffuseColor(color);
66
+ }
67
+
68
+ color = (Color3f)chopper.popData(ChunkMap.SPECULAR_COLOR);
69
+ if (color != null) {
70
+ material.setSpecularColor(color);
71
+ }
72
+
73
+ Texture texture = (Texture)chopper.popData(ChunkMap.TEXTURE);
74
+ if(texture != null)
75
+ {
76
+ appearance.setTexture(texture);
77
+ }
78
+
79
+ Boolean twoSided = (Boolean)chopper.popData(ChunkMap.TWO_SIDED);
80
+ if (twoSided != null) //Just being there is equivalent to a boolean true.
81
+ {
82
+
83
+ PolygonAttributes polyAttributes = appearance.getPolygonAttributes();
84
+ if(polyAttributes == null)
85
+ {
86
+ polyAttributes = new PolygonAttributes();
87
+ }
88
+
89
+ polyAttributes.setCullFace(PolygonAttributes.CULL_NONE);
90
+ appearance.setPolygonAttributes(polyAttributes);
91
+ }
92
+
93
+ Float transparency = (Float)chopper.popData(ChunkMap.TRANSPARENCY);
94
+ if (transparency != null) {
95
+ if (transparency.floatValue() > 0.01f) {
96
+
97
+ TransparencyAttributes transparencyAttributes = new TransparencyAttributes(TransparencyAttributes.FASTEST, transparency.floatValue());
98
+ appearance.setTransparencyAttributes(transparencyAttributes);
99
+ }
100
+ }
101
+
102
+ String name = (String)chopper.popData(ChunkMap.MATERIAL_NAME);
103
+ Float shininess = (Float)chopper.popData(ChunkMap.SHININESS);
104
+ if (shininess != null)
105
+ {
106
+ float shine = shininess.floatValue() * 1024f;
107
+ material.setShininess(shine);
108
+ }
109
+
110
+ /*
111
+ Boolean illuminated = (Boolean)chopper.popData(SELF_ILLUMINATED);
112
+ if(illuminated != null && illuminated.booleanValue() == true)
113
+ {
114
+ material.setEmissiveColor(ambientColor);
115
+ }
116
+ */
117
+
118
+ appearance.setMaterial(material);
119
+ chopper.setNamedObject(name, appearance);
120
+ }
121
+}
com/microcrowd/loader/java3d/max3ds/chunks/NamedObjectChunk.java
....@@ -0,0 +1,50 @@
1
+/**
2
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
3
+ * Microcrowd.com
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+ *
19
+ * Contact Josh DeFord jdeford@microcrowd.com
20
+ */
21
+
22
+package com.microcrowd.loader.java3d.max3ds.chunks;
23
+
24
+import javax.media.j3d.TransformGroup;
25
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
26
+
27
+/**
28
+ * Loads information about a named object: Cameras, meshes and lights
29
+ */
30
+public class NamedObjectChunk extends Chunk
31
+{
32
+
33
+ /**
34
+ * Adds a TransformGroup the the chopper's branch
35
+ * group to which meshes will be added.
36
+ *
37
+ * @param chopper The chopper containing the state of parsing.
38
+ */
39
+ public void loadData(ChunkChopper chopper)
40
+ {
41
+ final String name = chopper.getString();
42
+ TransformGroup transformGroup = new TransformGroup();
43
+
44
+ transformGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
45
+ transformGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
46
+ transformGroup.setCapability(TransformGroup.ENABLE_PICK_REPORTING);
47
+
48
+ chopper.addObject(name, transformGroup);
49
+ }
50
+}
com/microcrowd/loader/java3d/max3ds/chunks/PercentageChunk.java
....@@ -0,0 +1,59 @@
1
+/**
2
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
3
+ * Microcrowd.com
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+ *
19
+ * Contact Josh DeFord jdeford@microcrowd.com
20
+ */
21
+
22
+package com.microcrowd.loader.java3d.max3ds.chunks;
23
+
24
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
25
+
26
+/**
27
+ * Loads percentage values from binary data representing them.
28
+ */
29
+public class PercentageChunk extends Chunk
30
+{
31
+ /** Represents an int percentage */
32
+ public static final int INT = 0x30;
33
+
34
+ /** Represents a float percentage */
35
+ public static final int FLOAT = 0x31;
36
+ private float percentage;
37
+
38
+ /**
39
+ * Gets tye type of percentage, reads it
40
+ * and sets the value on the chopper using
41
+ * the id of the current chunk as the key.
42
+ *
43
+ */
44
+ public void loadData(ChunkChopper chopper)
45
+ {
46
+ int percentageType = chopper.getUnsignedShort();
47
+ int percentageLength = chopper.getUnsignedInt();
48
+ if (percentageType == INT) {
49
+ percentage = (chopper.getUnsignedShort()) / 100f;
50
+ chopper.pushData(chopper.getID(), new Float(percentage));
51
+ } else if (percentageType == FLOAT) {
52
+ percentage = chopper.getFloat() / 100f;
53
+ chopper.pushData(chopper.getID(), new Float(percentage));
54
+ } else {
55
+ throw new IllegalArgumentException("Only float and int percentages are enabled.");
56
+ }
57
+
58
+ }
59
+}
com/microcrowd/loader/java3d/max3ds/chunks/PivotChunk.java
....@@ -0,0 +1,45 @@
1
+/**
2
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
3
+ * Microcrowd.com
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+ *
19
+ * Contact Josh DeFord jdeford@microcrowd.com
20
+ */
21
+
22
+package com.microcrowd.loader.java3d.max3ds.chunks;
23
+
24
+import javax.vecmath.Point3f;
25
+import javax.vecmath.Vector3f;
26
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
27
+/**
28
+ * Loads the pivot for a mesh.
29
+ * {@see KeyFramerInfoChunk} for more information about using
30
+ * animations from a 3ds file
31
+ */
32
+public class PivotChunk extends Chunk
33
+{
34
+ /**
35
+ * Gets the pivot and associates it with the current mes.
36
+ * @param chopper the ChunkChopper containing the state of the parser.
37
+ */
38
+ public void loadData(ChunkChopper chopper)
39
+ {
40
+ Vector3f pivot = new Vector3f((Point3f)chopper.getPoint());
41
+
42
+ chopper.getKeyFramer().setPivot(pivot);
43
+ }
44
+
45
+}
com/microcrowd/loader/java3d/max3ds/chunks/PositionChunk.java
....@@ -0,0 +1,63 @@
1
+/**
2
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
3
+ * Microcrowd.com
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+ *
19
+ * Contact Josh DeFord jdeford@microcrowd.com
20
+ */
21
+
22
+package com.microcrowd.loader.java3d.max3ds.chunks;
23
+
24
+import java.util.ArrayList;
25
+import javax.vecmath.Point3f;
26
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
27
+
28
+/**
29
+ * Loads the position of a mesh as defined in the 3ds file.
30
+ * This position may need to be converted to another coordinate
31
+ * system by KeyFramerInfoChunk.
32
+ * * {@see KeyFramerInfoChunk} for more information about using
33
+ * animations from a 3ds file
34
+ */
35
+public class PositionChunk extends Chunk
36
+{
37
+ /**
38
+ * Loads the position for a shape and KeyFramerInfoChunk
39
+ *
40
+ * @param chopper the ChunkChopper containing the state of the parser.
41
+ */
42
+ public void loadData(ChunkChopper chopper)
43
+ {
44
+ int flags = chopper.getUnsignedShort();
45
+ chopper.getLong();
46
+ int numKeys = chopper.getUnsignedInt();
47
+
48
+ ArrayList pointList = new ArrayList();
49
+ for(int i =0; i < numKeys; i++)
50
+ {
51
+ long keyNumber = chopper.getUnsignedInt();
52
+ int accelerationData = chopper.getUnsignedShort();
53
+
54
+ Point3f position = chopper.getPoint();
55
+ if(i==0)
56
+ {
57
+ chopper.getKeyFramer().setPosition(position);
58
+ }
59
+ pointList.add(position);
60
+ }
61
+ chopper.getKeyFramer().setPositionKeys(pointList);
62
+ }
63
+}
com/microcrowd/loader/java3d/max3ds/chunks/RotationChunk.java
....@@ -0,0 +1,129 @@
1
+/*8
2
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
3
+ * Microcrowd.com
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+ *
19
+ * Contact Josh DeFord jdeford@microcrowd.com
20
+ */
21
+
22
+package com.microcrowd.loader.java3d.max3ds.chunks;
23
+
24
+import java.util.ArrayList;
25
+import java.util.List;
26
+import javax.vecmath.Quat4f;
27
+import javax.vecmath.Vector3f;
28
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
29
+
30
+/**
31
+ * Extracts the rotation information from the 3ds file.
32
+ * Rotations occur about a pivot at a position within
33
+ * a local coordinate system. The rotation information
34
+ * is provided to the KeyFramerInfoChunk which then converts
35
+ * it to a global coordinate system and applies animation
36
+ * information.
37
+ * {@see KeyFramerInfoChunk} for more information about using
38
+ * animations from a 3ds file
39
+ */
40
+public class RotationChunk extends Chunk
41
+{
42
+ /**
43
+ * String that will be used as a data object in the transform that the
44
+ * RotationInterpolator will be a child of so it may be look up later.
45
+ **/
46
+ public static String ROTATION_TAG = "ROTATION_INTERPOLATOR";
47
+
48
+ /**
49
+ * Loads the quaternion for a rotation of a shape
50
+ * and notifies mesh info chunk.
51
+ *
52
+ * @param chopper the ChunkChopper containing the state of the parser.
53
+ */
54
+ public void loadData(ChunkChopper chopper)
55
+ {
56
+ int flags = chopper.getUnsignedShort();
57
+ chopper.getLong();
58
+ int numKeys = chopper.getUnsignedInt();
59
+
60
+ Quat4f previousQuat = null;
61
+
62
+ List quats = new ArrayList();
63
+ for(int i =0; i < numKeys; i++)
64
+ {
65
+ long frameNumber = chopper.getUnsignedInt();//Part of the track header
66
+ int accelerationData = chopper.getUnsignedShort();//Part of the track header
67
+ getSplineTerms(accelerationData, chopper);//Part of the track header
68
+
69
+ float angle = chopper.getFloat();
70
+ Vector3f vector = chopper.getVector();
71
+
72
+ Quat4f quat = getQuaternion(vector, angle);
73
+ if(previousQuat != null) {
74
+ quat.mul(previousQuat, quat);
75
+ }
76
+ previousQuat = quat;
77
+
78
+ quats.add(quat);
79
+ if(i==0)
80
+ {
81
+ chopper.getKeyFramer().setRotation(quat);
82
+ }
83
+ }
84
+ chopper.getKeyFramer().setOrientationKeys(quats);
85
+ }
86
+
87
+ /**
88
+ * This only reads the spline data and should be part
89
+ * of the track header when it gets invented.
90
+ * @param chopper an integer representing the bits that
91
+ * determine which of the five possible spline terms are present in the
92
+ * data and should be read.
93
+ * @param chopper what to read the data from
94
+ * The possible spline values are are
95
+ * <ol>
96
+ * <li> Tension
97
+ * <li> Continuity
98
+ * <li> Bias
99
+ * <li> EaseTo
100
+ * <li> EaseFrom
101
+ * </ol>
102
+ */
103
+ private void getSplineTerms(final int accelerationData, ChunkChopper chopper)
104
+ {
105
+ int bits = accelerationData;
106
+ for(int i=0; i < 5; i++)
107
+ {
108
+ bits = bits >>> i;
109
+ if((bits & 1) == 1)
110
+ {
111
+ chopper.getFloat();
112
+ }
113
+ }
114
+ }
115
+
116
+ /**
117
+ * This converts a 3ds angle and axis to
118
+ * a quaternion rotation. Successive
119
+ * rotations are relative to the first so each
120
+ * rotation must be made absolute by multiplying
121
+ * it with its predecessor
122
+ */
123
+ public Quat4f getQuaternion(Vector3f axis, float angle)
124
+ {
125
+ float sinA = (float)(java.lang.Math.sin(angle/2.0f));
126
+ float cosA = (float)(java.lang.Math.cos(angle/2.0f));
127
+ return new Quat4f(axis.x * sinA, axis.y * sinA, axis.z * sinA, cosA);
128
+ }
129
+}
com/microcrowd/loader/java3d/max3ds/chunks/ScaleChunk.java
....@@ -0,0 +1,67 @@
1
+/**
2
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
3
+ * Microcrowd.com
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+ *
19
+ * Contact Josh DeFord jdeford@microcrowd.com
20
+ */
21
+
22
+package com.microcrowd.loader.java3d.max3ds.chunks;
23
+
24
+import java.util.ArrayList;
25
+import java.util.List;
26
+import javax.vecmath.Vector3f;
27
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
28
+
29
+/**
30
+ * Extracts scale information from the 3ds file which
31
+ * is then used by the mesh info chunk to construct a
32
+ * animation.
33
+ */
34
+public class ScaleChunk extends Chunk
35
+{
36
+ /**
37
+ * Loads the scale for a shape
38
+ * and notifies the KeyFramerInfoChunk
39
+ *
40
+ * @param chopper the ChunkChopper containing the state of the parser.
41
+ */
42
+ public void loadData(ChunkChopper chopper)
43
+ {
44
+ int flags = chopper.getUnsignedShort();
45
+ chopper.getLong();
46
+ int numKeys = chopper.getUnsignedInt();
47
+
48
+ List scaleKeys = new ArrayList();
49
+
50
+ for(int i =0; i < numKeys; i++)
51
+ {
52
+ long keyNumber = chopper.getUnsignedInt();
53
+ int accelerationData = chopper.getUnsignedShort();
54
+
55
+ float scaleX = chopper.getFloat();
56
+ float scaleZ = chopper.getFloat();
57
+ float scaleY = chopper.getFloat();
58
+ Vector3f scale = new Vector3f(scaleX, scaleY, scaleZ);
59
+ if(i==0)
60
+ {
61
+ chopper.getKeyFramer().setScale(scale);
62
+ }
63
+ scaleKeys.add(scale);
64
+ }
65
+ chopper.getKeyFramer().setScaleKeys(scaleKeys);
66
+ }
67
+}
com/microcrowd/loader/java3d/max3ds/chunks/SmoothingChunk.java
....@@ -0,0 +1,65 @@
1
+/**
2
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
3
+ * Microcrowd.com
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+ *
19
+ * Contact Josh DeFord jdeford@microcrowd.com
20
+ */
21
+package com.microcrowd.loader.java3d.max3ds.chunks;
22
+
23
+import javax.vecmath.Point3f;
24
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
25
+import com.microcrowd.loader.java3d.max3ds.ChunkMap;
26
+
27
+/**
28
+ * This chunk is used to generate normals for a mesh according
29
+ * to the data in the smoothing groups chunk.
30
+ * Vertices that share coordinates will all use the same, averaged
31
+ * normal if they also belong to the same smoothing groups.
32
+ * @author jdeford
33
+ */
34
+public class SmoothingChunk extends Chunk
35
+{
36
+ /**
37
+ * Loads the vertices smoothing groups for
38
+ * a mesh and stores it in chopper
39
+ *
40
+ * @param chopper the ChunkChopper containing the state of the parser.
41
+ */
42
+ public void loadData(ChunkChopper chopper)
43
+ {
44
+ Point3f[] vertices = (Point3f[])chopper.popData(ChunkMap.FACES_DESCRIPTION);
45
+ int[] smoothGroups = new int[vertices.length];
46
+ int numFaces = vertices.length/3;
47
+ for(int i=0; i < numFaces; i++)
48
+ {
49
+ int groupMask = chopper.getInt();
50
+ smoothGroups[i*3]=groupMask;
51
+ smoothGroups[(i*3)+1]=groupMask;
52
+ smoothGroups[(i*3)+2]=groupMask;
53
+
54
+ java.util.ArrayList list = new java.util.ArrayList();
55
+ for(int j=0; j < 32; j++)
56
+ {
57
+ if(((0x1l << j) & groupMask) > 0)
58
+ {
59
+ list.add(new Integer(j));
60
+ }
61
+ }
62
+ }
63
+ chopper.pushData(chopper.getID(), smoothGroups);
64
+ }
65
+}
com/microcrowd/loader/java3d/max3ds/chunks/SpotLightChunk.java
....@@ -0,0 +1,73 @@
1
+/**
2
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
3
+ * Microcrowd.com
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+ *
19
+ * Contact Josh DeFord jdeford@microcrowd.com
20
+ */
21
+package com.microcrowd.loader.java3d.max3ds.chunks;
22
+
23
+import javax.media.j3d.SpotLight;
24
+import javax.media.j3d.Transform3D;
25
+import javax.media.j3d.TransformGroup;
26
+import javax.vecmath.Point3d;
27
+import javax.vecmath.Point3f;
28
+import javax.vecmath.Vector3d;
29
+import javax.vecmath.Vector3f;
30
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
31
+import com.microcrowd.loader.java3d.max3ds.ChunkMap;
32
+
33
+/**
34
+ * SpotLights to be placed in a scene.
35
+ *
36
+ * All the default parameters other than
37
+ * position and direction are used and
38
+ * not loaded from the 3ds file.
39
+ */
40
+public class SpotLightChunk extends Chunk
41
+{
42
+
43
+
44
+ /**
45
+ * This is called by the chunk chopper before any of the chunk's
46
+ * subchunks are loaded. Any data loaded that may need to be
47
+ * used later by superchunks should be stored in
48
+ * the chunk chopper via {@link ChunkChopper#popData}
49
+ *
50
+ * @param chopper the ChunkChopper that will have the light placed in it.
51
+ */
52
+ public void loadData(ChunkChopper chopper)
53
+ {
54
+ Point3f target = chopper.getPoint();
55
+ float beam = chopper.getFloat();
56
+ float falloff = chopper.getFloat();
57
+ SpotLight light = new SpotLight();
58
+
59
+ Vector3f direction = new Vector3f(0,0,-1);
60
+
61
+ Vector3f position = (Vector3f)chopper.popData(ChunkMap.LIGHT);
62
+ TransformGroup group = chopper.getGroup();
63
+ Transform3D transform = new Transform3D();
64
+ group.getTransform(transform);
65
+ transform.lookAt(new Point3d(position), new Point3d(target), new Vector3d(0,1,0));
66
+ transform.invert();
67
+ transform.setTranslation(position);
68
+ group.setTransform(transform);
69
+
70
+ chopper.pushData(chopper.getID(), light);
71
+ chopper.addLightNode(light);
72
+ }
73
+}
com/microcrowd/loader/java3d/max3ds/chunks/StringChunk.java
....@@ -0,0 +1,52 @@
1
+/**
2
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
3
+ * Microcrowd.com
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+ *
19
+ * Contact Josh DeFord jdeford@microcrowd.com
20
+ */
21
+
22
+package com.microcrowd.loader.java3d.max3ds.chunks;
23
+
24
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
25
+
26
+/**
27
+ * These have no subchunks. Only String data terminated with a null. For
28
+ * strings with unknown length use {@link ChunkChopper#getString} This can
29
+ * also be used for chunks that have data of a known length beginning with a
30
+ * string with unnessecary(you don't want to use it) data following.
31
+ */
32
+public class StringChunk extends Chunk
33
+{
34
+ /**
35
+ * Reads in all the data for this chunk and makes a string out of it.
36
+ * This will set the data in the chopper with a key of this chunks id.
37
+ *
38
+ *
39
+ * @param chopper the chopper that is doing the parsing.
40
+ */
41
+ public void loadData(ChunkChopper chopper)
42
+ {
43
+ byte[] stringArray = chopper.getChunkBytes();
44
+
45
+ String value = new String(stringArray, 0, stringArray.length - 1);
46
+ if (value.indexOf((char)(0x0000)) > 0) {
47
+ value = value.substring(0, value.indexOf((char)(0x0000)));
48
+ }
49
+
50
+ chopper.pushData(chopper.getID(), value);
51
+ }
52
+}
com/microcrowd/loader/java3d/max3ds/chunks/TextureChunk.java
....@@ -0,0 +1,47 @@
1
+/**
2
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
3
+ * Microcrowd.com
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+ *
19
+ * Contact Josh DeFord jdeford@microcrowd.com
20
+ */
21
+
22
+package com.microcrowd.loader.java3d.max3ds.chunks;
23
+
24
+
25
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
26
+import com.microcrowd.loader.java3d.max3ds.ChunkMap;
27
+
28
+
29
+/**
30
+ * Loads percentage values from binary data representing them.
31
+ */
32
+public class TextureChunk extends Chunk
33
+{
34
+
35
+ /**
36
+ * Gets the current texture image from the chopper
37
+ * creates a texture with it and sets that texture
38
+ * on the chopper.
39
+ *
40
+ * @param chopper the parser containing the state of parsing
41
+ */
42
+ public void initialize(ChunkChopper chopper)
43
+ {
44
+ String textureName = (String)chopper.popData(ChunkMap.TEXTURE_NAME);
45
+ chopper.pushData(ChunkMap.TEXTURE, chopper.createTexture(textureName));
46
+ }
47
+}
com/microcrowd/loader/java3d/max3ds/chunks/Vertex2ListChunk.java
....@@ -0,0 +1,55 @@
1
+/**
2
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
3
+ * Microcrowd.com
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+ *
19
+ * Contact Josh DeFord jdeford@microcrowd.com
20
+ */
21
+
22
+package com.microcrowd.loader.java3d.max3ds.chunks;
23
+
24
+import javax.vecmath.TexCoord2f;
25
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
26
+
27
+/**
28
+ * Reads a list of x,y points that will be used
29
+ * later for texture mapping.
30
+ *
31
+ * @author jdeford
32
+ */
33
+public class Vertex2ListChunk extends Chunk
34
+{
35
+ private static final int POINT_2F_SIZE = 8;
36
+
37
+ /**
38
+ * Reads all the point data from the chopper and stores
39
+ * teh points in the chopper.
40
+ *
41
+ * @param chopper the chopper that will parse and store
42
+ * the data using this chunks id as the key.
43
+ */
44
+ public void loadData(ChunkChopper chopper)
45
+ {
46
+ int numVertices = chopper.getUnsignedShort();
47
+ TexCoord2f[] points = new TexCoord2f[numVertices];
48
+ for (int i = 0; i < numVertices; i++) {
49
+ float point0 = chopper.getFloat();
50
+ float point1 = chopper.getFloat();
51
+ points[i] = new TexCoord2f(point0, point1);
52
+ }
53
+ chopper.pushData(chopper.getID(), points);
54
+ }
55
+}
com/microcrowd/loader/java3d/max3ds/chunks/Vertex3ListChunk.java
....@@ -0,0 +1,54 @@
1
+/**
2
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
3
+ * Microcrowd.com
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+ *
19
+ * Contact Josh DeFord jdeford@microcrowd.com
20
+ */
21
+
22
+package com.microcrowd.loader.java3d.max3ds.chunks;
23
+
24
+import javax.vecmath.Point3f;
25
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
26
+
27
+/**
28
+ * Reads and store x,y,z vertex coordinates.
29
+ * The coordinates will be accessed with indexes to construct
30
+ * the mesh out of triangles.
31
+ * @author jdeford
32
+ */
33
+public class Vertex3ListChunk extends Chunk
34
+{
35
+ private static final int POINT_3F_SIZE = 12;
36
+
37
+ /**
38
+ * Reads all the point data from the chopper
39
+ * and stores it using this chunk's id as the key.
40
+ *
41
+ * @param chopper the chopper that will read and
42
+ * store the data.
43
+ */
44
+ public void loadData(ChunkChopper chopper)
45
+ {
46
+ int numVertices = chopper.getUnsignedShort();
47
+ Point3f[] points = new Point3f[numVertices];
48
+ for (int i = 0; i < numVertices; i++) {
49
+ points[i] = new Point3f(chopper.getPoint());
50
+ }
51
+
52
+ chopper.pushData(chopper.getID(), points);
53
+ }
54
+}
com/microcrowd/loader/java3d/max3ds/data/KeyFramer.java
....@@ -0,0 +1,526 @@
1
+/**
2
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
3
+ *
4
+ * Microcrowd.com
5
+ *
6
+ * This library is free software; you can redistribute it and/or
7
+ * modify it under the terms of the GNU Lesser General Public
8
+ * License as published by the Free Software Foundation; either
9
+ * version 2.1 of the License, or (at your option) any later version.
10
+ *
11
+ * This library is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
+ * Lesser General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public
17
+ * License along with this library; if not, write to the Free Software
18
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
+ *
20
+ * Contact Josh DeFord jdeford@microcrowd.com
21
+ */
22
+package com.microcrowd.loader.java3d.max3ds.data;
23
+
24
+import java.util.Enumeration;
25
+import java.util.HashMap;
26
+import java.util.List;
27
+import javax.media.j3d.Alpha;
28
+import javax.media.j3d.Behavior;
29
+import javax.media.j3d.Group;
30
+import javax.media.j3d.Node;
31
+import javax.media.j3d.RotPosPathInterpolator;
32
+import javax.media.j3d.Transform3D;
33
+import javax.media.j3d.TransformGroup;
34
+import javax.media.j3d.TransformInterpolator;
35
+import javax.vecmath.Matrix4f;
36
+import javax.vecmath.Point3f;
37
+import javax.vecmath.Quat4f;
38
+import javax.vecmath.Vector3d;
39
+import javax.vecmath.Vector3f;
40
+
41
+/**
42
+ * @author Josh DeFord
43
+ */
44
+public class KeyFramer
45
+{
46
+ private HashMap lastGroupMap = new HashMap();
47
+ private HashMap fatherMap = new HashMap();
48
+
49
+ private Quat4f rotation;
50
+ private Point3f position;
51
+ private Point3f pivotCenter;
52
+ private Vector3f pivot;
53
+ private Vector3f scale;
54
+ private HashMap namedObjectCoordinateSystems = new HashMap();
55
+
56
+ private List positionKeys;
57
+ private List orientationKeys;
58
+ private List scaleKeys;
59
+
60
+ private Integer id;
61
+ private Group father;
62
+ private Group dummyObject;
63
+
64
+
65
+ /**
66
+ * Retrieves the named object for the current key framer
67
+ * inserts the rotation, position and pivot transformations for frame 0
68
+ * and assigns the coordinate system to it.
69
+ *
70
+ * The inverse of the local coordinate system converts from 3ds
71
+ * semi-absolute coordinates (what is in the file) to local coordinates.
72
+ *
73
+ * Then these local coordinates are converted with matrix
74
+ * that will instantiate them to absolute coordinates:
75
+ * Xabs = sx a1 (Xl-Px) + sy a2 (Yl-Py) + sz a3 (Zl-Pz) + Tx
76
+ * Yabs = sx b1 (Xl-Px) + sy b2 (Yl-Py) + sz b3 (Zl-Pz) + Ty
77
+ * Zabs = sx c1 (Xl-Px) + sy c2 (Yl-Py) + sz c3 (Zl-Pz) + Tz
78
+ * Where:
79
+ * (Xabs,Yabs,Zabs) = absolute coordinate
80
+ * (Px,Py,Pz) = mesh pivot (constant)
81
+ * (X1,Y1,Z1) = local coordinates
82
+ *
83
+ */
84
+ public Behavior createBehavior(String meshName, Group transformGroup, Object testObject)
85
+ {
86
+ Group objectGroup = getObjectByName(meshName, transformGroup, testObject);
87
+ //System.out.println("mesh " + meshName + " scale " + scale);
88
+ if(objectGroup == null)
89
+ return null;
90
+
91
+ insertFather(objectGroup, meshName);
92
+
93
+ TransformInterpolator behavior = null;
94
+ Transform3D coordinateSystem = (Transform3D)namedObjectCoordinateSystems.get(meshName);
95
+
96
+ //Gonna put these children back later.
97
+ Enumeration children = removeChildren(objectGroup);
98
+
99
+ Transform3D coordinateTransform = coordinateSystem == null ? new Transform3D() : new Transform3D(coordinateSystem);
100
+
101
+ Transform3D targetTransform = new Transform3D();
102
+ TransformGroup targetGroup = new TransformGroup(targetTransform);
103
+
104
+ TransformGroup localCoordinates = hasKeys() ? buildLocalCoordinates(coordinateSystem) : new TransformGroup();
105
+ TransformGroup lastGroup = (TransformGroup)addGroups(objectGroup, new Group[]
106
+ {
107
+ localCoordinates,
108
+ targetGroup,
109
+ buildPivotGroup(coordinateTransform, pivot),
110
+ buildKeysGroup(),
111
+ });
112
+
113
+ addChildren(children, lastGroup);
114
+ lastGroupMap.put(objectGroup, lastGroup);
115
+
116
+
117
+ behavior = buildInterpolator(targetGroup, coordinateSystem);
118
+ if(behavior != null)
119
+ {
120
+ behavior.setEnable(false);
121
+ targetGroup.addChild(behavior);
122
+
123
+ behavior.computeTransform(0f, targetTransform);
124
+ targetGroup.setTransform(targetTransform);
125
+ }
126
+ return behavior;
127
+ }
128
+
129
+ private Enumeration removeChildren(Group group)
130
+ {
131
+ Enumeration children = group.getAllChildren();
132
+ group.removeAllChildren();
133
+ return children;
134
+ }
135
+
136
+ private void addChildren(Enumeration children, Group group)
137
+ {
138
+ if(group == null)
139
+ return;
140
+ while(children.hasMoreElements())
141
+ {
142
+ Node node = (Node)(children.nextElement());
143
+ group.addChild(node);
144
+ }
145
+ }
146
+
147
+ /**
148
+ * Looks up the current object.
149
+ * objectGroup is returned if it is the right one to return
150
+ * otherwise a new dummy object may be returned.
151
+ * If it isn't there it gets the dummy object
152
+ * from the frames description chunk.
153
+ */
154
+ private Group getObjectByName(String objectName, Group objectGroup, Object testObject)
155
+ {
156
+
157
+ //This means its a dummy object. It needs to be created.
158
+ if(objectGroup == null && testObject == null)
159
+ {
160
+ namedObjectCoordinateSystems.put(objectName, new Transform3D());
161
+ objectGroup = dummyObject;
162
+ }
163
+
164
+ return objectGroup;
165
+ }
166
+
167
+ /**
168
+ * Locates the father for the object named objectName and inserts
169
+ * its transform cluster between the parent and all
170
+ * the parent's children. This only occurs in a hierarchical
171
+ * model. like bones and stuff. The fatherGroup, if found,
172
+ * is removed from whatever parent belonged to on before insertion.
173
+ */
174
+ private void insertFather(Group parentGroup, String objectName)
175
+ {
176
+ if(father == null)
177
+ return;
178
+ Group topGroup = new TransformGroup();
179
+ topGroup.addChild(father);
180
+ Group bottomGroup = (Group)lastGroupMap.get(father);
181
+
182
+ if(topGroup == null)
183
+ return;
184
+
185
+ Group fatherParent = (Group)topGroup.getParent();
186
+ if(fatherParent != null)
187
+ fatherParent.removeChild(topGroup);
188
+
189
+ Enumeration originalChildren = removeChildren(parentGroup);
190
+ parentGroup.addChild(topGroup);
191
+ addChildren(originalChildren, bottomGroup);
192
+ }
193
+
194
+ /**
195
+ * Builds a transform group from the zeroth key of the
196
+ * position and rotation tracks.
197
+ * @return transform group with position and rotation information
198
+ */
199
+ private TransformGroup buildKeysGroup()
200
+ {
201
+ Transform3D positionTransform = new Transform3D();
202
+ positionTransform.set(new Vector3f(position));
203
+
204
+ Transform3D rotationTransform = new Transform3D();
205
+ rotationTransform.set(rotation);
206
+
207
+ Transform3D scaleTransform = new Transform3D();
208
+ scaleTransform.setScale(new Vector3d(scale));
209
+ TransformGroup scaleGroup = new TransformGroup(scaleTransform);
210
+
211
+ Transform3D keyTransform = new Transform3D(positionTransform);
212
+ keyTransform.mul(scaleTransform);
213
+ keyTransform.mul(rotationTransform);
214
+ return new TransformGroup(keyTransform);
215
+ }
216
+
217
+ /**
218
+ * Builds a pivot group that will allow the objects
219
+ * to be positioned properly according to their rotations
220
+ * and positions.
221
+ * @param coordinateTransform the coordinate system defining the
222
+ * location and orientation of the local axis. This is not modified.
223
+ * @param pivot the pivot defined in the 3ds file loaded by pivot chunk.
224
+ * This is not changed.
225
+ */
226
+ private TransformGroup buildPivotGroup(Transform3D coordinateTransform, Vector3f pivot)
227
+ {
228
+ Transform3D pivotTransform = new Transform3D();
229
+ pivotTransform.mulInverse(coordinateTransform);
230
+ pivot = new Vector3f(pivot);
231
+ pivot.negate();
232
+ translatePivot(pivotTransform, pivot, pivotCenter);
233
+ return new TransformGroup(pivotTransform);
234
+ }
235
+
236
+ /**
237
+ * Builds a coordinate group that will allow the objects
238
+ * to be positioned properly according to their rotations
239
+ * and positions.
240
+ * @param coordinateSystem the coordinate system defining the
241
+ * location and orientation of the local axis. This is modified
242
+ * so it will be useful during the construction
243
+ * of the animations.
244
+ */
245
+ private TransformGroup buildLocalCoordinates(Transform3D coordinateSystem)
246
+ {
247
+ Matrix4f coordMatrix = new Matrix4f();
248
+ Vector3f translation = new Vector3f();
249
+
250
+ coordinateSystem.get(translation);
251
+ coordinateSystem.invert();
252
+
253
+ coordinateSystem.get(coordMatrix);
254
+ coordMatrix.m03 = translation.x;
255
+ coordMatrix.m13 = translation.y;
256
+ coordMatrix.m23 = translation.z;
257
+ coordinateSystem.set(coordMatrix);
258
+ coordinateSystem.invert();
259
+ TransformGroup systemGroup = new TransformGroup(coordinateSystem);
260
+ coordinateSystem.invert();
261
+ return systemGroup;
262
+ }
263
+
264
+ /**
265
+ * Hierarchically adds the provided groups in order to parentGroup.
266
+ * groups[0] is added to parentGroup, groups[1] is added to groups[0] etc.
267
+ * @return the last group added (groups[groups.length - 1]).
268
+ */
269
+ private Group addGroups(Group parentGroup, Group[] groups)
270
+ {
271
+ Group nextGroup = parentGroup;
272
+ for(int i=0; i < groups.length; i++)
273
+ {
274
+ nextGroup.addChild(groups[i]);
275
+ nextGroup = groups[i];
276
+ }
277
+ return groups[groups.length - 1];
278
+ }
279
+
280
+ /**
281
+ * Does a pre rotational translation of the pivot.
282
+ * @param transform the matrix that will have a translation concatenated to it.
283
+ * @param vector the vector which will be used to translate the matrix.
284
+ * @param offset the offset used to offset the pivot.
285
+ */
286
+ private void translatePivot(Transform3D transform, Vector3f vector, Point3f offset)
287
+ {
288
+ if(offset != null)
289
+ {
290
+ pivot.sub(offset);
291
+ }
292
+ Matrix4f matrix = new Matrix4f();
293
+ transform.get(matrix);
294
+
295
+ matrix.m03 += (matrix.m00*vector.x + matrix.m01*vector.y + matrix.m02*vector.z);
296
+ matrix.m13 += (matrix.m10*vector.x + matrix.m11*vector.y + matrix.m12*vector.z);
297
+ matrix.m23 += (matrix.m20*vector.x + matrix.m21*vector.y + matrix.m22*vector.z);
298
+
299
+ transform.set(matrix);
300
+ }
301
+
302
+
303
+ /**
304
+ * Builds a rotation position interpolator for use on this mesh using position and rotation information
305
+ * adds it to targetGroup.
306
+ * This does not set the capability bits that need to be set for the animation
307
+ * to be used. The capability bits of the targetGroup must be set by the client application.
308
+ * The alpha object on the Interpolator must also be enabled.
309
+ * The Interpolator must also have its scheduling bounds set.
310
+ * @param pivotGroup transform group which will be operated on by the interpolator.
311
+ * @param interpolatorAxis the axis that about which rotations will be centered.
312
+ */
313
+ //TODO... This needs to use both a rotation interpolator and a position interpolator
314
+ //in case there are keys with no position information but position information and
315
+ //vice versa right now its using RotPosPathInterpolator
316
+ private TransformInterpolator buildInterpolator(TransformGroup targetGroup, Transform3D axisOfTransform)
317
+ {
318
+ makeTwoListsTheSameSize(positionKeys, orientationKeys);
319
+ int numKeys = positionKeys.size();
320
+
321
+ Point3f currentPoint = position;
322
+ Quat4f currentQuat = rotation;
323
+ RotPosPathInterpolator rotator = null;
324
+ if(numKeys > 1)
325
+ {
326
+ float[] knots = new float[numKeys];
327
+ Point3f[] points = new Point3f[numKeys];
328
+ Quat4f[] quats = new Quat4f[numKeys];
329
+
330
+ for(int i=0; i < numKeys; i++)
331
+ {
332
+ //Knots need to be between 0(beginning) and 1(end)
333
+ knots[i]= (i==0?0:((float)i/((float)(numKeys-1))));
334
+ if(positionKeys.size() > i)
335
+ {
336
+ Point3f newPoint = (Point3f)positionKeys.get(i);
337
+ if(newPoint != null)
338
+ {
339
+ currentPoint = newPoint;
340
+ }
341
+
342
+ Quat4f newQuat = (Quat4f)orientationKeys.get(i);
343
+ if(newQuat != null)
344
+ {
345
+ currentQuat = newQuat;
346
+ }
347
+ }
348
+
349
+ points[i] = currentPoint;
350
+ quats[i] = currentQuat;
351
+ quats[i].inverse();
352
+ }
353
+
354
+ //This gives a continuous loop at a rate of 30 fps
355
+ Alpha alpha = new Alpha(-1, (long)(numKeys/.03));
356
+ alpha.setStartTime(System.currentTimeMillis());
357
+ alpha.setDuplicateOnCloneTree(true);
358
+
359
+ rotator = new RotPosPathInterpolator(alpha, targetGroup,
360
+ axisOfTransform, knots,
361
+ quats, points);
362
+ }
363
+ return rotator;
364
+ }
365
+
366
+ public void makeTwoListsTheSameSize(List list1, List list2)
367
+ {
368
+ growList(list2.size() - 1, list1);
369
+ growList(list1.size() - 1, list2);
370
+ }
371
+
372
+ /**
373
+ * Make sure the list is at least able to
374
+ * hold a value at index.
375
+ * @param index an int specifying the initial size
376
+ * @parame the list that may need to grow
377
+ */
378
+ public void growList(int index, List list)
379
+ {
380
+ int numNeeded = (index + 1) - list.size();
381
+ while(numNeeded-- > 0)
382
+ {
383
+ list.add(null);
384
+ }
385
+ }
386
+
387
+ /**
388
+ * Sets the center of the bounding box that the pivot
389
+ * should offset.
390
+ */
391
+ public void setPivotCenter(Point3f center)
392
+ {
393
+ this.pivotCenter = center;
394
+ }
395
+
396
+ /**
397
+ * Called to set the coordinate system transform for an object named
398
+ * objectName.
399
+ * This is the first t
400
+ */
401
+ public void setCoordinateSystem(String objectName, Transform3D coordinateSystem)
402
+ {
403
+ namedObjectCoordinateSystems.put(objectName, coordinateSystem);
404
+ }
405
+
406
+ /**
407
+ * Sets the group that will be used to center rotations.
408
+ * This is applied to the mesh after all other transforms
409
+ * have been applied.
410
+ * @param group the group that will act as the rotation transform.
411
+ */
412
+ public void setRotation(Quat4f rotation)
413
+ {
414
+ this.rotation = rotation;
415
+ }
416
+
417
+ /**
418
+ * Sets the pivot that will be used to as a pivot for
419
+ * these transfomations.
420
+ * @param group the group that will act as the pivot.
421
+ */
422
+ public void setPivot(Vector3f pivot)
423
+ {
424
+ this.pivot = pivot;
425
+ }
426
+
427
+ /**
428
+ * Sets the scale for x y and z axis for objects.
429
+ * This is applied to the mesh before the rotation transform
430
+ * has been applied.
431
+ * @param group the group that will act as the scale
432
+ */
433
+ public void setScale(Vector3f scale)
434
+ {
435
+ this.scale = scale;
436
+ }
437
+
438
+ /**
439
+ * Sets the scale information necessary for animation.s
440
+ * @param scaleKeys a list of Vector3f, which may contain null elements,
441
+ * containing a position for some keys.
442
+ */
443
+ public void setScaleKeys(List scaleKeys)
444
+ {
445
+ this.scaleKeys = scaleKeys;
446
+ }
447
+
448
+ /**
449
+ * Sets the group that will be used to translate the mesh..
450
+ * This is applied to the mesh just before the rotation transform
451
+ * has been applied.
452
+ * @param group the group that will act as the position transform.
453
+ */
454
+ public void setPosition(Point3f position)
455
+ {
456
+ this.position = position;
457
+ }
458
+
459
+ /**
460
+ * Sets the position information necessary for animation.s
461
+ * @param positions a list of Point3f, which may contain null elements,
462
+ * containing a position for some keys.
463
+ */
464
+ public void setPositionKeys(List positions)
465
+ {
466
+ positionKeys = positions;
467
+ }
468
+
469
+ /**
470
+ * Sets the orientation information necessary for animation.s
471
+ * @param positions a list of Quat4f, which may contain null elements,
472
+ * containing a orientation for some keys.
473
+ */
474
+ public void setOrientationKeys(List orientations)
475
+ {
476
+ orientationKeys = orientations;
477
+ }
478
+
479
+ /**
480
+ *
481
+ */
482
+ public void setDummyObject(Group object)
483
+ {
484
+ dummyObject = object;
485
+ }
486
+
487
+ /**
488
+ * returns true if position keys and orientation
489
+ * keys are longer than one element each.
490
+ */
491
+ public boolean hasKeys()
492
+ {
493
+ return (positionKeys.size() > 1 || orientationKeys.size() > 1);
494
+ }
495
+
496
+ /**
497
+ */
498
+ public void addFather(int fatherID, TransformGroup newFather)
499
+ {
500
+ if(fatherID < 0)
501
+ {
502
+ father = null;
503
+ }
504
+ else
505
+ {
506
+ father = (TransformGroup)(fatherMap.get(new Integer(fatherID)));
507
+ //Remove the father's father because the father will
508
+ //be inserted somewhere later.
509
+ Group grandFather = (Group)father.getParent();
510
+ if(grandFather != null)
511
+ {
512
+ grandFather.removeChild(father);
513
+ }
514
+ }
515
+ fatherMap.put(id, newFather);
516
+ }
517
+
518
+ /**
519
+ * Sets the id for these frames.
520
+ * @param id the id for these frames.
521
+ */
522
+ public void setID(int id)
523
+ {
524
+ this.id = new Integer(id);
525
+ }
526
+}
com/microcrowd/loader/java3d/max3ds/package.html
....@@ -0,0 +1,3 @@
1
+<html><body>
2
+ Contains classes used to load 3d studio max files.
3
+</body></html>
com/realvue/sim/ui/loader/java3d/max3ds/Loader3DS.java
....@@ -0,0 +1,34 @@
1
+/*
2
+ * Microcrowd.com
3
+ *
4
+ * This library is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU Lesser General Public
6
+ * License as published by the Free Software Foundation; either
7
+ * version 2.1 of the License, or (at your option) any later version.
8
+ *
9
+ * This library is distributed in the hope that it will be useful,
10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
+ * Lesser General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU Lesser General Public
15
+ * License along with this library; if not, write to the Free Software
16
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
+ *
18
+ * Contact Josh DeFord jdeford@microcrowd.com
19
+ */
20
+package com.realvue.sim.ui.loader.java3d.max3ds;
21
+
22
+
23
+/**
24
+ * @author jdeford
25
+ *
26
+ * Fonzie makes the windmill go round.
27
+ */
28
+public class Loader3DS
29
+{
30
+ static
31
+ {
32
+ System.err.println("com.realvue.sim.ui.loader.java3d.max3ds.Loader has been replaced by com.microcrowd.loader.java3d.max3ds.Loader3DS. Just change the package and it will work.");
33
+ }
34
+}