OSDN Git Service

Add support Wavefromt(.obj) model.
[nyartoolkit-and/nyartoolkit-and.git] / src / min3d / parser / .svn / text-base / AParser.java.svn-base
1 package min3d.parser;\r
2 \r
3 import java.io.FileNotFoundException;\r
4 import java.io.FileOutputStream;\r
5 import java.io.IOException;\r
6 import java.io.InputStream;\r
7 import java.util.ArrayList;\r
8 import java.util.Collections;\r
9 import java.util.Comparator;\r
10 import java.util.HashMap;\r
11 \r
12 import min3d.Min3d;\r
13 import min3d.Shared;\r
14 import min3d.Utils;\r
15 import min3d.animation.AnimationObject3d;\r
16 import min3d.core.Object3dContainer;\r
17 import min3d.vos.Color4;\r
18 import min3d.vos.Number3d;\r
19 import min3d.vos.Uv;\r
20 import android.content.res.Resources;\r
21 import android.graphics.Bitmap;\r
22 import android.graphics.Bitmap.Config;\r
23 import android.util.Log;\r
24 \r
25 /**\r
26  * Abstract parser class with basic parsing functionality.\r
27  * \r
28  * @author dennis.ippel\r
29  *\r
30  */\r
31 public abstract class AParser implements IParser {\r
32         protected Resources resources;\r
33         protected String resourceID;\r
34         protected String packageID;\r
35         protected String currentMaterialKey;\r
36         protected ArrayList<ParseObjectData> parseObjects;\r
37         protected ParseObjectData co;\r
38         protected boolean firstObject;\r
39         protected TextureAtlas textureAtlas;\r
40         protected ArrayList<Number3d> vertices;\r
41         protected ArrayList<Uv> texCoords;\r
42         protected ArrayList<Number3d> normals;\r
43         protected boolean generateMipMap;\r
44         protected HashMap<String, Material> materialMap;\r
45         \r
46         public AParser()\r
47         {\r
48                 vertices = new ArrayList<Number3d>();\r
49                 texCoords = new ArrayList<Uv>();\r
50                 normals = new ArrayList<Number3d>();\r
51                 parseObjects = new ArrayList<ParseObjectData>();\r
52                 textureAtlas = new TextureAtlas();\r
53                 firstObject = true;\r
54                 materialMap = new HashMap<String, Material>();\r
55         }\r
56         \r
57         public AParser(Resources resources, String resourceID, Boolean generateMipMap)\r
58         {\r
59                 this();\r
60                 this.resources = resources;\r
61                 this.resourceID = resourceID;\r
62                 if (resourceID.indexOf(":") > -1)\r
63                         this.packageID = resourceID.split(":")[0];\r
64                 this.generateMipMap = generateMipMap;\r
65         }\r
66         \r
67         protected void cleanup()\r
68         {\r
69                 parseObjects.clear();\r
70                 textureAtlas.cleanup();\r
71                 vertices.clear();\r
72                 texCoords.clear();\r
73                 normals.clear();\r
74         }\r
75         \r
76         /**\r
77          * Override this in the concrete parser\r
78          */\r
79         public Object3dContainer getParsedObject() {\r
80                 return null;\r
81         }\r
82         \r
83         /**\r
84          * Override this in the concrete parser if applicable \r
85          */\r
86         public AnimationObject3d getParsedAnimationObject() {\r
87                 return null;\r
88         }\r
89 \r
90         protected String readString(InputStream stream) throws IOException {\r
91                 String result = new String();\r
92                 byte inByte;\r
93                 while ((inByte = (byte) stream.read()) != 0)\r
94                         result += (char) inByte;\r
95                 return result;\r
96         }\r
97 \r
98         protected int readInt(InputStream stream) throws IOException {\r
99                 return stream.read() | (stream.read() << 8) | (stream.read() << 16)\r
100                                 | (stream.read() << 24);\r
101         }\r
102 \r
103         protected int readShort(InputStream stream) throws IOException {\r
104                 return (stream.read() | (stream.read() << 8));\r
105         }\r
106 \r
107         protected float readFloat(InputStream stream) throws IOException {\r
108                 return Float.intBitsToFloat(readInt(stream));\r
109         }\r
110 \r
111         /**\r
112          * Override this in the concrete parser\r
113          */\r
114         public void parse() {\r
115         }\r
116         \r
117 \r
118         /**\r
119          * Contains texture information. UV offsets and scaling is stored here.\r
120          * This is used with texture atlases.\r
121          * \r
122          * @author dennis.ippel\r
123          *\r
124          */\r
125         protected class BitmapAsset\r
126         {\r
127                 /**\r
128                  * The texture bitmap\r
129                  */\r
130                 public Bitmap bitmap;\r
131                 /**\r
132                  * The texture identifier\r
133                  */\r
134                 public String key;\r
135                 /**\r
136                  * Resource ID\r
137                  */\r
138                 public String resourceID;\r
139                 /**\r
140                  * U-coordinate offset\r
141                  */\r
142                 public float uOffset;\r
143                 /**\r
144                  * V-coordinate offset\r
145                  */\r
146                 public float vOffset;\r
147                 /**\r
148                  * U-coordinate scaling value\r
149                  */\r
150                 public float uScale;\r
151                 /**\r
152                  * V-coordinate scaling value\r
153                  */\r
154                 public float vScale;\r
155                 public boolean useForAtlasDimensions;\r
156                 \r
157                 /**\r
158                  * Creates a new BitmapAsset object\r
159                  * @param bitmap\r
160                  * @param key\r
161                  */\r
162                 public BitmapAsset(String key, String resourceID)\r
163                 {\r
164                         this.key = key;\r
165                         this.resourceID = resourceID;\r
166                         useForAtlasDimensions = false;\r
167                 }\r
168         }\r
169         \r
170         /**\r
171          * When a model contains per-face textures a texture atlas is created. This\r
172          * combines multiple textures into one and re-calculates the UV coordinates.\r
173          * \r
174          * @author dennis.ippel\r
175          * \r
176          */\r
177         protected class TextureAtlas {\r
178                 /**\r
179                  * The texture bitmaps that should be combined into one.\r
180                  */\r
181                 private ArrayList<BitmapAsset> bitmaps;\r
182                 /**\r
183                  * The texture atlas bitmap\r
184                  */\r
185                 private Bitmap atlas;\r
186 \r
187                 /**\r
188                  * Creates a new texture atlas instance.\r
189                  */\r
190                 public TextureAtlas() {\r
191                         bitmaps = new ArrayList<BitmapAsset>();\r
192                 }\r
193                 private String atlasId;\r
194 \r
195                 /**\r
196                  * Adds a bitmap to the atlas\r
197                  * \r
198                  * @param bitmap\r
199                  */\r
200                 public void addBitmapAsset(BitmapAsset ba) {\r
201                         BitmapAsset existingBA = getBitmapAssetByResourceID(ba.resourceID);\r
202 \r
203                         if(existingBA == null)\r
204                         {\r
205                                 int bmResourceID = resources.getIdentifier(ba.resourceID, null, null);\r
206                                 if(bmResourceID == 0)\r
207                                 {\r
208                                         Log.d(Min3d.TAG, "Texture not found: " + ba.resourceID);\r
209                                         return;\r
210                                 }\r
211 \r
212                                 Log.d(Min3d.TAG, "Adding texture " + ba.resourceID);\r
213                                 \r
214                                 Bitmap b = Utils.makeBitmapFromResourceId(bmResourceID);\r
215                                 ba.useForAtlasDimensions = true;\r
216                                 ba.bitmap = b;\r
217                         }\r
218                         else\r
219                         {\r
220                                 ba.bitmap = existingBA.bitmap;\r
221                         }\r
222 \r
223                         bitmaps.add(ba);\r
224                 }\r
225                 \r
226                 public BitmapAsset getBitmapAssetByResourceID(String resourceID)\r
227                 {\r
228                         int numBitmaps = bitmaps.size();\r
229                         \r
230                         for(int i=0; i<numBitmaps; i++)\r
231                         {\r
232                                 if(bitmaps.get(i).resourceID.equals(resourceID))\r
233                                         return bitmaps.get(i);\r
234                         }\r
235                         \r
236                         return null;\r
237                 }\r
238 \r
239                 /**\r
240                  * Generates a new texture atlas\r
241                  */\r
242                 public void generate() {\r
243                         Collections.sort(bitmaps, new BitmapHeightComparer());\r
244 \r
245                         if(bitmaps.size() == 0) return;\r
246                         \r
247                         BitmapAsset largestBitmap = bitmaps.get(0);\r
248                         int totalWidth = 0;\r
249                         int numBitmaps = bitmaps.size();\r
250                         int uOffset = 0;\r
251                         int vOffset = 0;\r
252 \r
253                         for (int i = 0; i < numBitmaps; i++) {\r
254                                 if(bitmaps.get(i).useForAtlasDimensions)\r
255                                         totalWidth += bitmaps.get(i).bitmap.getWidth();\r
256                         }\r
257 \r
258                         atlas = Bitmap.createBitmap(totalWidth, largestBitmap.bitmap\r
259                                         .getHeight(), Config.ARGB_8888);\r
260 \r
261                         for (int i = 0; i < numBitmaps; i++) {\r
262                                 BitmapAsset ba = bitmaps.get(i);\r
263                                 BitmapAsset existingBA = getBitmapAssetByResourceID(ba.resourceID);                             \r
264                                 \r
265                                 if(ba.useForAtlasDimensions)\r
266                                 {\r
267                                         Bitmap b = ba.bitmap;\r
268                                         int w = b.getWidth();\r
269                                         int h = b.getHeight();\r
270                                         int[] pixels = new int[w * h];\r
271                                         \r
272                                         b.getPixels(pixels, 0, w, 0, 0, w, h);\r
273                                         atlas.setPixels(pixels, 0, w, uOffset, vOffset, w, h);\r
274                                         \r
275                                         ba.uOffset = (float) uOffset / totalWidth;\r
276                                         ba.vOffset = 0;\r
277                                         ba.uScale = (float) w / (float) totalWidth;\r
278                                         ba.vScale = (float) h / (float) largestBitmap.bitmap.getHeight();\r
279                                         \r
280                                         uOffset += w;\r
281                                         b.recycle();\r
282                                 }\r
283                                 else\r
284                                 {\r
285                                         ba.uOffset = existingBA.uOffset;\r
286                                         ba.vOffset = existingBA.vOffset;\r
287                                         ba.uScale = existingBA.uScale;\r
288                                         ba.vScale = existingBA.vScale;\r
289                                 }\r
290                         }\r
291                         /*\r
292                         FileOutputStream fos;\r
293                         try {\r
294                                 fos = new FileOutputStream("/data/screenshot.png");\r
295                                 atlas.compress(Bitmap.CompressFormat.PNG, 100, fos);\r
296                                 fos.flush();\r
297                                 fos.close();\r
298                         } catch (FileNotFoundException e) {\r
299                                 // TODO Auto-generated catch block\r
300                                 e.printStackTrace();\r
301                         } catch (IOException e) {\r
302                                 // TODO Auto-generated catch block\r
303                                 e.printStackTrace();\r
304                         }\r
305                         */\r
306                         setId(Shared.textureManager().getNewAtlasId());\r
307                 }\r
308 \r
309                 /**\r
310                  * Returns the generated texture atlas bitmap\r
311                  * \r
312                  * @return\r
313                  */\r
314                 public Bitmap getBitmap() {\r
315                         return atlas;\r
316                 }\r
317 \r
318                 /**\r
319                  * Indicates whether bitmaps have been added to the atlas.\r
320                  * \r
321                  * @return\r
322                  */\r
323                 public boolean hasBitmaps() {\r
324                         return bitmaps.size() > 0;\r
325                 }\r
326 \r
327                 /**\r
328                  * Compares the height of two BitmapAsset objects.\r
329                  * \r
330                  * @author dennis.ippel\r
331                  * \r
332                  */\r
333                 private class BitmapHeightComparer implements Comparator<BitmapAsset> {\r
334                         public int compare(BitmapAsset b1, BitmapAsset b2) {\r
335                                 int height1 = b1.bitmap.getHeight();\r
336                                 int height2 = b2.bitmap.getHeight();\r
337 \r
338                                 if (height1 < height2) {\r
339                                         return 1;\r
340                                 } else if (height1 == height2) {\r
341                                         return 0;\r
342                                 } else {\r
343                                         return -1;\r
344                                 }\r
345                         }\r
346                 }\r
347                 \r
348                 /**\r
349                  * Returns a bitmap asset with a specified name.\r
350                  * \r
351                  * @param materialKey\r
352                  * @return\r
353                  */\r
354                 public BitmapAsset getBitmapAssetByName(String materialKey) {\r
355                         int numBitmaps = bitmaps.size();\r
356 \r
357                         for (int i = 0; i < numBitmaps; i++) {\r
358                                 if (bitmaps.get(i).key.equals(materialKey))\r
359                                         return bitmaps.get(i);\r
360                         }\r
361 \r
362                         return null;\r
363                 }\r
364                 \r
365                 public void cleanup()\r
366                 {\r
367                         int numBitmaps = bitmaps.size();\r
368 \r
369                         for (int i = 0; i < numBitmaps; i++) {\r
370                                 bitmaps.get(i).bitmap.recycle();\r
371                         }\r
372                         \r
373                         if(atlas != null) atlas.recycle();\r
374                         bitmaps.clear();\r
375                         vertices.clear();\r
376                         texCoords.clear();\r
377                         normals.clear();\r
378                 }\r
379 \r
380                 public void setId(String newAtlasId) {\r
381                         atlasId = newAtlasId;                   \r
382                 }\r
383 \r
384                 public String getId() {\r
385                         return atlasId;\r
386                 }\r
387         }\r
388         \r
389         protected class Material {\r
390                 public String name;\r
391                 public String diffuseTextureMap;\r
392                 public Color4 diffuseColor;\r
393 \r
394                 public Material(String name) {\r
395                         this.name = name;\r
396                 }\r
397         }\r
398 }\r