├── .gitattributes ├── .gitignore └── src ├── de └── wc3data │ ├── examples │ └── CreateBox.java │ ├── image │ ├── BlpFile.java │ ├── ImageUtils.java │ └── TgaFile.java │ ├── map │ └── ShadowMap.java │ ├── mdx │ ├── AttachmentChunk.java │ ├── AttachmentVisibility.java │ ├── BlizzardDataInputStream.java │ ├── BlizzardDataOutputStream.java │ ├── BoneChunk.java │ ├── CameraChunk.java │ ├── CameraPositionTranslation.java │ ├── CameraRotation.java │ ├── CameraTargetTranslation.java │ ├── CollisionShapeChunk.java │ ├── EventObjectChunk.java │ ├── GeosetAlpha.java │ ├── GeosetAnimationChunk.java │ ├── GeosetChunk.java │ ├── GeosetColor.java │ ├── GeosetRotation.java │ ├── GeosetScaling.java │ ├── GeosetTranslation.java │ ├── GlobalSequenceChunk.java │ ├── HelperChunk.java │ ├── LayerChunk.java │ ├── LightAmbientColor.java │ ├── LightAmbientIntensity.java │ ├── LightChunk.java │ ├── LightColor.java │ ├── LightIntensity.java │ ├── LightVisibility.java │ ├── MaterialAlpha.java │ ├── MaterialChunk.java │ ├── MaterialTextureId.java │ ├── MdxModel.java │ ├── ModelChunk.java │ ├── ModelUtils.java │ ├── Node.java │ ├── ParticleEmitter2Chunk.java │ ├── ParticleEmitter2EmissionRate.java │ ├── ParticleEmitter2Latitude.java │ ├── ParticleEmitter2Length.java │ ├── ParticleEmitter2Speed.java │ ├── ParticleEmitter2Visibility.java │ ├── ParticleEmitter2Width.java │ ├── ParticleEmitterChunk.java │ ├── ParticleEmitterVisibility.java │ ├── PivotPointChunk.java │ ├── RibbonEmitterChunk.java │ ├── RibbonEmitterHeightAbove.java │ ├── RibbonEmitterHeightBelow.java │ ├── RibbonEmitterVisibility.java │ ├── SequenceChunk.java │ ├── TextureAnimationChunk.java │ ├── TextureChunk.java │ ├── TextureRotation.java │ ├── TextureScaling.java │ ├── TextureTranslation.java │ ├── Tracks.java │ └── VersionChunk.java │ └── stream │ ├── BlizzardDataInputStream.java │ ├── BlizzardDataOutputStream.java │ └── StreamUtils.java └── mdxinfo.txt /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | bin/ 9 | tmp/ 10 | *.tmp 11 | *.bak 12 | *.swp 13 | *~.nib 14 | local.properties 15 | .classpath 16 | .settings/ 17 | .loadpath 18 | 19 | # External tool builders 20 | .externalToolBuilders/ 21 | 22 | # Locally stored "Eclipse launch configurations" 23 | *.launch 24 | 25 | # CDT-specific 26 | .cproject 27 | 28 | # PDT-specific 29 | .buildpath 30 | 31 | 32 | ################# 33 | ## Visual Studio 34 | ################# 35 | 36 | ## Ignore Visual Studio temporary files, build results, and 37 | ## files generated by popular Visual Studio add-ons. 38 | 39 | # User-specific files 40 | *.suo 41 | *.user 42 | *.sln.docstates 43 | 44 | # Build results 45 | 46 | [Dd]ebug/ 47 | [Rr]elease/ 48 | x64/ 49 | build/ 50 | [Bb]in/ 51 | [Oo]bj/ 52 | 53 | # MSTest test Results 54 | [Tt]est[Rr]esult*/ 55 | [Bb]uild[Ll]og.* 56 | 57 | *_i.c 58 | *_p.c 59 | *.ilk 60 | *.meta 61 | *.obj 62 | *.pch 63 | *.pdb 64 | *.pgc 65 | *.pgd 66 | *.rsp 67 | *.sbr 68 | *.tlb 69 | *.tli 70 | *.tlh 71 | *.tmp 72 | *.tmp_proj 73 | *.log 74 | *.vspscc 75 | *.vssscc 76 | .builds 77 | *.pidb 78 | *.log 79 | *.scc 80 | 81 | # Visual C++ cache files 82 | ipch/ 83 | *.aps 84 | *.ncb 85 | *.opensdf 86 | *.sdf 87 | *.cachefile 88 | 89 | # Visual Studio profiler 90 | *.psess 91 | *.vsp 92 | *.vspx 93 | 94 | # Guidance Automation Toolkit 95 | *.gpState 96 | 97 | # ReSharper is a .NET coding add-in 98 | _ReSharper*/ 99 | *.[Rr]e[Ss]harper 100 | 101 | # TeamCity is a build add-in 102 | _TeamCity* 103 | 104 | # DotCover is a Code Coverage Tool 105 | *.dotCover 106 | 107 | # NCrunch 108 | *.ncrunch* 109 | .*crunch*.local.xml 110 | 111 | # Installshield output folder 112 | [Ee]xpress/ 113 | 114 | # DocProject is a documentation generator add-in 115 | DocProject/buildhelp/ 116 | DocProject/Help/*.HxT 117 | DocProject/Help/*.HxC 118 | DocProject/Help/*.hhc 119 | DocProject/Help/*.hhk 120 | DocProject/Help/*.hhp 121 | DocProject/Help/Html2 122 | DocProject/Help/html 123 | 124 | # Click-Once directory 125 | publish/ 126 | 127 | # Publish Web Output 128 | *.Publish.xml 129 | *.pubxml 130 | 131 | # NuGet Packages Directory 132 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 133 | #packages/ 134 | 135 | # Windows Azure Build Output 136 | csx 137 | *.build.csdef 138 | 139 | # Windows Store app package directory 140 | AppPackages/ 141 | 142 | # Others 143 | sql/ 144 | *.Cache 145 | ClientBin/ 146 | [Ss]tyle[Cc]op.* 147 | ~$* 148 | *~ 149 | *.dbmdl 150 | *.[Pp]ublish.xml 151 | *.pfx 152 | *.publishsettings 153 | 154 | # RIA/Silverlight projects 155 | Generated_Code/ 156 | 157 | # Backup & report files from converting an old project file to a newer 158 | # Visual Studio version. Backup files are not needed, because we have git ;-) 159 | _UpgradeReport_Files/ 160 | Backup*/ 161 | UpgradeLog*.XML 162 | UpgradeLog*.htm 163 | 164 | # SQL Server files 165 | App_Data/*.mdf 166 | App_Data/*.ldf 167 | 168 | ############# 169 | ## Windows detritus 170 | ############# 171 | 172 | # Windows image file caches 173 | Thumbs.db 174 | ehthumbs.db 175 | 176 | # Folder config file 177 | Desktop.ini 178 | 179 | # Recycle Bin used on file shares 180 | $RECYCLE.BIN/ 181 | 182 | # Mac crap 183 | .DS_Store 184 | 185 | 186 | ############# 187 | ## Python 188 | ############# 189 | 190 | *.py[co] 191 | 192 | # Packages 193 | *.egg 194 | *.egg-info 195 | dist/ 196 | build/ 197 | eggs/ 198 | parts/ 199 | var/ 200 | sdist/ 201 | develop-eggs/ 202 | .installed.cfg 203 | 204 | # Installer logs 205 | pip-log.txt 206 | 207 | # Unit test / coverage reports 208 | .coverage 209 | .tox 210 | 211 | #Translations 212 | *.mo 213 | 214 | #Mr Developer 215 | .mr.developer.cfg 216 | -------------------------------------------------------------------------------- /src/de/wc3data/examples/CreateBox.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.examples; 2 | 3 | import de.wc3data.mdx.ModelUtils; 4 | import de.wc3data.mdx.BlizzardDataOutputStream; 5 | import de.wc3data.mdx.GeosetChunk; 6 | import de.wc3data.mdx.GeosetChunk.Geoset; 7 | import de.wc3data.mdx.LayerChunk; 8 | import de.wc3data.mdx.LayerChunk.Layer; 9 | import de.wc3data.mdx.MaterialChunk; 10 | import de.wc3data.mdx.MaterialChunk.Material; 11 | import de.wc3data.mdx.MdxModel; 12 | import de.wc3data.mdx.TextureChunk; 13 | import de.wc3data.mdx.TextureChunk.Texture; 14 | import java.io.File; 15 | import java.io.FileNotFoundException; 16 | import java.io.IOException; 17 | import java.util.ArrayList; 18 | import java.util.List; 19 | 20 | /** 21 | * 22 | * @author Oger-Lord 23 | */ 24 | public class CreateBox { 25 | 26 | 27 | public static void main(String args[]) throws FileNotFoundException, IOException{ 28 | 29 | BlizzardDataOutputStream out = new BlizzardDataOutputStream(new File("Box.mdx")); 30 | MdxModel model = createBoxModel(); 31 | model.save(out); 32 | out.close(); 33 | } 34 | 35 | public static MdxModel createBoxModel() 36 | { 37 | MdxModel model = new MdxModel(); 38 | 39 | //Create the Geoset 40 | model.geosetChunk = new GeosetChunk(); 41 | createBoxGeoset(model.geosetChunk); 42 | 43 | //Create the Material 44 | model.materialChunk = new MaterialChunk(); 45 | createMaterial(model.materialChunk); 46 | 47 | //Create the Texture 48 | model.textureChunk = new TextureChunk(); 49 | createTexture(model.textureChunk); 50 | 51 | //This step is important so that the model can be displayed correctly 52 | //Generates the modelChunk, containing: 53 | // BlendTime, MinimumExtent, MaximumExtent, BoundRadius 54 | //Make sure that you set the geoset befor using this function 55 | ModelUtils.generateModelChunk(model, "Box"); 56 | 57 | return model; 58 | } 59 | 60 | private static void createMaterial(MaterialChunk materialChunk){ 61 | MaterialChunk.Material material = materialChunk.new Material(); 62 | 63 | material.layerChunk = new LayerChunk(); 64 | LayerChunk.Layer layer = material.layerChunk.new Layer(); 65 | 66 | layer.textureId = 0; //id of the texture 67 | layer.filterMode = 1; //constant color 68 | layer.alpha = 1; //no Transparency 69 | 70 | layer.materialAlpha = null; 71 | layer.textureAnimationId = -1; //No Texture Animation 72 | 73 | material.layerChunk.layer = new LayerChunk.Layer[1]; 74 | material.layerChunk.layer[0] = layer; 75 | 76 | materialChunk.material = new MaterialChunk.Material[1]; 77 | materialChunk.material[0] = material; 78 | } 79 | 80 | private static void createTexture(TextureChunk textureChunk){ 81 | TextureChunk.Texture texture = textureChunk.new Texture(); 82 | 83 | texture.fileName = "environment\\Sky\\LordaeronSummerSky\\LordaeronSummerSky.blp"; 84 | 85 | textureChunk.texture = new TextureChunk.Texture[1]; 86 | textureChunk.texture[0] = texture; 87 | } 88 | 89 | private static void createBoxGeoset(GeosetChunk geosetChunk){ 90 | 91 | GeosetChunk.Geoset geoset = geosetChunk.new Geoset(); 92 | 93 | //Create all 8 vertex points of the Box 94 | geoset.vertexPositions = new float[]{ -50f,-50f,0f, 95 | 50f,-50f,0f, 96 | 50f, 50f,0f, 97 | -50f, 50f,0f, 98 | -50f,-50f,100f, 99 | 50f,-50f,100f, 100 | 50f, 50f,100f, 101 | -50f, 50f,100f }; 102 | 103 | //Position of the vertices on the texture 104 | geoset.vertexTexturePositions = new float[]{ 105 | 0f,0f, 106 | 1f,0f, 107 | 1f,1f, 108 | 0f,1f, 109 | 0f,0f, 110 | 1f,0f, 111 | 1f,1f, 112 | 0f,1f 113 | }; 114 | 115 | //Create all 6 Sides 116 | List faces = new ArrayList(); 117 | 118 | createRectangle(faces,0,4,7,3); //Front 119 | createRectangle(faces,1,2,6,5); //Back 120 | 121 | createRectangle(faces,4,5,6,7); //Top 122 | createRectangle(faces,3,2,1,0); //Bottom 123 | 124 | createRectangle(faces,0,1,5,4); //Left 125 | createRectangle(faces,3,7,6,2); //Right 126 | 127 | geoset.faces = ModelUtils.convert2ShortArrayI(faces); 128 | 129 | //Set MaterialId for texture 130 | geoset.materialId = 0; 131 | 132 | //Calculate the extents/bounds 133 | ModelUtils.calculateExtent(geoset); 134 | 135 | //Calculate the normals 136 | ModelUtils.calculateNormals(geoset); 137 | 138 | //generate face and vertex groups 139 | ModelUtils.calculateVertexGroup(geoset); 140 | 141 | geosetChunk.geoset = new GeosetChunk.Geoset[1]; 142 | geosetChunk.geoset[0] = geoset; 143 | } 144 | 145 | 146 | private static void createRectangle(List faces, int iA, int iB, int iC, int iD){ 147 | //Add first triangle 148 | faces.add(iA); 149 | faces.add(iB); 150 | faces.add(iD); 151 | 152 | //Add second triangle 153 | faces.add(iB); 154 | faces.add(iC); 155 | faces.add(iD); 156 | 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /src/de/wc3data/image/ImageUtils.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.image; 2 | 3 | import java.awt.AlphaComposite; 4 | import java.awt.Color; 5 | import java.awt.Composite; 6 | import java.awt.Graphics2D; 7 | import java.awt.Image; 8 | import java.awt.RenderingHints; 9 | import java.awt.image.BufferedImage; 10 | 11 | public class ImageUtils { 12 | 13 | /** 14 | * Takes an images as input and generates an array containing this image and 15 | * all possible mipmaps 16 | * 17 | * @param input 18 | * @return 19 | */ 20 | public static BufferedImage[] generateMipMaps(BufferedImage input) { 21 | int num = 0; 22 | int curWidth = input.getWidth(); 23 | int curHeight = input.getHeight(); 24 | int pow; 25 | do { 26 | num++; 27 | pow = (int) Math.pow(2.0D, num - 1); 28 | } while ((pow < curWidth) || (pow < curHeight)); 29 | BufferedImage[] result = new BufferedImage[num]; 30 | result[0] = input; 31 | for (int i = 1; i < num; i++) { 32 | curWidth /= 2; 33 | curHeight /= 2; 34 | if (curHeight == 0) { 35 | curHeight = 1; 36 | } 37 | if (curWidth == 0) { 38 | curWidth = 1; 39 | } 40 | result[i] = ImageUtils.getScaledInstance(result[(i - 1)], curWidth, curHeight, RenderingHints.VALUE_INTERPOLATION_BICUBIC, true); 41 | } 42 | return result; 43 | } 44 | 45 | /** 46 | * Scales an Image 47 | * 48 | * @param img 49 | * @param targetWidth 50 | * @param targetHeight 51 | * @param hint Rendering Hint 52 | * @param higherQuality 53 | * @return 54 | */ 55 | public static BufferedImage getScaledInstance(BufferedImage img, int targetWidth, int targetHeight, Object hint, boolean higherQuality) { 56 | int type = img.getTransparency() == 1 57 | ? 1 : 2; 58 | BufferedImage ret = img; 59 | int h; 60 | int w; 61 | if (higherQuality) { 62 | w = img.getWidth(); 63 | h = img.getHeight(); 64 | } else { 65 | w = targetWidth; 66 | h = targetHeight; 67 | } 68 | do { 69 | if ((higherQuality) && (w > targetWidth)) { 70 | w /= 2; 71 | if (w < targetWidth) { 72 | w = targetWidth; 73 | } 74 | } 75 | if ((higherQuality) && (h > targetHeight)) { 76 | h /= 2; 77 | if (h < targetHeight) { 78 | h = targetHeight; 79 | } 80 | } 81 | 82 | 83 | BufferedImage tmp; 84 | if(img.getColorModel().hasAlpha() == false){ 85 | tmp= new BufferedImage(w, h, type); 86 | Graphics2D g2 = tmp.createGraphics(); 87 | g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint); 88 | g2.drawImage(ret, 0, 0, w, h, null); 89 | g2.dispose(); 90 | }else{ 91 | //Necessary because otherwise Bilinear resize would couse transparent pixel to change color 92 | tmp = resizeWorkAround(ret,w,h, hint); 93 | } 94 | 95 | ret = tmp; 96 | } while ((w != targetWidth) || (h != targetHeight)); 97 | return ret; 98 | } 99 | 100 | private static BufferedImage resizeWorkAround(BufferedImage ret, int w, int h, Object hint) { 101 | 102 | BufferedImage noAlpha = new BufferedImage(ret.getWidth(), ret.getHeight(), BufferedImage.TYPE_INT_ARGB); 103 | 104 | for (int x = 0; x < ret.getWidth(); x++) { 105 | for (int y = 0; y < ret.getHeight(); y++) { 106 | int color = ret.getRGB(x, y); 107 | color = color | 0xff000000; 108 | noAlpha.setRGB(x, y, color); 109 | } 110 | } 111 | 112 | BufferedImage noAlphaSmall = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); 113 | Graphics2D g2 = noAlphaSmall.createGraphics(); 114 | g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint); 115 | g2.drawImage(noAlpha, 0, 0, w, h, null); 116 | g2.dispose(); 117 | 118 | 119 | BufferedImage tmp = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); 120 | g2 = tmp.createGraphics(); 121 | g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint); 122 | g2.drawImage(ret, 0, 0, w, h, null); 123 | g2.dispose(); 124 | 125 | noAlphaSmall.getAlphaRaster().setRect(0, 0, tmp.getAlphaRaster()); 126 | 127 | return noAlphaSmall; 128 | } 129 | 130 | /** 131 | * An alternative way to convert an image to type_byte_indexed (paletted) 132 | * that avoids dithering. 133 | * 134 | * @param src 135 | * @return 136 | */ 137 | public static BufferedImage antiDitherConvert(BufferedImage src) { 138 | BufferedImage convertedImage = new BufferedImage(src.getWidth(), src.getHeight(), BufferedImage.TYPE_BYTE_INDEXED); 139 | for (int x = 0; x < src.getWidth(); x++) { 140 | for (int y = 0; y < src.getHeight(); y++) { 141 | convertedImage.setRGB(x, y, src.getRGB(x, y)); 142 | } 143 | } 144 | return convertedImage; 145 | } 146 | 147 | public static BufferedImage changeImageType(BufferedImage src, int type) { 148 | BufferedImage img = new BufferedImage(src.getWidth(), src.getHeight(), type); 149 | Graphics2D g = (Graphics2D) img.getGraphics(); 150 | 151 | if (img.getColorModel().hasAlpha()) { 152 | Composite comp = AlphaComposite.getInstance(AlphaComposite.SRC); 153 | g.setComposite(comp); 154 | } 155 | 156 | g.drawImage(src, 0, 0, null); 157 | g.dispose(); 158 | 159 | return img; 160 | } 161 | 162 | public static BufferedImage convertStandardImageType(BufferedImage src, boolean useAlpha) { 163 | 164 | if (useAlpha && src.getType() == BufferedImage.TYPE_INT_ARGB) { 165 | return src; 166 | } 167 | 168 | if (useAlpha == false && src.getType() == BufferedImage.TYPE_INT_RGB) { 169 | return src; 170 | } 171 | 172 | return ImageUtils.changeImageType(src, useAlpha ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB); 173 | 174 | } 175 | } -------------------------------------------------------------------------------- /src/de/wc3data/image/TgaFile.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this template, choose Tools | Templates 3 | * and open the template in the editor. 4 | */ 5 | package de.wc3data.image; 6 | 7 | import java.awt.image.BufferedImage; 8 | import java.awt.image.DataBuffer; 9 | import java.awt.image.DataBufferByte; 10 | import java.awt.image.DataBufferInt; 11 | import java.io.ByteArrayOutputStream; 12 | import java.io.File; 13 | import java.io.FileInputStream; 14 | import java.io.FileNotFoundException; 15 | import java.io.IOException; 16 | import java.io.InputStream; 17 | import java.io.RandomAccessFile; 18 | 19 | /** 20 | * 21 | * @author Riven, modified by Oger-Lord 22 | */ 23 | public class TgaFile { 24 | 25 | /** 26 | * Read a TGA image from a file 27 | * @param file 28 | * @return 29 | * @throws FileNotFoundException 30 | * @throws IOException 31 | */ 32 | public static BufferedImage readTGA(File file) throws FileNotFoundException, IOException{ 33 | return readTGA(file.getName(),new FileInputStream(file)); 34 | 35 | } 36 | 37 | /** 38 | * Read a TGA image from an input stream. 39 | * @param name 40 | * @param stream 41 | * @return 42 | * @throws IOException 43 | */ 44 | public static BufferedImage readTGA(String name, InputStream stream) throws IOException { 45 | 46 | //Read Header 47 | byte[] header = new byte[18]; 48 | stream.read(header); 49 | 50 | //Read pixel data 51 | ByteArrayOutputStream buffer = new ByteArrayOutputStream(); 52 | int nRead; 53 | byte[] data = new byte[16384]; 54 | 55 | while ((nRead = stream.read(data, 0, data.length)) != -1) { 56 | buffer.write(data, 0, nRead); 57 | } 58 | buffer.flush(); 59 | data = buffer.toByteArray(); 60 | 61 | 62 | //Verify Header 63 | if ((header[0] | header[1]) != 0) { 64 | throw new IllegalStateException("Error " + name); 65 | } 66 | if (header[2] != 2) { 67 | throw new IllegalStateException("Error " + name); 68 | } 69 | int w = 0, h = 0; 70 | w |= (header[12] & 0xFF) << 0; 71 | w |= (header[13] & 0xFF) << 8; 72 | h |= (header[14] & 0xFF) << 0; 73 | h |= (header[15] & 0xFF) << 8; 74 | 75 | boolean alpha; 76 | 77 | if((header[16] == 24)){ 78 | alpha = false; 79 | }else if(header[16] == 32){ 80 | alpha=true; 81 | }else{ 82 | throw new IllegalStateException("Error " + name + " invalid pixel depth: " + header[16] ); 83 | } 84 | 85 | if ((header[17] & 15) != (alpha ? 8 : 0)) { 86 | throw new IllegalStateException("Error " + name); 87 | } 88 | 89 | 90 | BufferedImage dst = new BufferedImage(w, h, alpha ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB); 91 | int[] pixels = ((DataBufferInt) dst.getRaster().getDataBuffer()).getData(); 92 | if (pixels.length != w * h) { 93 | throw new IllegalStateException("Error " + name); 94 | } 95 | if (data.length < pixels.length * (alpha ? 4 : 3)) { 96 | throw new IllegalStateException("Error " + name + " not enaugh pixel data"); 97 | } 98 | 99 | if (alpha) { 100 | for (int i = 0, p = (pixels.length - 1) * 4; i < pixels.length; i++, p -= 4) { 101 | pixels[i] |= ((data[p + 0]) & 0xFF) << 0; 102 | pixels[i] |= ((data[p + 1]) & 0xFF) << 8; 103 | pixels[i] |= ((data[p + 2]) & 0xFF) << 16; 104 | pixels[i] |= ((data[p + 3]) & 0xFF) << 24; 105 | } 106 | } else { 107 | for (int i = 0, p = (pixels.length - 1) * 3; i < pixels.length; i++, p -= 3) { 108 | pixels[i] |= ((data[p + 0]) & 0xFF) << 0; 109 | pixels[i] |= ((data[p + 1]) & 0xFF) << 8; 110 | pixels[i] |= ((data[p + 2]) & 0xFF) << 16; 111 | } 112 | } 113 | 114 | if ((header[17] >> 4) == 1) { 115 | // ok 116 | } else if ((header[17] >> 4) == 0) { 117 | // flip horizontally 118 | 119 | for (int y = 0; y < h; y++) { 120 | int w2 = w / 2; 121 | for (int x = 0; x < w2; x++) { 122 | int a = (y * w) + x; 123 | int b = (y * w) + (w - 1 - x); 124 | int t = pixels[a]; 125 | pixels[a] = pixels[b]; 126 | pixels[b] = t; 127 | } 128 | } 129 | } else { 130 | throw new UnsupportedOperationException("Error " + name); 131 | } 132 | 133 | return dst; 134 | } 135 | 136 | /** 137 | * Write a BufferedImage to a TGA file 138 | * BufferedImages should be TYPE_INT_ARGB or TYPE_INT_RGB 139 | * @param src 140 | * @param file 141 | * @throws IOException 142 | */ 143 | public static void writeTGA(BufferedImage src, File file) throws IOException { 144 | 145 | boolean alpha = src.getColorModel().hasAlpha(); 146 | src = ImageUtils.convertStandardImageType(src, alpha); 147 | 148 | DataBuffer buffer = src.getRaster().getDataBuffer(); 149 | byte[] data; 150 | 151 | if (buffer instanceof DataBufferByte) { 152 | 153 | //Not used anymore because convert to standard image type => Buffer is int 154 | byte[] pixels = ((DataBufferByte) src.getRaster().getDataBuffer()).getData(); 155 | if (pixels.length != src.getWidth() * src.getHeight() * (alpha ? 4 : 3)) { 156 | throw new IllegalStateException(); 157 | } 158 | 159 | data = pixels; 160 | 161 | } else if (buffer instanceof DataBufferInt) { 162 | 163 | int[] pixels = ((DataBufferInt) src.getRaster().getDataBuffer()).getData(); 164 | if (pixels.length != src.getWidth() * src.getHeight()) { 165 | throw new IllegalStateException(); 166 | } 167 | 168 | data = new byte[pixels.length * (alpha ? 4 : 3)]; 169 | 170 | if (alpha) { 171 | 172 | for (int p = 0; p < pixels.length; p++) { 173 | int i = p*4; 174 | data[i + 0] = (byte) ((pixels[p] >> 0) & 0xFF); 175 | data[i + 1] = (byte) ((pixels[p] >> 8) & 0xFF); 176 | data[i + 2] = (byte) ((pixels[p] >> 16) & 0xFF); 177 | data[i + 3] = (byte) ((pixels[p] >> 24) & 0xFF); 178 | } 179 | } else { 180 | 181 | for (int p = 0; p < pixels.length; p++) { 182 | int i = p*3; 183 | data[i + 0] = (byte) ((pixels[p] >> 0) & 0xFF); 184 | data[i + 1] = (byte) ((pixels[p] >> 8) & 0xFF); 185 | data[i + 2] = (byte) ((pixels[p] >> 16) & 0xFF); 186 | } 187 | } 188 | } else { 189 | throw new UnsupportedOperationException(); 190 | } 191 | 192 | byte[] header = new byte[18]; 193 | header[2] = 2; // uncompressed, true-color image 194 | header[12] = (byte) ((src.getWidth() >> 0) & 0xFF); 195 | header[13] = (byte) ((src.getWidth() >> 8) & 0xFF); 196 | header[14] = (byte) ((src.getHeight() >> 0) & 0xFF); 197 | header[15] = (byte) ((src.getHeight() >> 8) & 0xFF); 198 | header[16] = (byte) (alpha ? 32 : 24); // bits per pixel 199 | header[17] = (byte) ((alpha ? 8 : 0) | (2 << 4)); 200 | 201 | RandomAccessFile raf = new RandomAccessFile(file, "rw"); 202 | raf.write(header); 203 | raf.write(data); 204 | raf.setLength(raf.getFilePointer()); // trim 205 | raf.close(); 206 | } 207 | } 208 | -------------------------------------------------------------------------------- /src/de/wc3data/map/ShadowMap.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this template, choose Tools | Templates 3 | * and open the template in the editor. 4 | */ 5 | package de.wc3data.map; 6 | 7 | import java.awt.Color; 8 | import java.awt.Graphics2D; 9 | import java.awt.image.BufferedImage; 10 | import java.io.File; 11 | import java.io.FileInputStream; 12 | import java.io.FileNotFoundException; 13 | import java.io.FileOutputStream; 14 | import java.io.IOException; 15 | import java.io.InputStream; 16 | import java.io.OutputStream; 17 | 18 | 19 | /** 20 | * 21 | * This class is able to load and save war3map.shd files. 22 | * 23 | * @author Karsten 24 | */ 25 | public class ShadowMap { 26 | 27 | private boolean[][] shadowMap; 28 | 29 | public ShadowMap() { 30 | } 31 | 32 | public ShadowMap(boolean[][] shadowMap) { 33 | this.shadowMap = shadowMap; 34 | } 35 | 36 | public void save(File file) throws IOException { 37 | OutputStream out = new FileOutputStream(file); 38 | save(out); 39 | } 40 | 41 | public void save(OutputStream stream) throws IOException { 42 | for (int y = shadowMap[0].length - 1; y >= 0; y--) { 43 | for (int x = 0; x < shadowMap.length; x++) { 44 | if (shadowMap[x][y]) { 45 | 46 | stream.write(0xFF); 47 | } else { 48 | stream.write(0x00); 49 | } 50 | } 51 | } 52 | 53 | stream.flush(); 54 | } 55 | 56 | /** 57 | * 58 | * @param file The war3map.shd to load. 59 | * @param sizeTerrainX The X size of the terrain (w3e) 60 | * @param sizeTerrainY The Y size of the terrain (w3e) 61 | * @throws FileNotFoundException 62 | * @throws IOException 63 | */ 64 | public void load(File file, int sizeTerrainX, int sizeTerrainY) throws FileNotFoundException, IOException { 65 | InputStream stream = new FileInputStream(file); 66 | load(stream, sizeTerrainX, sizeTerrainY); 67 | } 68 | 69 | /** 70 | * 71 | * @param stream 72 | * @param sizeTerrainX The X size of the terrain (w3e) 73 | * @param sizeTerrainY The Y size of the terrain (w3e) 74 | * @throws IOException 75 | */ 76 | public void load(InputStream stream, int sizeTerrainX, int sizeTerrainY) throws IOException { 77 | shadowMap = new boolean[sizeTerrainX*4][sizeTerrainY*4]; 78 | 79 | for (int y = shadowMap[0].length - 1; y >= 0; y--) { 80 | 81 | byte b[] = new byte[shadowMap.length]; 82 | stream.read(b); 83 | 84 | for (int x = 0; x < shadowMap.length; x++) { 85 | 86 | if (b[x] == -1) { 87 | shadowMap[x][y] = true; 88 | } else { 89 | shadowMap[x][y] = false; 90 | } 91 | } 92 | } 93 | } 94 | 95 | /** 96 | * Converts the shadowmap into an BufferedImage. Black for shadow, white for no shadow. 97 | * @return 98 | */ 99 | public BufferedImage convert2BufferedImage() { 100 | BufferedImage image = new BufferedImage(shadowMap.length, shadowMap[0].length, BufferedImage.TYPE_INT_RGB); 101 | Graphics2D g = (Graphics2D) image.getGraphics(); 102 | 103 | for (int x = 0; x < shadowMap.length; x++) { 104 | for (int y = 0; y < shadowMap[0].length; y++) { 105 | 106 | if (shadowMap[x][y]) { 107 | g.setColor(Color.BLACK); 108 | } else { 109 | g.setColor(Color.WHITE); 110 | } 111 | g.fillRect(x, y, 1, 1); 112 | } 113 | } 114 | g.dispose(); 115 | return image; 116 | } 117 | 118 | /** 119 | * Converts an image into a shadowmap. Dark colors for shadow, bright colors for no shadow. 120 | * @param image 121 | */ 122 | public void fromBufferedImage(BufferedImage image) { 123 | shadowMap = new boolean[image.getWidth()][image.getHeight()]; 124 | 125 | for (int x = 0; x < shadowMap.length; x++) { 126 | for (int y = 0; y < shadowMap[0].length; y++) { 127 | int clr = image.getRGB(x, y); 128 | int red = (clr & 0x00ff0000) >> 16; 129 | int green = (clr & 0x0000ff00) >> 8; 130 | int blue = clr & 0x000000ff; 131 | 132 | if (red + green + blue < 128 * 3) { 133 | shadowMap[x][y] = true; 134 | } else { 135 | shadowMap[x][y] = false; 136 | } 137 | } 138 | } 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/AttachmentChunk.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class AttachmentChunk { 8 | public Attachment[] attachment = new Attachment[0]; 9 | 10 | public static final String key = "ATCH"; 11 | 12 | public void load(BlizzardDataInputStream in) throws IOException { 13 | StreamUtils.checkId(in, "ATCH"); 14 | int chunkSize = in.readInt(); 15 | List attachmentList = new ArrayList(); 16 | int attachmentCounter = chunkSize; 17 | while (attachmentCounter > 0) { 18 | Attachment tempattachment = new Attachment(); 19 | attachmentList.add(tempattachment); 20 | tempattachment.load(in); 21 | attachmentCounter -= tempattachment.getSize(); 22 | } 23 | attachment = attachmentList.toArray(new Attachment[attachmentList 24 | .size()]); 25 | } 26 | 27 | public void save(BlizzardDataOutputStream out) throws IOException { 28 | int nrOfAttachments = attachment.length; 29 | out.writeNByteString("ATCH", 4); 30 | out.writeInt(getSize() - 8);// ChunkSize 31 | for (int i = 0; i < attachment.length; i++) { 32 | attachment[i].save(out); 33 | } 34 | 35 | } 36 | 37 | public int getSize() { 38 | int a = 0; 39 | a += 4; 40 | a += 4; 41 | for (int i = 0; i < attachment.length; i++) { 42 | a += attachment[i].getSize(); 43 | } 44 | 45 | return a; 46 | } 47 | 48 | public class Attachment { 49 | public Node node = new Node(); 50 | public String unknownName = ""; 51 | public int unknownNull; 52 | public int attachmentId; 53 | public AttachmentVisibility attachmentVisibility; 54 | 55 | public void load(BlizzardDataInputStream in) throws IOException { 56 | int inclusiveSize = in.readInt(); 57 | node = new Node(); 58 | node.load(in); 59 | unknownName = in.readCharsAsString(256); 60 | unknownNull = in.readInt(); 61 | attachmentId = in.readInt(); 62 | if (StreamUtils.checkOptionalId(in, attachmentVisibility.key)) { 63 | attachmentVisibility = new AttachmentVisibility(); 64 | attachmentVisibility.load(in); 65 | } 66 | 67 | } 68 | 69 | public void save(BlizzardDataOutputStream out) throws IOException { 70 | out.writeInt(getSize());// InclusiveSize 71 | node.save(out); 72 | out.writeNByteString(unknownName, 256); 73 | out.writeInt(unknownNull); 74 | out.writeInt(attachmentId); 75 | if (attachmentVisibility != null) { 76 | attachmentVisibility.save(out); 77 | } 78 | 79 | } 80 | 81 | public int getSize() { 82 | int a = 0; 83 | a += 4; 84 | a += node.getSize(); 85 | a += 256; 86 | a += 4; 87 | a += 4; 88 | if (attachmentVisibility != null) { 89 | a += attachmentVisibility.getSize(); 90 | } 91 | 92 | return a; 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/AttachmentVisibility.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class AttachmentVisibility { 8 | public int interpolationType; 9 | public int globalSequenceId; 10 | public ScalingTrack[] scalingTrack = new ScalingTrack[0]; 11 | 12 | public static final String key = "KATV"; 13 | 14 | public void load(BlizzardDataInputStream in) throws IOException { 15 | StreamUtils.checkId(in, "KATV"); 16 | int nrOfTracks = in.readInt(); 17 | interpolationType = in.readInt(); 18 | globalSequenceId = in.readInt(); 19 | scalingTrack = new ScalingTrack[nrOfTracks]; 20 | for (int i = 0; i < nrOfTracks; i++) { 21 | scalingTrack[i] = new ScalingTrack(); 22 | scalingTrack[i].load(in); 23 | } 24 | } 25 | 26 | public void save(BlizzardDataOutputStream out) throws IOException { 27 | int nrOfTracks = scalingTrack.length; 28 | out.writeNByteString("KATV", 4); 29 | out.writeInt(nrOfTracks); 30 | out.writeInt(interpolationType); 31 | out.writeInt(globalSequenceId); 32 | for (int i = 0; i < scalingTrack.length; i++) { 33 | scalingTrack[i].save(out); 34 | } 35 | 36 | } 37 | 38 | public int getSize() { 39 | int a = 0; 40 | a += 4; 41 | a += 4; 42 | a += 4; 43 | a += 4; 44 | for (int i = 0; i < scalingTrack.length; i++) { 45 | a += scalingTrack[i].getSize(); 46 | } 47 | 48 | return a; 49 | } 50 | 51 | public class ScalingTrack { 52 | public int time; 53 | public float visibility; 54 | public float inTan; 55 | public float outTan; 56 | 57 | public void load(BlizzardDataInputStream in) throws IOException { 58 | time = in.readInt(); 59 | visibility = in.readFloat(); 60 | if (interpolationType > 1) { 61 | inTan = in.readFloat(); 62 | outTan = in.readFloat(); 63 | } 64 | } 65 | 66 | public void save(BlizzardDataOutputStream out) throws IOException { 67 | out.writeInt(time); 68 | out.writeFloat(visibility); 69 | if (interpolationType > 1) { 70 | out.writeFloat(inTan); 71 | out.writeFloat(outTan); 72 | } 73 | 74 | } 75 | 76 | public int getSize() { 77 | int a = 0; 78 | a += 4; 79 | a += 4; 80 | if (interpolationType > 1) { 81 | a += 4; 82 | a += 4; 83 | } 84 | 85 | return a; 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/BlizzardDataInputStream.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import java.io.BufferedInputStream; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.io.PrintStream; 7 | 8 | public class BlizzardDataInputStream extends BufferedInputStream { 9 | private long offset = 0L; 10 | 11 | public BlizzardDataInputStream(InputStream in) { 12 | super(in); 13 | } 14 | 15 | private static int convertToInt(byte[] b) { 16 | return b[0] & 0xFF | (b[1] & 0xFF) << 8 | (b[2] & 0xFF) << 16 17 | | (b[3] & 0xFF) << 24; 18 | } 19 | 20 | private static int convertNToInt(byte[] b) { 21 | int result = 0; 22 | for (int i = 0; i < b.length; i++) { 23 | result |= (b[i] & 0xFF) << i * 8; 24 | } 25 | return result; 26 | } 27 | 28 | private static short convertToShort(byte[] b) { 29 | int result = 0; 30 | 31 | for (int i = 0; i < b.length; i++) { 32 | result |= (b[i] & 0xFF) << i * 8; 33 | } 34 | return (short) result; 35 | // return (short)(b[0] << 8 | b[1] & 0xFF); 36 | } 37 | 38 | /* 39 | * public long skip(long count) throws IOException { 40 | * System.out.println("Skipping: " + count); throw new 41 | * Error("BDIS: skip is buggy!"); } 42 | */ 43 | 44 | public long getOffset() { 45 | return this.offset; 46 | } 47 | 48 | public byte readByte() throws IOException { 49 | byte[] b = new byte[1]; 50 | this.offset += 1L; 51 | read(b); 52 | return b[0]; 53 | } 54 | 55 | public int read(byte[] b) throws IOException { 56 | this.offset += b.length; 57 | return super.read(b); 58 | } 59 | 60 | public void skipUntilZeroInt() throws IOException { 61 | int numZeroBytes = 0; 62 | for (;;) { 63 | this.offset += 1L; 64 | int readByte; 65 | if ((readByte = read()) == 0) { 66 | numZeroBytes++; 67 | if (numZeroBytes != 4) { 68 | } 69 | } else { 70 | if (readByte == -1) { 71 | return; 72 | } 73 | numZeroBytes = 0; 74 | } 75 | } 76 | } 77 | 78 | public short readShort() throws IOException { 79 | byte[] b = new byte[2]; 80 | this.offset += 2L; 81 | read(b, 0, 2); 82 | return convertToShort(b); 83 | } 84 | 85 | public int readInt() throws IOException { 86 | byte[] b = new byte[4]; 87 | this.offset += 4L; 88 | read(b, 0, 4); 89 | return convertToInt(b); 90 | } 91 | 92 | public int readNByteInt(int numBytes) throws IOException { 93 | byte[] b = new byte[numBytes]; 94 | this.offset += numBytes; 95 | read(b, 0, numBytes); 96 | return convertNToInt(b); 97 | } 98 | 99 | public boolean readBool() throws IOException { 100 | return readInt() == 1; 101 | } 102 | 103 | public float readFloat() throws IOException { 104 | return Float.intBitsToFloat(readInt()); 105 | } 106 | 107 | public char readChar() throws IOException { 108 | this.offset += 1L; 109 | return (char) read(); 110 | } 111 | 112 | public char[] readChars(int charCount) throws IOException { 113 | char[] c = new char[charCount]; 114 | for (int i = 0; i < charCount; i++) { 115 | c[i] = readChar(); 116 | } 117 | return c; 118 | } 119 | 120 | public String readCharsAsString(int charCount) throws IOException { 121 | char[] c = readChars(charCount); 122 | for (int i = 0; i < charCount; i++) { 123 | if (c[i] == 0) { 124 | return String.valueOf(c, 0, i); 125 | } 126 | } 127 | return String.valueOf(c); 128 | } 129 | 130 | public String readCharsAsStringCheckNull(int charCount) throws IOException { 131 | char[] result = readChars(charCount); 132 | boolean isNull = true; 133 | for (int i = 0; i < charCount; i++) { 134 | if (result[i] != 0) { 135 | isNull = false; 136 | } 137 | } 138 | if (isNull) { 139 | return null; 140 | } 141 | return String.valueOf(result); 142 | } 143 | 144 | public String readExportSig() throws IOException { 145 | char[] c = readChars(4); 146 | for (int i = 0; i < 4; i++) { 147 | if (c[i] == 65535) { 148 | return null; 149 | } 150 | } 151 | return String.valueOf(c); 152 | } 153 | 154 | public String readString() throws IOException { 155 | StringBuilder sb = new StringBuilder(16); 156 | int curVal = read(); 157 | while (curVal != 0) { 158 | if (curVal == -1) { 159 | return null; 160 | } 161 | sb.append((char) curVal); 162 | curVal = read(); 163 | this.offset += 1L; 164 | } 165 | this.offset += 1L; 166 | return sb.toString(); 167 | } 168 | 169 | public void close() throws IOException { 170 | this.in.close(); 171 | } 172 | } -------------------------------------------------------------------------------- /src/de/wc3data/mdx/BlizzardDataOutputStream.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import java.io.BufferedOutputStream; 4 | import java.io.File; 5 | import java.io.FileNotFoundException; 6 | import java.io.FileOutputStream; 7 | import java.io.IOException; 8 | 9 | public class BlizzardDataOutputStream extends BufferedOutputStream { 10 | 11 | public BlizzardDataOutputStream(File file) throws FileNotFoundException { 12 | super(new FileOutputStream(file)); 13 | } 14 | 15 | public BlizzardDataOutputStream(File file, boolean append) 16 | throws FileNotFoundException { 17 | super(new FileOutputStream(file, append)); 18 | } 19 | 20 | static byte[] convertIntToByteArray(int i) { 21 | byte[] result = new byte[4]; 22 | long l = i >= 0 ? i : 4294967296L + i; 23 | for (int j = 0; j < 4; j++) { 24 | result[j] = ((byte) (int) (l % 256L)); 25 | l /= 256L; 26 | } 27 | return result; 28 | } 29 | 30 | static byte[] convertIntToNByteArray(int i, int numBytes) { 31 | byte[] result = new byte[numBytes]; 32 | long l = i >= 0 ? i : 4294967296L + i; 33 | for (int j = 0; j < numBytes; j++) { 34 | result[j] = ((byte) (int) (l % 256L)); 35 | l /= 256L; 36 | } 37 | return result; 38 | } 39 | 40 | public void writeChars(char[] toWrite) throws IOException { 41 | byte[] b = new byte[toWrite.length]; 42 | for (int i = 0; i < toWrite.length; i++) { 43 | b[i] = ((byte) toWrite[i]); 44 | } 45 | write(b); 46 | } 47 | 48 | public void writeInt(int toWrite) throws IOException { 49 | write(convertIntToByteArray(toWrite)); 50 | } 51 | 52 | public void writeShort(short toWrite) throws IOException { 53 | write(convertIntToNByteArray(toWrite, 2)); 54 | } 55 | 56 | public void writeNByteInt(int toWrite, int numBytes) throws IOException { 57 | write(convertIntToNByteArray(toWrite, numBytes)); 58 | } 59 | 60 | public void writeBool(boolean toWrite) throws IOException { 61 | writeInt(toWrite ? 1 : 0); 62 | } 63 | 64 | public void writeByte(int toWrite) throws IOException { 65 | write(new byte[] { (byte) toWrite }); 66 | } 67 | 68 | public void writeFloat(float toWrite) throws IOException { 69 | writeInt(Float.floatToIntBits(toWrite)); 70 | } 71 | 72 | public void writeFourByteString(String toWrite) throws IOException { 73 | byte[] result = new byte[4]; 74 | for (int i = 0; i < 4; i++) { 75 | if ((toWrite != null) && (i < toWrite.length())) { 76 | result[i] = ((byte) toWrite.charAt(i)); 77 | } else { 78 | result[i] = 0; 79 | } 80 | } 81 | write(result); 82 | } 83 | 84 | public void writeNByteString(String toWrite, int charCount) 85 | throws IOException { 86 | byte[] result = new byte[charCount]; 87 | for (int i = 0; i < charCount; i++) { 88 | if ((toWrite != null) && (i < toWrite.length())) { 89 | result[i] = ((byte) toWrite.charAt(i)); 90 | } else { 91 | result[i] = 0; 92 | } 93 | } 94 | write(result); 95 | } 96 | 97 | public void writeString(String toWrite) throws IOException { 98 | int length; 99 | if (toWrite == null) { 100 | length = 0; 101 | } else { 102 | length = toWrite.length(); 103 | } 104 | byte[] result = new byte[length + 1]; 105 | for (int i = 0; i < length; i++) { 106 | result[i] = ((byte) toWrite.charAt(i)); 107 | } 108 | result[length] = 0; 109 | write(result); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/BoneChunk.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class BoneChunk { 8 | public Bone[] bone = new Bone[0]; 9 | 10 | public static final String key = "BONE"; 11 | 12 | public void load(BlizzardDataInputStream in) throws IOException { 13 | StreamUtils.checkId(in, "BONE"); 14 | int chunkSize = in.readInt(); 15 | List boneList = new ArrayList(); 16 | int boneCounter = chunkSize; 17 | while (boneCounter > 0) { 18 | Bone tempbone = new Bone(); 19 | boneList.add(tempbone); 20 | tempbone.load(in); 21 | boneCounter -= tempbone.getSize(); 22 | } 23 | bone = boneList.toArray(new Bone[boneList.size()]); 24 | } 25 | 26 | public void save(BlizzardDataOutputStream out) throws IOException { 27 | int nrOfBones = bone.length; 28 | out.writeNByteString("BONE", 4); 29 | out.writeInt(getSize() - 8);// ChunkSize 30 | for (int i = 0; i < bone.length; i++) { 31 | bone[i].save(out); 32 | } 33 | 34 | } 35 | 36 | public int getSize() { 37 | int a = 0; 38 | a += 4; 39 | a += 4; 40 | for (int i = 0; i < bone.length; i++) { 41 | a += bone[i].getSize(); 42 | } 43 | 44 | return a; 45 | } 46 | 47 | public class Bone { 48 | public Node node = new Node(); 49 | public int geosetId; 50 | public int geosetAnimationId; 51 | 52 | public void load(BlizzardDataInputStream in) throws IOException { 53 | node = new Node(); 54 | node.load(in); 55 | geosetId = in.readInt(); 56 | geosetAnimationId = in.readInt(); 57 | } 58 | 59 | public void save(BlizzardDataOutputStream out) throws IOException { 60 | node.save(out); 61 | out.writeInt(geosetId); 62 | out.writeInt(geosetAnimationId); 63 | 64 | } 65 | 66 | public int getSize() { 67 | int a = 0; 68 | a += node.getSize(); 69 | a += 4; 70 | a += 4; 71 | 72 | return a; 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/CameraChunk.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class CameraChunk { 8 | public Camera[] camera = new Camera[0]; 9 | 10 | public static final String key = "CAMS"; 11 | 12 | public void load(BlizzardDataInputStream in) throws IOException { 13 | StreamUtils.checkId(in, "CAMS"); 14 | int chunkSize = in.readInt(); 15 | List cameraList = new ArrayList(); 16 | int cameraCounter = chunkSize; 17 | while (cameraCounter > 0) { 18 | Camera tempcamera = new Camera(); 19 | cameraList.add(tempcamera); 20 | tempcamera.load(in); 21 | cameraCounter -= tempcamera.getSize(); 22 | } 23 | camera = cameraList.toArray(new Camera[cameraList.size()]); 24 | } 25 | 26 | public void save(BlizzardDataOutputStream out) throws IOException { 27 | int nrOfCameras = camera.length; 28 | out.writeNByteString("CAMS", 4); 29 | out.writeInt(getSize() - 8);// ChunkSize 30 | for (int i = 0; i < camera.length; i++) { 31 | camera[i].save(out); 32 | } 33 | 34 | } 35 | 36 | public int getSize() { 37 | int a = 0; 38 | a += 4; 39 | a += 4; 40 | for (int i = 0; i < camera.length; i++) { 41 | a += camera[i].getSize(); 42 | } 43 | 44 | return a; 45 | } 46 | 47 | public class Camera { 48 | public String name = ""; 49 | public float[] position = new float[3]; 50 | public float fieldOfView; 51 | public float farClippingPlane; 52 | public float nearClippingPlane; 53 | public float[] targetPosition = new float[3]; 54 | public CameraPositionTranslation cameraPositionTranslation; 55 | public CameraRotation cameraRotation; 56 | public CameraTargetTranslation cameraTargetTranslation; 57 | 58 | public void load(BlizzardDataInputStream in) throws IOException { 59 | int inclusiveSize = in.readInt(); 60 | name = in.readCharsAsString(80); 61 | position = StreamUtils.loadFloatArray(in, 3); 62 | fieldOfView = in.readFloat(); 63 | farClippingPlane = in.readFloat(); 64 | nearClippingPlane = in.readFloat(); 65 | targetPosition = StreamUtils.loadFloatArray(in, 3); 66 | for (int i = 0; i < 3; i++) { 67 | if (StreamUtils.checkOptionalId(in, cameraPositionTranslation.key)) { 68 | cameraPositionTranslation = new CameraPositionTranslation(); 69 | cameraPositionTranslation.load(in); 70 | } else if (StreamUtils.checkOptionalId(in, 71 | cameraRotation.key)) { 72 | cameraRotation = new CameraRotation(); 73 | cameraRotation.load(in); 74 | } else if (StreamUtils.checkOptionalId(in, 75 | cameraTargetTranslation.key)) { 76 | cameraTargetTranslation = new CameraTargetTranslation(); 77 | cameraTargetTranslation.load(in); 78 | } 79 | 80 | } 81 | } 82 | 83 | public void save(BlizzardDataOutputStream out) throws IOException { 84 | out.writeInt(getSize());// InclusiveSize 85 | out.writeNByteString(name, 80); 86 | if (position.length % 3 != 0) { 87 | throw new IllegalArgumentException( 88 | "The array position needs either the length 3 or a multiple of this number. (got " 89 | + position.length + ")"); 90 | } 91 | StreamUtils.saveFloatArray(out, position); 92 | out.writeFloat(fieldOfView); 93 | out.writeFloat(farClippingPlane); 94 | out.writeFloat(nearClippingPlane); 95 | if (targetPosition.length % 3 != 0) { 96 | throw new IllegalArgumentException( 97 | "The array targetPosition needs either the length 3 or a multiple of this number. (got " 98 | + targetPosition.length + ")"); 99 | } 100 | StreamUtils.saveFloatArray(out, targetPosition); 101 | if (cameraPositionTranslation != null) { 102 | cameraPositionTranslation.save(out); 103 | } 104 | if (cameraRotation != null) { 105 | cameraRotation.save(out); 106 | } 107 | if (cameraTargetTranslation != null) { 108 | cameraTargetTranslation.save(out); 109 | } 110 | 111 | } 112 | 113 | public int getSize() { 114 | int a = 0; 115 | a += 4; 116 | a += 80; 117 | a += 12; 118 | a += 4; 119 | a += 4; 120 | a += 4; 121 | a += 12; 122 | if (cameraPositionTranslation != null) { 123 | a += cameraPositionTranslation.getSize(); 124 | } 125 | if (cameraRotation != null) { 126 | a += cameraRotation.getSize(); 127 | } 128 | if (cameraTargetTranslation != null) { 129 | a += cameraTargetTranslation.getSize(); 130 | } 131 | 132 | return a; 133 | } 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/CameraPositionTranslation.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class CameraPositionTranslation { 8 | public int interpolationType; 9 | public int globalSequenceId; 10 | public TranslationTrack[] translationTrack = new TranslationTrack[0]; 11 | 12 | public static final String key = "KCTR"; 13 | 14 | public void load(BlizzardDataInputStream in) throws IOException { 15 | StreamUtils.checkId(in, "KCTR"); 16 | int nrOfTracks = in.readInt(); 17 | interpolationType = in.readInt(); 18 | globalSequenceId = in.readInt(); 19 | translationTrack = new TranslationTrack[nrOfTracks]; 20 | for (int i = 0; i < nrOfTracks; i++) { 21 | translationTrack[i] = new TranslationTrack(); 22 | translationTrack[i].load(in); 23 | } 24 | } 25 | 26 | public void save(BlizzardDataOutputStream out) throws IOException { 27 | int nrOfTracks = translationTrack.length; 28 | out.writeNByteString("KCTR", 4); 29 | out.writeInt(nrOfTracks); 30 | out.writeInt(interpolationType); 31 | out.writeInt(globalSequenceId); 32 | for (int i = 0; i < translationTrack.length; i++) { 33 | translationTrack[i].save(out); 34 | } 35 | 36 | } 37 | 38 | public int getSize() { 39 | int a = 0; 40 | a += 4; 41 | a += 4; 42 | a += 4; 43 | a += 4; 44 | for (int i = 0; i < translationTrack.length; i++) { 45 | a += translationTrack[i].getSize(); 46 | } 47 | 48 | return a; 49 | } 50 | 51 | public class TranslationTrack { 52 | public int time; 53 | public float[] translation = new float[3]; 54 | public float[] inTan = new float[3]; 55 | public float[] outTan = new float[3]; 56 | 57 | public void load(BlizzardDataInputStream in) throws IOException { 58 | time = in.readInt(); 59 | translation = StreamUtils.loadFloatArray(in, 3); 60 | if (interpolationType > 1) { 61 | inTan = StreamUtils.loadFloatArray(in, 3); 62 | outTan = StreamUtils.loadFloatArray(in, 3); 63 | } 64 | } 65 | 66 | public void save(BlizzardDataOutputStream out) throws IOException { 67 | out.writeInt(time); 68 | if (translation.length % 3 != 0) { 69 | throw new IllegalArgumentException( 70 | "The array translation needs either the length 3 or a multiple of this number. (got " 71 | + translation.length + ")"); 72 | } 73 | StreamUtils.saveFloatArray(out, translation); 74 | if (interpolationType > 1) { 75 | if (inTan.length % 3 != 0) { 76 | throw new IllegalArgumentException( 77 | "The array inTan needs either the length 3 or a multiple of this number. (got " 78 | + inTan.length + ")"); 79 | } 80 | StreamUtils.saveFloatArray(out, inTan); 81 | if (outTan.length % 3 != 0) { 82 | throw new IllegalArgumentException( 83 | "The array outTan needs either the length 3 or a multiple of this number. (got " 84 | + outTan.length + ")"); 85 | } 86 | StreamUtils.saveFloatArray(out, outTan); 87 | } 88 | 89 | } 90 | 91 | public int getSize() { 92 | int a = 0; 93 | a += 4; 94 | a += 12; 95 | if (interpolationType > 1) { 96 | a += 12; 97 | a += 12; 98 | } 99 | 100 | return a; 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/CameraRotation.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class CameraRotation { 8 | public int interpolationType; 9 | public int globalSequenceId; 10 | public TranslationTrack[] translationTrack = new TranslationTrack[0]; 11 | 12 | public static final String key = "KCRL"; 13 | 14 | public void load(BlizzardDataInputStream in) throws IOException { 15 | StreamUtils.checkId(in, "KCRL"); 16 | int nrOfTracks = in.readInt(); 17 | interpolationType = in.readInt(); 18 | globalSequenceId = in.readInt(); 19 | translationTrack = new TranslationTrack[nrOfTracks]; 20 | for (int i = 0; i < nrOfTracks; i++) { 21 | translationTrack[i] = new TranslationTrack(); 22 | translationTrack[i].load(in); 23 | } 24 | } 25 | 26 | public void save(BlizzardDataOutputStream out) throws IOException { 27 | int nrOfTracks = translationTrack.length; 28 | out.writeNByteString("KCRL", 4); 29 | out.writeInt(nrOfTracks); 30 | out.writeInt(interpolationType); 31 | out.writeInt(globalSequenceId); 32 | for (int i = 0; i < translationTrack.length; i++) { 33 | translationTrack[i].save(out); 34 | } 35 | 36 | } 37 | 38 | public int getSize() { 39 | int a = 0; 40 | a += 4; 41 | a += 4; 42 | a += 4; 43 | a += 4; 44 | for (int i = 0; i < translationTrack.length; i++) { 45 | a += translationTrack[i].getSize(); 46 | } 47 | 48 | return a; 49 | } 50 | 51 | public class TranslationTrack { 52 | public int time; 53 | public float rotation; 54 | public float inTan; 55 | public float outTan; 56 | 57 | public void load(BlizzardDataInputStream in) throws IOException { 58 | time = in.readInt(); 59 | rotation = in.readFloat(); 60 | if (interpolationType > 1) { 61 | inTan = in.readFloat(); 62 | outTan = in.readFloat(); 63 | } 64 | } 65 | 66 | public void save(BlizzardDataOutputStream out) throws IOException { 67 | out.writeInt(time); 68 | out.writeFloat(rotation); 69 | if (interpolationType > 1) { 70 | out.writeFloat(inTan); 71 | out.writeFloat(outTan); 72 | } 73 | 74 | } 75 | 76 | public int getSize() { 77 | int a = 0; 78 | a += 4; 79 | a += 4; 80 | if (interpolationType > 1) { 81 | a += 4; 82 | a += 4; 83 | } 84 | 85 | return a; 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/CameraTargetTranslation.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class CameraTargetTranslation { 8 | public int interpolationType; 9 | public int globalSequenceId; 10 | public TranslationTrack[] translationTrack = new TranslationTrack[0]; 11 | 12 | public static final String key = "KTTR"; 13 | 14 | public void load(BlizzardDataInputStream in) throws IOException { 15 | StreamUtils.checkId(in, "KTTR"); 16 | int nrOfTracks = in.readInt(); 17 | interpolationType = in.readInt(); 18 | globalSequenceId = in.readInt(); 19 | translationTrack = new TranslationTrack[nrOfTracks]; 20 | for (int i = 0; i < nrOfTracks; i++) { 21 | translationTrack[i] = new TranslationTrack(); 22 | translationTrack[i].load(in); 23 | } 24 | } 25 | 26 | public void save(BlizzardDataOutputStream out) throws IOException { 27 | int nrOfTracks = translationTrack.length; 28 | out.writeNByteString("KTTR", 4); 29 | out.writeInt(nrOfTracks); 30 | out.writeInt(interpolationType); 31 | out.writeInt(globalSequenceId); 32 | for (int i = 0; i < translationTrack.length; i++) { 33 | translationTrack[i].save(out); 34 | } 35 | 36 | } 37 | 38 | public int getSize() { 39 | int a = 0; 40 | a += 4; 41 | a += 4; 42 | a += 4; 43 | a += 4; 44 | for (int i = 0; i < translationTrack.length; i++) { 45 | a += translationTrack[i].getSize(); 46 | } 47 | 48 | return a; 49 | } 50 | 51 | public class TranslationTrack { 52 | public int time; 53 | public float[] translation = new float[3]; 54 | public float[] inTan = new float[3]; 55 | public float[] outTan = new float[3]; 56 | 57 | public void load(BlizzardDataInputStream in) throws IOException { 58 | time = in.readInt(); 59 | translation = StreamUtils.loadFloatArray(in, 3); 60 | if (interpolationType > 1) { 61 | inTan = StreamUtils.loadFloatArray(in, 3); 62 | outTan = StreamUtils.loadFloatArray(in, 3); 63 | } 64 | } 65 | 66 | public void save(BlizzardDataOutputStream out) throws IOException { 67 | out.writeInt(time); 68 | if (translation.length % 3 != 0) { 69 | throw new IllegalArgumentException( 70 | "The array translation needs either the length 3 or a multiple of this number. (got " 71 | + translation.length + ")"); 72 | } 73 | StreamUtils.saveFloatArray(out, translation); 74 | if (interpolationType > 1) { 75 | if (inTan.length % 3 != 0) { 76 | throw new IllegalArgumentException( 77 | "The array inTan needs either the length 3 or a multiple of this number. (got " 78 | + inTan.length + ")"); 79 | } 80 | StreamUtils.saveFloatArray(out, inTan); 81 | if (outTan.length % 3 != 0) { 82 | throw new IllegalArgumentException( 83 | "The array outTan needs either the length 3 or a multiple of this number. (got " 84 | + outTan.length + ")"); 85 | } 86 | StreamUtils.saveFloatArray(out, outTan); 87 | } 88 | 89 | } 90 | 91 | public int getSize() { 92 | int a = 0; 93 | a += 4; 94 | a += 12; 95 | if (interpolationType > 1) { 96 | a += 12; 97 | a += 12; 98 | } 99 | 100 | return a; 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/CollisionShapeChunk.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class CollisionShapeChunk { 8 | public CollisionShape[] collisionShape = new CollisionShape[0]; 9 | 10 | public static final String key = "CLID"; 11 | 12 | public void load(BlizzardDataInputStream in) throws IOException { 13 | StreamUtils.checkId(in, "CLID"); 14 | int chunkSize = in.readInt(); 15 | List collisionShapeList = new ArrayList(); 16 | int collisionShapeCounter = chunkSize; 17 | while (collisionShapeCounter > 0) { 18 | CollisionShape tempcollisionShape = new CollisionShape(); 19 | collisionShapeList.add(tempcollisionShape); 20 | tempcollisionShape.load(in); 21 | collisionShapeCounter -= tempcollisionShape.getSize(); 22 | } 23 | collisionShape = collisionShapeList 24 | .toArray(new CollisionShape[collisionShapeList.size()]); 25 | } 26 | 27 | public void save(BlizzardDataOutputStream out) throws IOException { 28 | int nrOfCollisionShapes = collisionShape.length; 29 | out.writeNByteString("CLID", 4); 30 | out.writeInt(getSize() - 8);// ChunkSize 31 | for (int i = 0; i < collisionShape.length; i++) { 32 | collisionShape[i].save(out); 33 | } 34 | 35 | } 36 | 37 | public int getSize() { 38 | int a = 0; 39 | a += 4; 40 | a += 4; 41 | for (int i = 0; i < collisionShape.length; i++) { 42 | a += collisionShape[i].getSize(); 43 | } 44 | 45 | return a; 46 | } 47 | 48 | public class CollisionShape { 49 | public Node node = new Node(); 50 | public int type; 51 | public float[] vertexs = new float[0]; 52 | public float boundsRadius; 53 | 54 | public void load(BlizzardDataInputStream in) throws IOException { 55 | node = new Node(); 56 | node.load(in); 57 | type = in.readInt(); 58 | vertexs = StreamUtils.loadFloatArray(in, (2 - type / 2) * 3); 59 | if (type == 2) { 60 | boundsRadius = in.readFloat(); 61 | } 62 | } 63 | 64 | public void save(BlizzardDataOutputStream out) throws IOException { 65 | int nrOfVertices = vertexs.length / 3; 66 | node.save(out); 67 | out.writeInt(type); 68 | if (vertexs.length % 3 != 0) { 69 | throw new IllegalArgumentException( 70 | "The array vertexs needs either the length 3 or a multiple of this number. (got " 71 | + vertexs.length + ")"); 72 | } 73 | StreamUtils.saveFloatArray(out, vertexs); 74 | if (type == 2) { 75 | out.writeFloat(boundsRadius); 76 | } 77 | 78 | } 79 | 80 | public int getSize() { 81 | int a = 0; 82 | a += node.getSize(); 83 | a += 4; 84 | a += (2 - type / 2) * 12; 85 | if (type == 2) { 86 | a += 4; 87 | } 88 | 89 | return a; 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/EventObjectChunk.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class EventObjectChunk { 8 | public EventObject[] eventObject = new EventObject[0]; 9 | 10 | public static final String key = "EVTS"; 11 | 12 | public void load(BlizzardDataInputStream in) throws IOException { 13 | StreamUtils.checkId(in, "EVTS"); 14 | int chunkSize = in.readInt(); 15 | List eventObjectList = new ArrayList(); 16 | int eventObjectCounter = chunkSize; 17 | while (eventObjectCounter > 0) { 18 | EventObject tempeventObject = new EventObject(); 19 | eventObjectList.add(tempeventObject); 20 | tempeventObject.load(in); 21 | eventObjectCounter -= tempeventObject.getSize(); 22 | } 23 | eventObject = eventObjectList.toArray(new EventObject[eventObjectList 24 | .size()]); 25 | } 26 | 27 | public void save(BlizzardDataOutputStream out) throws IOException { 28 | int nrOfEventObjects = eventObject.length; 29 | out.writeNByteString("EVTS", 4); 30 | out.writeInt(getSize() - 8);// ChunkSize 31 | for (int i = 0; i < eventObject.length; i++) { 32 | eventObject[i].save(out); 33 | } 34 | 35 | } 36 | 37 | public int getSize() { 38 | int a = 0; 39 | a += 4; 40 | a += 4; 41 | for (int i = 0; i < eventObject.length; i++) { 42 | a += eventObject[i].getSize(); 43 | } 44 | 45 | return a; 46 | } 47 | 48 | public class EventObject { 49 | public Node node = new Node(); 50 | public Tracks tracks; 51 | 52 | public void load(BlizzardDataInputStream in) throws IOException { 53 | node = new Node(); 54 | node.load(in); 55 | if (StreamUtils.checkOptionalId(in, tracks.key)) { 56 | tracks = new Tracks(); 57 | tracks.load(in); 58 | } 59 | 60 | } 61 | 62 | public void save(BlizzardDataOutputStream out) throws IOException { 63 | node.save(out); 64 | if (tracks != null) { 65 | tracks.save(out); 66 | } 67 | 68 | } 69 | 70 | public int getSize() { 71 | int a = 0; 72 | a += node.getSize(); 73 | if (tracks != null) { 74 | a += tracks.getSize(); 75 | } 76 | 77 | return a; 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/GeosetAlpha.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class GeosetAlpha { 8 | public int interpolationType; 9 | public int globalSequenceId; 10 | public ScalingTrack[] scalingTrack = new ScalingTrack[0]; 11 | 12 | public static final String key = "KGAO"; 13 | 14 | public void load(BlizzardDataInputStream in) throws IOException { 15 | StreamUtils.checkId(in, "KGAO"); 16 | int nrOfTracks = in.readInt(); 17 | interpolationType = in.readInt(); 18 | globalSequenceId = in.readInt(); 19 | scalingTrack = new ScalingTrack[nrOfTracks]; 20 | for (int i = 0; i < nrOfTracks; i++) { 21 | scalingTrack[i] = new ScalingTrack(); 22 | scalingTrack[i].load(in); 23 | } 24 | } 25 | 26 | public void save(BlizzardDataOutputStream out) throws IOException { 27 | int nrOfTracks = scalingTrack.length; 28 | out.writeNByteString("KGAO", 4); 29 | out.writeInt(nrOfTracks); 30 | out.writeInt(interpolationType); 31 | out.writeInt(globalSequenceId); 32 | for (int i = 0; i < scalingTrack.length; i++) { 33 | scalingTrack[i].save(out); 34 | } 35 | 36 | } 37 | 38 | public int getSize() { 39 | int a = 0; 40 | a += 4; 41 | a += 4; 42 | a += 4; 43 | a += 4; 44 | for (int i = 0; i < scalingTrack.length; i++) { 45 | a += scalingTrack[i].getSize(); 46 | } 47 | 48 | return a; 49 | } 50 | 51 | public class ScalingTrack { 52 | public int time; 53 | public float alpha; 54 | public float inTan; 55 | public float outTan; 56 | 57 | public void load(BlizzardDataInputStream in) throws IOException { 58 | time = in.readInt(); 59 | alpha = in.readFloat(); 60 | if (interpolationType > 1) { 61 | inTan = in.readFloat(); 62 | outTan = in.readFloat(); 63 | } 64 | } 65 | 66 | public void save(BlizzardDataOutputStream out) throws IOException { 67 | out.writeInt(time); 68 | out.writeFloat(alpha); 69 | if (interpolationType > 1) { 70 | out.writeFloat(inTan); 71 | out.writeFloat(outTan); 72 | } 73 | 74 | } 75 | 76 | public int getSize() { 77 | int a = 0; 78 | a += 4; 79 | a += 4; 80 | if (interpolationType > 1) { 81 | a += 4; 82 | a += 4; 83 | } 84 | 85 | return a; 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/GeosetAnimationChunk.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class GeosetAnimationChunk { 8 | public GeosetAnimation[] geosetAnimation = new GeosetAnimation[0]; 9 | 10 | public static final String key = "GEOA"; 11 | 12 | public void load(BlizzardDataInputStream in) throws IOException { 13 | StreamUtils.checkId(in, "GEOA"); 14 | int chunkSize = in.readInt(); 15 | List geosetAnimationList = new ArrayList(); 16 | int geosetAnimationCounter = chunkSize; 17 | while (geosetAnimationCounter > 0) { 18 | GeosetAnimation tempgeosetAnimation = new GeosetAnimation(); 19 | geosetAnimationList.add(tempgeosetAnimation); 20 | tempgeosetAnimation.load(in); 21 | geosetAnimationCounter -= tempgeosetAnimation.getSize(); 22 | } 23 | geosetAnimation = geosetAnimationList 24 | .toArray(new GeosetAnimation[geosetAnimationList.size()]); 25 | } 26 | 27 | public void save(BlizzardDataOutputStream out) throws IOException { 28 | int nrOfGeosetAnimations = geosetAnimation.length; 29 | out.writeNByteString("GEOA", 4); 30 | out.writeInt(getSize() - 8);// ChunkSize 31 | for (int i = 0; i < geosetAnimation.length; i++) { 32 | geosetAnimation[i].save(out); 33 | } 34 | 35 | } 36 | 37 | public int getSize() { 38 | int a = 0; 39 | a += 4; 40 | a += 4; 41 | for (int i = 0; i < geosetAnimation.length; i++) { 42 | a += geosetAnimation[i].getSize(); 43 | } 44 | 45 | return a; 46 | } 47 | 48 | public class GeosetAnimation { 49 | public float alpha; 50 | public int flags; 51 | public float[] color = new float[3]; 52 | public int geosetId; 53 | public GeosetAlpha geosetAlpha; 54 | public GeosetColor geosetColor; 55 | 56 | public void load(BlizzardDataInputStream in) throws IOException { 57 | int inclusiveSize = in.readInt(); 58 | alpha = in.readFloat(); 59 | flags = in.readInt(); 60 | color = StreamUtils.loadFloatArray(in, 3); 61 | geosetId = in.readInt(); 62 | for (int i = 0; i < 2; i++) { 63 | if (StreamUtils.checkOptionalId(in, geosetAlpha.key)) { 64 | geosetAlpha = new GeosetAlpha(); 65 | geosetAlpha.load(in); 66 | } else if (StreamUtils.checkOptionalId(in, geosetColor.key)) { 67 | geosetColor = new GeosetColor(); 68 | geosetColor.load(in); 69 | } 70 | 71 | } 72 | } 73 | 74 | public void save(BlizzardDataOutputStream out) throws IOException { 75 | out.writeInt(getSize());// InclusiveSize 76 | out.writeFloat(alpha); 77 | out.writeInt(flags); 78 | if (color.length % 3 != 0) { 79 | throw new IllegalArgumentException( 80 | "The array color needs either the length 3 or a multiple of this number. (got " 81 | + color.length + ")"); 82 | } 83 | StreamUtils.saveFloatArray(out, color); 84 | out.writeInt(geosetId); 85 | if (geosetAlpha != null) { 86 | geosetAlpha.save(out); 87 | } 88 | if (geosetColor != null) { 89 | geosetColor.save(out); 90 | } 91 | 92 | } 93 | 94 | public int getSize() { 95 | int a = 0; 96 | a += 4; 97 | a += 4; 98 | a += 4; 99 | a += 12; 100 | a += 4; 101 | if (geosetAlpha != null) { 102 | a += geosetAlpha.getSize(); 103 | } 104 | if (geosetColor != null) { 105 | a += geosetColor.getSize(); 106 | } 107 | 108 | return a; 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/GeosetChunk.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class GeosetChunk { 8 | public Geoset[] geoset = new Geoset[0]; 9 | 10 | public static final String key = "GEOS"; 11 | 12 | public void load(BlizzardDataInputStream in) throws IOException { 13 | StreamUtils.checkId(in, "GEOS"); 14 | int chunkSize = in.readInt(); 15 | List geosetList = new ArrayList(); 16 | int geosetCounter = chunkSize; 17 | while (geosetCounter > 0) { 18 | Geoset tempgeoset = new Geoset(); 19 | geosetList.add(tempgeoset); 20 | tempgeoset.load(in); 21 | geosetCounter -= tempgeoset.getSize(); 22 | } 23 | geoset = geosetList.toArray(new Geoset[geosetList.size()]); 24 | } 25 | 26 | public void save(BlizzardDataOutputStream out) throws IOException { 27 | int nrOfGeosets = geoset.length; 28 | out.writeNByteString("GEOS", 4); 29 | out.writeInt(getSize() - 8);// ChunkSize 30 | for (int i = 0; i < geoset.length; i++) { 31 | geoset[i].save(out); 32 | } 33 | 34 | } 35 | 36 | public int getSize() { 37 | int a = 0; 38 | a += 4; 39 | a += 4; 40 | for (int i = 0; i < geoset.length; i++) { 41 | a += geoset[i].getSize(); 42 | } 43 | 44 | return a; 45 | } 46 | 47 | public class Geoset { 48 | public float[] vertexPositions = new float[0]; 49 | public float[] vertexNormals = new float[0]; 50 | public int[] faceTypeGroups = new int[0]; 51 | public int[] faceGroups = new int[0]; 52 | public short[] faces = new short[0]; 53 | public byte[] vertexGroups = new byte[0]; 54 | public int[] matrixGroups = new int[0]; 55 | public int[] matrixIndexs = new int[0]; 56 | public int materialId; 57 | public int selectionGroup; 58 | public int selectionType; 59 | public float boundsRadius; 60 | public float[] minimumExtent = new float[3]; 61 | public float[] maximumExtent = new float[3]; 62 | public Extent[] extent = new Extent[0]; 63 | public int nrOfTextureVertexGroups; 64 | public float[] vertexTexturePositions = new float[0]; 65 | 66 | public float[] vertexTexturePositions2 = null; 67 | 68 | public static final String key = "VRTX"; 69 | 70 | public void load(BlizzardDataInputStream in) throws IOException { 71 | int inclusiveSize = in.readInt(); 72 | StreamUtils.checkId(in, "VRTX"); 73 | int nrOfVertexPositions = in.readInt(); 74 | vertexPositions = StreamUtils.loadFloatArray(in, 75 | nrOfVertexPositions * 3); 76 | StreamUtils.checkId(in, "NRMS"); 77 | int nrOfVertexNormals = in.readInt(); 78 | vertexNormals = StreamUtils.loadFloatArray(in, nrOfVertexNormals * 3); 79 | StreamUtils.checkId(in, "PTYP"); 80 | int nrOfFaceTypeGroups = in.readInt(); 81 | faceTypeGroups = StreamUtils.loadIntArray(in, nrOfFaceTypeGroups); 82 | StreamUtils.checkId(in, "PCNT"); 83 | int nrOfFaceGroups = in.readInt(); 84 | faceGroups = StreamUtils.loadIntArray(in, nrOfFaceGroups); 85 | StreamUtils.checkId(in, "PVTX"); 86 | int nrOfIndexes = in.readInt(); 87 | faces = StreamUtils.loadShortArray(in, nrOfIndexes); 88 | StreamUtils.checkId(in, "GNDX"); 89 | int nrOfVertexGroups = in.readInt(); 90 | vertexGroups = StreamUtils.loadByteArray(in, nrOfVertexGroups); 91 | StreamUtils.checkId(in, "MTGC"); 92 | int nrOfMatrixGroups = in.readInt(); 93 | matrixGroups = StreamUtils.loadIntArray(in, nrOfMatrixGroups); 94 | StreamUtils.checkId(in, "MATS"); 95 | int nrOfMatrixIndexes = in.readInt(); 96 | matrixIndexs = StreamUtils.loadIntArray(in, nrOfMatrixIndexes); 97 | materialId = in.readInt(); 98 | selectionGroup = in.readInt(); 99 | selectionType = in.readInt(); 100 | boundsRadius = in.readFloat(); 101 | minimumExtent = StreamUtils.loadFloatArray(in, 3); 102 | maximumExtent = StreamUtils.loadFloatArray(in, 3); 103 | int nrOfExtents = in.readInt(); 104 | extent = new Extent[nrOfExtents]; 105 | for (int i = 0; i < nrOfExtents; i++) { 106 | extent[i] = new Extent(); 107 | extent[i].load(in); 108 | } 109 | StreamUtils.checkId(in, "UVAS"); 110 | nrOfTextureVertexGroups = in.readInt(); 111 | StreamUtils.checkId(in, "UVBS"); 112 | int nrOfVertexTexturePositions = in.readInt(); 113 | vertexTexturePositions = StreamUtils.loadFloatArray(in, 114 | nrOfVertexTexturePositions * 2); 115 | 116 | if(StreamUtils.checkOptionalId(in, "UVBS")){ 117 | StreamUtils.checkId(in, "UVBS"); 118 | int nrOfVertexTexturePositions2 = in.readInt(); 119 | vertexTexturePositions2 = StreamUtils.loadFloatArray(in, 120 | nrOfVertexTexturePositions2 * 2); 121 | } 122 | } 123 | 124 | public void save(BlizzardDataOutputStream out) throws IOException { 125 | int nrOfVertexTexturePositions = vertexTexturePositions.length / 2; 126 | int nrOfExtents = extent.length; 127 | int nrOfMatrixIndexes = matrixIndexs.length; 128 | int nrOfMatrixGroups = matrixGroups.length; 129 | int nrOfVertexGroups = vertexGroups.length; 130 | int nrOfIndexes = faces.length; 131 | int nrOfFaceGroups = faceGroups.length; 132 | int nrOfFaceTypeGroups = faceTypeGroups.length; 133 | int nrOfVertexNormals = vertexNormals.length / 3; 134 | int nrOfVertexPositions = vertexPositions.length / 3; 135 | out.writeInt(getSize());// InclusiveSize 136 | out.writeNByteString("VRTX", 4); 137 | out.writeInt(nrOfVertexPositions); 138 | if (vertexPositions.length % 3 != 0) { 139 | throw new IllegalArgumentException( 140 | "The array vertexPositions needs either the length 3 or a multiple of this number. (got " 141 | + vertexPositions.length + ")"); 142 | } 143 | StreamUtils.saveFloatArray(out, vertexPositions); 144 | out.writeNByteString("NRMS", 4); 145 | out.writeInt(nrOfVertexNormals); 146 | if (vertexNormals.length % 3 != 0) { 147 | throw new IllegalArgumentException( 148 | "The array vertexNormals needs either the length 3 or a multiple of this number. (got " 149 | + vertexNormals.length + ")"); 150 | } 151 | StreamUtils.saveFloatArray(out, vertexNormals); 152 | out.writeNByteString("PTYP", 4); 153 | out.writeInt(nrOfFaceTypeGroups); 154 | StreamUtils.saveIntArray(out, faceTypeGroups); 155 | out.writeNByteString("PCNT", 4); 156 | out.writeInt(nrOfFaceGroups); 157 | StreamUtils.saveIntArray(out, faceGroups); 158 | out.writeNByteString("PVTX", 4); 159 | out.writeInt(nrOfIndexes); 160 | StreamUtils.saveShortArray(out, faces); 161 | out.writeNByteString("GNDX", 4); 162 | out.writeInt(nrOfVertexGroups); 163 | StreamUtils.saveByteArray(out, vertexGroups); 164 | out.writeNByteString("MTGC", 4); 165 | out.writeInt(nrOfMatrixGroups); 166 | StreamUtils.saveIntArray(out, matrixGroups); 167 | out.writeNByteString("MATS", 4); 168 | out.writeInt(nrOfMatrixIndexes); 169 | StreamUtils.saveIntArray(out, matrixIndexs); 170 | out.writeInt(materialId); 171 | out.writeInt(selectionGroup); 172 | out.writeInt(selectionType); 173 | out.writeFloat(boundsRadius); 174 | if (minimumExtent.length % 3 != 0) { 175 | throw new IllegalArgumentException( 176 | "The array minimumExtent needs either the length 3 or a multiple of this number. (got " 177 | + minimumExtent.length + ")"); 178 | } 179 | StreamUtils.saveFloatArray(out, minimumExtent); 180 | if (maximumExtent.length % 3 != 0) { 181 | throw new IllegalArgumentException( 182 | "The array maximumExtent needs either the length 3 or a multiple of this number. (got " 183 | + maximumExtent.length + ")"); 184 | } 185 | StreamUtils.saveFloatArray(out, maximumExtent); 186 | out.writeInt(nrOfExtents); 187 | for (int i = 0; i < extent.length; i++) { 188 | extent[i].save(out); 189 | } 190 | out.writeNByteString("UVAS", 4); 191 | out.writeInt(nrOfTextureVertexGroups); 192 | out.writeNByteString("UVBS", 4); 193 | out.writeInt(nrOfVertexTexturePositions); 194 | if (vertexTexturePositions.length % 2 != 0) { 195 | throw new IllegalArgumentException( 196 | "The array vertexTexturePositions needs either the length 2 or a multiple of this number. (got " 197 | + vertexTexturePositions.length + ")"); 198 | } 199 | StreamUtils.saveFloatArray(out, vertexTexturePositions); 200 | 201 | if(vertexTexturePositions2 != null){ 202 | out.writeNByteString("UVBS", 4); 203 | out.writeInt(vertexTexturePositions2.length); 204 | StreamUtils.saveFloatArray(out, vertexTexturePositions); 205 | } 206 | 207 | } 208 | 209 | public int getSize() { 210 | int a = 0; 211 | a += 4; 212 | a += 4; 213 | a += 4; 214 | a += 4 * vertexPositions.length; 215 | a += 4; 216 | a += 4; 217 | a += 4 * vertexNormals.length; 218 | a += 4; 219 | a += 4; 220 | a += 4 * faceTypeGroups.length; 221 | a += 4; 222 | a += 4; 223 | a += 4 * faceGroups.length; 224 | a += 4; 225 | a += 4; 226 | a += 2 * faces.length; 227 | a += 4; 228 | a += 4; 229 | a += 1 * vertexGroups.length; 230 | a += 4; 231 | a += 4; 232 | a += 4 * matrixGroups.length; 233 | a += 4; 234 | a += 4; 235 | a += 4 * matrixIndexs.length; 236 | a += 4; 237 | a += 4; 238 | a += 4; 239 | a += 4; 240 | a += 12; 241 | a += 12; 242 | a += 4; 243 | for (int i = 0; i < extent.length; i++) { 244 | a += extent[i].getSize(); 245 | } 246 | a += 4; 247 | a += 4; 248 | a += 4; 249 | a += 4; 250 | a += 4 * vertexTexturePositions.length; 251 | 252 | if(vertexTexturePositions2 != null){ 253 | a += 4; 254 | a += 4; 255 | a += 4 * vertexTexturePositions2.length; 256 | } 257 | 258 | return a; 259 | } 260 | 261 | public class Extent { 262 | public float[] minimumExtent = new float[3]; 263 | public float[] maximumExtent = new float[3]; 264 | public float bounds; 265 | 266 | public void load(BlizzardDataInputStream in) throws IOException { 267 | minimumExtent = StreamUtils.loadFloatArray(in, 3); 268 | maximumExtent = StreamUtils.loadFloatArray(in, 3); 269 | bounds = in.readFloat(); 270 | } 271 | 272 | public void save(BlizzardDataOutputStream out) throws IOException { 273 | if (minimumExtent.length % 3 != 0) { 274 | throw new IllegalArgumentException( 275 | "The array minimumExtent needs either the length 3 or a multiple of this number. (got " 276 | + minimumExtent.length + ")"); 277 | } 278 | StreamUtils.saveFloatArray(out, minimumExtent); 279 | if (maximumExtent.length % 3 != 0) { 280 | throw new IllegalArgumentException( 281 | "The array maximumExtent needs either the length 3 or a multiple of this number. (got " 282 | + maximumExtent.length + ")"); 283 | } 284 | StreamUtils.saveFloatArray(out, maximumExtent); 285 | out.writeFloat(bounds); 286 | 287 | } 288 | 289 | public int getSize() { 290 | int a = 0; 291 | a += 12; 292 | a += 12; 293 | a += 4; 294 | 295 | return a; 296 | } 297 | } 298 | } 299 | } 300 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/GeosetColor.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class GeosetColor { 8 | public int interpolationType; 9 | public int globalSequenceId; 10 | public ScalingTrack[] scalingTrack = new ScalingTrack[0]; 11 | 12 | public static final String key = "KGAC"; 13 | 14 | public void load(BlizzardDataInputStream in) throws IOException { 15 | StreamUtils.checkId(in, "KGAC"); 16 | int nrOfTracks = in.readInt(); 17 | interpolationType = in.readInt(); 18 | globalSequenceId = in.readInt(); 19 | scalingTrack = new ScalingTrack[nrOfTracks]; 20 | for (int i = 0; i < nrOfTracks; i++) { 21 | scalingTrack[i] = new ScalingTrack(); 22 | scalingTrack[i].load(in); 23 | } 24 | } 25 | 26 | public void save(BlizzardDataOutputStream out) throws IOException { 27 | int nrOfTracks = scalingTrack.length; 28 | out.writeNByteString("KGAC", 4); 29 | out.writeInt(nrOfTracks); 30 | out.writeInt(interpolationType); 31 | out.writeInt(globalSequenceId); 32 | for (int i = 0; i < scalingTrack.length; i++) { 33 | scalingTrack[i].save(out); 34 | } 35 | 36 | } 37 | 38 | public int getSize() { 39 | int a = 0; 40 | a += 4; 41 | a += 4; 42 | a += 4; 43 | a += 4; 44 | for (int i = 0; i < scalingTrack.length; i++) { 45 | a += scalingTrack[i].getSize(); 46 | } 47 | 48 | return a; 49 | } 50 | 51 | public class ScalingTrack { 52 | public int time; 53 | public float[] color = new float[3]; 54 | public float[] inTan = new float[3]; 55 | public float[] outTan = new float[3]; 56 | 57 | public void load(BlizzardDataInputStream in) throws IOException { 58 | time = in.readInt(); 59 | color = StreamUtils.loadFloatArray(in, 3); 60 | if (interpolationType > 1) { 61 | inTan = StreamUtils.loadFloatArray(in, 3); 62 | outTan = StreamUtils.loadFloatArray(in, 3); 63 | } 64 | } 65 | 66 | public void save(BlizzardDataOutputStream out) throws IOException { 67 | out.writeInt(time); 68 | if (color.length % 3 != 0) { 69 | throw new IllegalArgumentException( 70 | "The array color needs either the length 3 or a multiple of this number. (got " 71 | + color.length + ")"); 72 | } 73 | StreamUtils.saveFloatArray(out, color); 74 | if (interpolationType > 1) { 75 | if (inTan.length % 3 != 0) { 76 | throw new IllegalArgumentException( 77 | "The array inTan needs either the length 3 or a multiple of this number. (got " 78 | + inTan.length + ")"); 79 | } 80 | StreamUtils.saveFloatArray(out, inTan); 81 | if (outTan.length % 3 != 0) { 82 | throw new IllegalArgumentException( 83 | "The array outTan needs either the length 3 or a multiple of this number. (got " 84 | + outTan.length + ")"); 85 | } 86 | StreamUtils.saveFloatArray(out, outTan); 87 | } 88 | 89 | } 90 | 91 | public int getSize() { 92 | int a = 0; 93 | a += 4; 94 | a += 12; 95 | if (interpolationType > 1) { 96 | a += 12; 97 | a += 12; 98 | } 99 | 100 | return a; 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/GeosetRotation.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class GeosetRotation { 8 | public int interpolationType; 9 | public int globalSequenceId; 10 | public RotationTrack[] rotationTrack = new RotationTrack[0]; 11 | 12 | public static final String key = "KGRT"; 13 | 14 | public void load(BlizzardDataInputStream in) throws IOException { 15 | StreamUtils.checkId(in, "KGRT"); 16 | int nrOfTracks = in.readInt(); 17 | interpolationType = in.readInt(); 18 | globalSequenceId = in.readInt(); 19 | rotationTrack = new RotationTrack[nrOfTracks]; 20 | for (int i = 0; i < nrOfTracks; i++) { 21 | rotationTrack[i] = new RotationTrack(); 22 | rotationTrack[i].load(in); 23 | } 24 | } 25 | 26 | public void save(BlizzardDataOutputStream out) throws IOException { 27 | int nrOfTracks = rotationTrack.length; 28 | out.writeNByteString("KGRT", 4); 29 | out.writeInt(nrOfTracks); 30 | out.writeInt(interpolationType); 31 | out.writeInt(globalSequenceId); 32 | for (int i = 0; i < rotationTrack.length; i++) { 33 | rotationTrack[i].save(out); 34 | } 35 | 36 | } 37 | 38 | public int getSize() { 39 | int a = 0; 40 | a += 4; 41 | a += 4; 42 | a += 4; 43 | a += 4; 44 | for (int i = 0; i < rotationTrack.length; i++) { 45 | a += rotationTrack[i].getSize(); 46 | } 47 | 48 | return a; 49 | } 50 | 51 | public class RotationTrack { 52 | public int time; 53 | public float[] rotation = new float[4]; 54 | public float[] inTan = new float[4]; 55 | public float[] outTan = new float[4]; 56 | 57 | public void load(BlizzardDataInputStream in) throws IOException { 58 | time = in.readInt(); 59 | rotation = StreamUtils.loadFloatArray(in, 4); 60 | if (interpolationType > 1) { 61 | inTan = StreamUtils.loadFloatArray(in, 4); 62 | outTan = StreamUtils.loadFloatArray(in, 4); 63 | } 64 | } 65 | 66 | public void save(BlizzardDataOutputStream out) throws IOException { 67 | out.writeInt(time); 68 | if (rotation.length % 4 != 0) { 69 | throw new IllegalArgumentException( 70 | "The array rotation needs either the length 4 or a multiple of this number. (got " 71 | + rotation.length + ")"); 72 | } 73 | StreamUtils.saveFloatArray(out, rotation); 74 | if (interpolationType > 1) { 75 | if (inTan.length % 4 != 0) { 76 | throw new IllegalArgumentException( 77 | "The array inTan needs either the length 4 or a multiple of this number. (got " 78 | + inTan.length + ")"); 79 | } 80 | StreamUtils.saveFloatArray(out, inTan); 81 | if (outTan.length % 4 != 0) { 82 | throw new IllegalArgumentException( 83 | "The array outTan needs either the length 4 or a multiple of this number. (got " 84 | + outTan.length + ")"); 85 | } 86 | StreamUtils.saveFloatArray(out, outTan); 87 | } 88 | 89 | } 90 | 91 | public int getSize() { 92 | int a = 0; 93 | a += 4; 94 | a += 16; 95 | if (interpolationType > 1) { 96 | a += 16; 97 | a += 16; 98 | } 99 | 100 | return a; 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/GeosetScaling.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class GeosetScaling { 8 | public int interpolationType; 9 | public int globalSequenceId; 10 | public ScalingTrack[] scalingTrack = new ScalingTrack[0]; 11 | 12 | public static final String key = "KGSC"; 13 | 14 | public void load(BlizzardDataInputStream in) throws IOException { 15 | StreamUtils.checkId(in, "KGSC"); 16 | int nrOfTracks = in.readInt(); 17 | interpolationType = in.readInt(); 18 | globalSequenceId = in.readInt(); 19 | scalingTrack = new ScalingTrack[nrOfTracks]; 20 | for (int i = 0; i < nrOfTracks; i++) { 21 | scalingTrack[i] = new ScalingTrack(); 22 | scalingTrack[i].load(in); 23 | } 24 | } 25 | 26 | public void save(BlizzardDataOutputStream out) throws IOException { 27 | int nrOfTracks = scalingTrack.length; 28 | out.writeNByteString("KGSC", 4); 29 | out.writeInt(nrOfTracks); 30 | out.writeInt(interpolationType); 31 | out.writeInt(globalSequenceId); 32 | for (int i = 0; i < scalingTrack.length; i++) { 33 | scalingTrack[i].save(out); 34 | } 35 | 36 | } 37 | 38 | public int getSize() { 39 | int a = 0; 40 | a += 4; 41 | a += 4; 42 | a += 4; 43 | a += 4; 44 | for (int i = 0; i < scalingTrack.length; i++) { 45 | a += scalingTrack[i].getSize(); 46 | } 47 | 48 | return a; 49 | } 50 | 51 | public class ScalingTrack { 52 | public int time; 53 | public float[] scaling = new float[3]; 54 | public float[] inTan = new float[3]; 55 | public float[] outTan = new float[3]; 56 | 57 | public void load(BlizzardDataInputStream in) throws IOException { 58 | time = in.readInt(); 59 | scaling = StreamUtils.loadFloatArray(in, 3); 60 | if (interpolationType > 1) { 61 | inTan = StreamUtils.loadFloatArray(in, 3); 62 | outTan = StreamUtils.loadFloatArray(in, 3); 63 | } 64 | } 65 | 66 | public void save(BlizzardDataOutputStream out) throws IOException { 67 | out.writeInt(time); 68 | if (scaling.length % 3 != 0) { 69 | throw new IllegalArgumentException( 70 | "The array scaling needs either the length 3 or a multiple of this number. (got " 71 | + scaling.length + ")"); 72 | } 73 | StreamUtils.saveFloatArray(out, scaling); 74 | if (interpolationType > 1) { 75 | if (inTan.length % 3 != 0) { 76 | throw new IllegalArgumentException( 77 | "The array inTan needs either the length 3 or a multiple of this number. (got " 78 | + inTan.length + ")"); 79 | } 80 | StreamUtils.saveFloatArray(out, inTan); 81 | if (outTan.length % 3 != 0) { 82 | throw new IllegalArgumentException( 83 | "The array outTan needs either the length 3 or a multiple of this number. (got " 84 | + outTan.length + ")"); 85 | } 86 | StreamUtils.saveFloatArray(out, outTan); 87 | } 88 | 89 | } 90 | 91 | public int getSize() { 92 | int a = 0; 93 | a += 4; 94 | a += 12; 95 | if (interpolationType > 1) { 96 | a += 12; 97 | a += 12; 98 | } 99 | 100 | return a; 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/GeosetTranslation.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class GeosetTranslation { 8 | public int interpolationType; 9 | public int globalSequenceId; 10 | public TranslationTrack[] translationTrack = new TranslationTrack[0]; 11 | 12 | public static final String key = "KGTR"; 13 | 14 | public void load(BlizzardDataInputStream in) throws IOException { 15 | StreamUtils.checkId(in, "KGTR"); 16 | int nrOfTracks = in.readInt(); 17 | interpolationType = in.readInt(); 18 | globalSequenceId = in.readInt(); 19 | translationTrack = new TranslationTrack[nrOfTracks]; 20 | for (int i = 0; i < nrOfTracks; i++) { 21 | translationTrack[i] = new TranslationTrack(); 22 | translationTrack[i].load(in); 23 | } 24 | } 25 | 26 | public void save(BlizzardDataOutputStream out) throws IOException { 27 | int nrOfTracks = translationTrack.length; 28 | out.writeNByteString("KGTR", 4); 29 | out.writeInt(nrOfTracks); 30 | out.writeInt(interpolationType); 31 | out.writeInt(globalSequenceId); 32 | for (int i = 0; i < translationTrack.length; i++) { 33 | translationTrack[i].save(out); 34 | } 35 | 36 | } 37 | 38 | public int getSize() { 39 | int a = 0; 40 | a += 4; 41 | a += 4; 42 | a += 4; 43 | a += 4; 44 | for (int i = 0; i < translationTrack.length; i++) { 45 | a += translationTrack[i].getSize(); 46 | } 47 | 48 | return a; 49 | } 50 | 51 | public class TranslationTrack { 52 | public int time; 53 | public float[] translation = new float[3]; 54 | public float[] inTan = new float[3]; 55 | public float[] outTan = new float[3]; 56 | 57 | public void load(BlizzardDataInputStream in) throws IOException { 58 | time = in.readInt(); 59 | translation = StreamUtils.loadFloatArray(in, 3); 60 | if (interpolationType > 1) { 61 | inTan = StreamUtils.loadFloatArray(in, 3); 62 | outTan = StreamUtils.loadFloatArray(in, 3); 63 | } 64 | } 65 | 66 | public void save(BlizzardDataOutputStream out) throws IOException { 67 | out.writeInt(time); 68 | if (translation.length % 3 != 0) { 69 | throw new IllegalArgumentException( 70 | "The array translation needs either the length 3 or a multiple of this number. (got " 71 | + translation.length + ")"); 72 | } 73 | StreamUtils.saveFloatArray(out, translation); 74 | if (interpolationType > 1) { 75 | if (inTan.length % 3 != 0) { 76 | throw new IllegalArgumentException( 77 | "The array inTan needs either the length 3 or a multiple of this number. (got " 78 | + inTan.length + ")"); 79 | } 80 | StreamUtils.saveFloatArray(out, inTan); 81 | if (outTan.length % 3 != 0) { 82 | throw new IllegalArgumentException( 83 | "The array outTan needs either the length 3 or a multiple of this number. (got " 84 | + outTan.length + ")"); 85 | } 86 | StreamUtils.saveFloatArray(out, outTan); 87 | } 88 | 89 | } 90 | 91 | public int getSize() { 92 | int a = 0; 93 | a += 4; 94 | a += 12; 95 | if (interpolationType > 1) { 96 | a += 12; 97 | a += 12; 98 | } 99 | 100 | return a; 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/GlobalSequenceChunk.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class GlobalSequenceChunk { 8 | public int[] globalSequences = new int[0]; 9 | 10 | public static final String key = "GLBS"; 11 | 12 | public void load(BlizzardDataInputStream in) throws IOException { 13 | StreamUtils.checkId(in, "GLBS"); 14 | int chunkSize = in.readInt(); 15 | globalSequences = StreamUtils.loadIntArray(in, chunkSize / 4); 16 | } 17 | 18 | public void save(BlizzardDataOutputStream out) throws IOException { 19 | int nrOfGlobalSequences = globalSequences.length; 20 | out.writeNByteString("GLBS", 4); 21 | out.writeInt(getSize() - 8);// ChunkSize 22 | StreamUtils.saveIntArray(out, globalSequences); 23 | 24 | } 25 | 26 | public int getSize() { 27 | int a = 0; 28 | a += 4; 29 | a += 4; 30 | a += 4 * globalSequences.length; 31 | 32 | return a; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/HelperChunk.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class HelperChunk { 8 | public Helper[] helper = new Helper[0]; 9 | 10 | public static final String key = "HELP"; 11 | 12 | public void load(BlizzardDataInputStream in) throws IOException { 13 | StreamUtils.checkId(in, "HELP"); 14 | int chunkSize = in.readInt(); 15 | List helperList = new ArrayList(); 16 | int helperCounter = chunkSize; 17 | while (helperCounter > 0) { 18 | Helper temphelper = new Helper(); 19 | helperList.add(temphelper); 20 | temphelper.load(in); 21 | helperCounter -= temphelper.getSize(); 22 | } 23 | helper = helperList.toArray(new Helper[helperList.size()]); 24 | } 25 | 26 | public void save(BlizzardDataOutputStream out) throws IOException { 27 | int nrOfHelpers = helper.length; 28 | out.writeNByteString("HELP", 4); 29 | out.writeInt(getSize() - 8);// ChunkSize 30 | for (int i = 0; i < helper.length; i++) { 31 | helper[i].save(out); 32 | } 33 | 34 | } 35 | 36 | public int getSize() { 37 | int a = 0; 38 | a += 4; 39 | a += 4; 40 | for (int i = 0; i < helper.length; i++) { 41 | a += helper[i].getSize(); 42 | } 43 | 44 | return a; 45 | } 46 | 47 | public class Helper { 48 | public Node node = new Node(); 49 | 50 | public void load(BlizzardDataInputStream in) throws IOException { 51 | node = new Node(); 52 | node.load(in); 53 | } 54 | 55 | public void save(BlizzardDataOutputStream out) throws IOException { 56 | node.save(out); 57 | 58 | } 59 | 60 | public int getSize() { 61 | int a = 0; 62 | a += node.getSize(); 63 | 64 | return a; 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/LayerChunk.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class LayerChunk { 8 | public Layer[] layer = new Layer[0]; 9 | 10 | public static final String key = "LAYS"; 11 | 12 | public void load(BlizzardDataInputStream in) throws IOException { 13 | StreamUtils.checkId(in, "LAYS"); 14 | int nrOfLayers = in.readInt(); 15 | layer = new Layer[nrOfLayers]; 16 | for (int i = 0; i < nrOfLayers; i++) { 17 | layer[i] = new Layer(); 18 | layer[i].load(in); 19 | } 20 | } 21 | 22 | public void save(BlizzardDataOutputStream out) throws IOException { 23 | int nrOfLayers = layer.length; 24 | out.writeNByteString("LAYS", 4); 25 | out.writeInt(nrOfLayers); 26 | for (int i = 0; i < layer.length; i++) { 27 | layer[i].save(out); 28 | } 29 | 30 | } 31 | 32 | public int getSize() { 33 | int a = 0; 34 | a += 4; 35 | a += 4; 36 | for (int i = 0; i < layer.length; i++) { 37 | a += layer[i].getSize(); 38 | } 39 | 40 | return a; 41 | } 42 | 43 | public class Layer { 44 | public int filterMode; 45 | public int shadingFlags; 46 | public int textureId; 47 | public int textureAnimationId; 48 | public int unknownNull; 49 | public float alpha; 50 | public MaterialAlpha materialAlpha; 51 | public MaterialTextureId materialTextureId; 52 | 53 | public void load(BlizzardDataInputStream in) throws IOException { 54 | int inclusiveSize = in.readInt(); 55 | filterMode = in.readInt(); 56 | shadingFlags = in.readInt(); 57 | textureId = in.readInt(); 58 | textureAnimationId = in.readInt(); 59 | unknownNull = in.readInt(); 60 | alpha = in.readFloat(); 61 | for (int i = 0; i < 2; i++) { 62 | if (StreamUtils.checkOptionalId(in, materialAlpha.key)) { 63 | materialAlpha = new MaterialAlpha(); 64 | materialAlpha.load(in); 65 | } else if (StreamUtils.checkOptionalId(in, materialTextureId.key)) { 66 | materialTextureId = new MaterialTextureId(); 67 | materialTextureId.load(in); 68 | } 69 | 70 | } 71 | } 72 | 73 | public void save(BlizzardDataOutputStream out) throws IOException { 74 | out.writeInt(getSize());// InclusiveSize 75 | out.writeInt(filterMode); 76 | out.writeInt(shadingFlags); 77 | out.writeInt(textureId); 78 | out.writeInt(textureAnimationId); 79 | out.writeInt(unknownNull); 80 | out.writeFloat(alpha); 81 | if (materialAlpha != null) { 82 | materialAlpha.save(out); 83 | } 84 | if (materialTextureId != null) { 85 | materialTextureId.save(out); 86 | } 87 | 88 | } 89 | 90 | public int getSize() { 91 | int a = 0; 92 | a += 4; 93 | a += 4; 94 | a += 4; 95 | a += 4; 96 | a += 4; 97 | a += 4; 98 | a += 4; 99 | if (materialAlpha != null) { 100 | a += materialAlpha.getSize(); 101 | } 102 | if (materialTextureId != null) { 103 | a += materialTextureId.getSize(); 104 | } 105 | 106 | return a; 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/LightAmbientColor.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class LightAmbientColor { 8 | public int interpolationType; 9 | public int globalSequenceId; 10 | public ScalingTrack[] scalingTrack = new ScalingTrack[0]; 11 | 12 | public static final String key = "KLBC"; 13 | 14 | public void load(BlizzardDataInputStream in) throws IOException { 15 | StreamUtils.checkId(in, "KLBC"); 16 | int nrOfTracks = in.readInt(); 17 | interpolationType = in.readInt(); 18 | globalSequenceId = in.readInt(); 19 | scalingTrack = new ScalingTrack[nrOfTracks]; 20 | for (int i = 0; i < nrOfTracks; i++) { 21 | scalingTrack[i] = new ScalingTrack(); 22 | scalingTrack[i].load(in); 23 | } 24 | } 25 | 26 | public void save(BlizzardDataOutputStream out) throws IOException { 27 | int nrOfTracks = scalingTrack.length; 28 | out.writeNByteString("KLBC", 4); 29 | out.writeInt(nrOfTracks); 30 | out.writeInt(interpolationType); 31 | out.writeInt(globalSequenceId); 32 | for (int i = 0; i < scalingTrack.length; i++) { 33 | scalingTrack[i].save(out); 34 | } 35 | 36 | } 37 | 38 | public int getSize() { 39 | int a = 0; 40 | a += 4; 41 | a += 4; 42 | a += 4; 43 | a += 4; 44 | for (int i = 0; i < scalingTrack.length; i++) { 45 | a += scalingTrack[i].getSize(); 46 | } 47 | 48 | return a; 49 | } 50 | 51 | public class ScalingTrack { 52 | public int time; 53 | public float[] ambientColor = new float[3]; 54 | public float[] inTan = new float[3]; 55 | public float[] outTan = new float[3]; 56 | 57 | public void load(BlizzardDataInputStream in) throws IOException { 58 | time = in.readInt(); 59 | ambientColor = StreamUtils.loadFloatArray(in, 3); 60 | if (interpolationType > 1) { 61 | inTan = StreamUtils.loadFloatArray(in, 3); 62 | outTan = StreamUtils.loadFloatArray(in, 3); 63 | } 64 | } 65 | 66 | public void save(BlizzardDataOutputStream out) throws IOException { 67 | out.writeInt(time); 68 | if (ambientColor.length % 3 != 0) { 69 | throw new IllegalArgumentException( 70 | "The array ambientColor needs either the length 3 or a multiple of this number. (got " 71 | + ambientColor.length + ")"); 72 | } 73 | StreamUtils.saveFloatArray(out, ambientColor); 74 | if (interpolationType > 1) { 75 | if (inTan.length % 3 != 0) { 76 | throw new IllegalArgumentException( 77 | "The array inTan needs either the length 3 or a multiple of this number. (got " 78 | + inTan.length + ")"); 79 | } 80 | StreamUtils.saveFloatArray(out, inTan); 81 | if (outTan.length % 3 != 0) { 82 | throw new IllegalArgumentException( 83 | "The array outTan needs either the length 3 or a multiple of this number. (got " 84 | + outTan.length + ")"); 85 | } 86 | StreamUtils.saveFloatArray(out, outTan); 87 | } 88 | 89 | } 90 | 91 | public int getSize() { 92 | int a = 0; 93 | a += 4; 94 | a += 12; 95 | if (interpolationType > 1) { 96 | a += 12; 97 | a += 12; 98 | } 99 | 100 | return a; 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/LightAmbientIntensity.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class LightAmbientIntensity { 8 | public int interpolationType; 9 | public int globalSequenceId; 10 | public ScalingTrack[] scalingTrack = new ScalingTrack[0]; 11 | 12 | public static final String key = "KLBI"; 13 | 14 | public void load(BlizzardDataInputStream in) throws IOException { 15 | StreamUtils.checkId(in, "KLBI"); 16 | int nrOfTracks = in.readInt(); 17 | interpolationType = in.readInt(); 18 | globalSequenceId = in.readInt(); 19 | scalingTrack = new ScalingTrack[nrOfTracks]; 20 | for (int i = 0; i < nrOfTracks; i++) { 21 | scalingTrack[i] = new ScalingTrack(); 22 | scalingTrack[i].load(in); 23 | } 24 | } 25 | 26 | public void save(BlizzardDataOutputStream out) throws IOException { 27 | int nrOfTracks = scalingTrack.length; 28 | out.writeNByteString("KLBI", 4); 29 | out.writeInt(nrOfTracks); 30 | out.writeInt(interpolationType); 31 | out.writeInt(globalSequenceId); 32 | for (int i = 0; i < scalingTrack.length; i++) { 33 | scalingTrack[i].save(out); 34 | } 35 | 36 | } 37 | 38 | public int getSize() { 39 | int a = 0; 40 | a += 4; 41 | a += 4; 42 | a += 4; 43 | a += 4; 44 | for (int i = 0; i < scalingTrack.length; i++) { 45 | a += scalingTrack[i].getSize(); 46 | } 47 | 48 | return a; 49 | } 50 | 51 | public class ScalingTrack { 52 | public int time; 53 | public float ambientIntensity; 54 | public float inTan; 55 | public float outTan; 56 | 57 | public void load(BlizzardDataInputStream in) throws IOException { 58 | time = in.readInt(); 59 | ambientIntensity = in.readFloat(); 60 | if (interpolationType > 1) { 61 | inTan = in.readFloat(); 62 | outTan = in.readFloat(); 63 | } 64 | } 65 | 66 | public void save(BlizzardDataOutputStream out) throws IOException { 67 | out.writeInt(time); 68 | out.writeFloat(ambientIntensity); 69 | if (interpolationType > 1) { 70 | out.writeFloat(inTan); 71 | out.writeFloat(outTan); 72 | } 73 | 74 | } 75 | 76 | public int getSize() { 77 | int a = 0; 78 | a += 4; 79 | a += 4; 80 | if (interpolationType > 1) { 81 | a += 4; 82 | a += 4; 83 | } 84 | 85 | return a; 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/LightChunk.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class LightChunk { 8 | public Light[] light = new Light[0]; 9 | 10 | public static final String key = "LITE"; 11 | 12 | public void load(BlizzardDataInputStream in) throws IOException { 13 | StreamUtils.checkId(in, "LITE"); 14 | int chunkSize = in.readInt(); 15 | List lightList = new ArrayList(); 16 | int lightCounter = chunkSize; 17 | while (lightCounter > 0) { 18 | Light templight = new Light(); 19 | lightList.add(templight); 20 | templight.load(in); 21 | lightCounter -= templight.getSize(); 22 | } 23 | light = lightList.toArray(new Light[lightList.size()]); 24 | } 25 | 26 | public void save(BlizzardDataOutputStream out) throws IOException { 27 | int nrOfLights = light.length; 28 | out.writeNByteString("LITE", 4); 29 | out.writeInt(getSize() - 8);// ChunkSize 30 | for (int i = 0; i < light.length; i++) { 31 | light[i].save(out); 32 | } 33 | 34 | } 35 | 36 | public int getSize() { 37 | int a = 0; 38 | a += 4; 39 | a += 4; 40 | for (int i = 0; i < light.length; i++) { 41 | a += light[i].getSize(); 42 | } 43 | 44 | return a; 45 | } 46 | 47 | public class Light { 48 | public Node node = new Node(); 49 | public int type; 50 | public int attenuationStart; 51 | public int attenuationEnd; 52 | public float[] color = new float[3]; 53 | public float intensity; 54 | public float[] ambientColor = new float[3]; 55 | public float ambientIntensity; 56 | public LightVisibility lightVisibility; 57 | public LightColor lightColor; 58 | public LightIntensity lightIntensity; 59 | public LightAmbientColor lightAmbientColor; 60 | public LightAmbientIntensity lightAmbientIntensity; 61 | 62 | public void load(BlizzardDataInputStream in) throws IOException { 63 | int inclusiveSize = in.readInt(); 64 | node = new Node(); 65 | node.load(in); 66 | type = in.readInt(); 67 | attenuationStart = in.readInt(); 68 | attenuationEnd = in.readInt(); 69 | color = StreamUtils.loadFloatArray(in, 3); 70 | intensity = in.readFloat(); 71 | ambientColor = StreamUtils.loadFloatArray(in, 3); 72 | ambientIntensity = in.readFloat(); 73 | for (int i = 0; i < 5; i++) { 74 | if (StreamUtils.checkOptionalId(in, lightVisibility.key)) { 75 | lightVisibility = new LightVisibility(); 76 | lightVisibility.load(in); 77 | } else if (StreamUtils.checkOptionalId(in, lightColor.key)) { 78 | lightColor = new LightColor(); 79 | lightColor.load(in); 80 | } else if (StreamUtils.checkOptionalId(in, lightIntensity.key)) { 81 | lightIntensity = new LightIntensity(); 82 | lightIntensity.load(in); 83 | } else if (StreamUtils.checkOptionalId(in, lightAmbientColor.key)) { 84 | lightAmbientColor = new LightAmbientColor(); 85 | lightAmbientColor.load(in); 86 | } else if (StreamUtils.checkOptionalId(in, 87 | lightAmbientIntensity.key)) { 88 | lightAmbientIntensity = new LightAmbientIntensity(); 89 | lightAmbientIntensity.load(in); 90 | } 91 | 92 | } 93 | } 94 | 95 | public void save(BlizzardDataOutputStream out) throws IOException { 96 | out.writeInt(getSize());// InclusiveSize 97 | node.save(out); 98 | out.writeInt(type); 99 | out.writeInt(attenuationStart); 100 | out.writeInt(attenuationEnd); 101 | if (color.length % 3 != 0) { 102 | throw new IllegalArgumentException( 103 | "The array color needs either the length 3 or a multiple of this number. (got " 104 | + color.length + ")"); 105 | } 106 | StreamUtils.saveFloatArray(out, color); 107 | out.writeFloat(intensity); 108 | if (ambientColor.length % 3 != 0) { 109 | throw new IllegalArgumentException( 110 | "The array ambientColor needs either the length 3 or a multiple of this number. (got " 111 | + ambientColor.length + ")"); 112 | } 113 | StreamUtils.saveFloatArray(out, ambientColor); 114 | out.writeFloat(ambientIntensity); 115 | if (lightVisibility != null) { 116 | lightVisibility.save(out); 117 | } 118 | if (lightColor != null) { 119 | lightColor.save(out); 120 | } 121 | if (lightIntensity != null) { 122 | lightIntensity.save(out); 123 | } 124 | if (lightAmbientColor != null) { 125 | lightAmbientColor.save(out); 126 | } 127 | if (lightAmbientIntensity != null) { 128 | lightAmbientIntensity.save(out); 129 | } 130 | 131 | } 132 | 133 | public int getSize() { 134 | int a = 0; 135 | a += 4; 136 | a += node.getSize(); 137 | a += 4; 138 | a += 4; 139 | a += 4; 140 | a += 12; 141 | a += 4; 142 | a += 12; 143 | a += 4; 144 | if (lightVisibility != null) { 145 | a += lightVisibility.getSize(); 146 | } 147 | if (lightColor != null) { 148 | a += lightColor.getSize(); 149 | } 150 | if (lightIntensity != null) { 151 | a += lightIntensity.getSize(); 152 | } 153 | if (lightAmbientColor != null) { 154 | a += lightAmbientColor.getSize(); 155 | } 156 | if (lightAmbientIntensity != null) { 157 | a += lightAmbientIntensity.getSize(); 158 | } 159 | 160 | return a; 161 | } 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/LightColor.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class LightColor { 8 | public int interpolationType; 9 | public int globalSequenceId; 10 | public ScalingTrack[] scalingTrack = new ScalingTrack[0]; 11 | 12 | public static final String key = "KLAC"; 13 | 14 | public void load(BlizzardDataInputStream in) throws IOException { 15 | StreamUtils.checkId(in, "KLAC"); 16 | int nrOfTracks = in.readInt(); 17 | interpolationType = in.readInt(); 18 | globalSequenceId = in.readInt(); 19 | scalingTrack = new ScalingTrack[nrOfTracks]; 20 | for (int i = 0; i < nrOfTracks; i++) { 21 | scalingTrack[i] = new ScalingTrack(); 22 | scalingTrack[i].load(in); 23 | } 24 | } 25 | 26 | public void save(BlizzardDataOutputStream out) throws IOException { 27 | int nrOfTracks = scalingTrack.length; 28 | out.writeNByteString("KLAC", 4); 29 | out.writeInt(nrOfTracks); 30 | out.writeInt(interpolationType); 31 | out.writeInt(globalSequenceId); 32 | for (int i = 0; i < scalingTrack.length; i++) { 33 | scalingTrack[i].save(out); 34 | } 35 | 36 | } 37 | 38 | public int getSize() { 39 | int a = 0; 40 | a += 4; 41 | a += 4; 42 | a += 4; 43 | a += 4; 44 | for (int i = 0; i < scalingTrack.length; i++) { 45 | a += scalingTrack[i].getSize(); 46 | } 47 | 48 | return a; 49 | } 50 | 51 | public class ScalingTrack { 52 | public int time; 53 | public float[] color = new float[3]; 54 | public float[] inTan = new float[3]; 55 | public float[] outTan = new float[3]; 56 | 57 | public void load(BlizzardDataInputStream in) throws IOException { 58 | time = in.readInt(); 59 | color = StreamUtils.loadFloatArray(in, 3); 60 | if (interpolationType > 1) { 61 | inTan = StreamUtils.loadFloatArray(in, 3); 62 | outTan = StreamUtils.loadFloatArray(in, 3); 63 | } 64 | } 65 | 66 | public void save(BlizzardDataOutputStream out) throws IOException { 67 | out.writeInt(time); 68 | if (color.length % 3 != 0) { 69 | throw new IllegalArgumentException( 70 | "The array color needs either the length 3 or a multiple of this number. (got " 71 | + color.length + ")"); 72 | } 73 | StreamUtils.saveFloatArray(out, color); 74 | if (interpolationType > 1) { 75 | if (inTan.length % 3 != 0) { 76 | throw new IllegalArgumentException( 77 | "The array inTan needs either the length 3 or a multiple of this number. (got " 78 | + inTan.length + ")"); 79 | } 80 | StreamUtils.saveFloatArray(out, inTan); 81 | if (outTan.length % 3 != 0) { 82 | throw new IllegalArgumentException( 83 | "The array outTan needs either the length 3 or a multiple of this number. (got " 84 | + outTan.length + ")"); 85 | } 86 | StreamUtils.saveFloatArray(out, outTan); 87 | } 88 | 89 | } 90 | 91 | public int getSize() { 92 | int a = 0; 93 | a += 4; 94 | a += 12; 95 | if (interpolationType > 1) { 96 | a += 12; 97 | a += 12; 98 | } 99 | 100 | return a; 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/LightIntensity.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class LightIntensity { 8 | public int interpolationType; 9 | public int globalSequenceId; 10 | public ScalingTrack[] scalingTrack = new ScalingTrack[0]; 11 | 12 | public static final String key = "KLAI"; 13 | 14 | public void load(BlizzardDataInputStream in) throws IOException { 15 | StreamUtils.checkId(in, "KLAI"); 16 | int nrOfTracks = in.readInt(); 17 | interpolationType = in.readInt(); 18 | globalSequenceId = in.readInt(); 19 | scalingTrack = new ScalingTrack[nrOfTracks]; 20 | for (int i = 0; i < nrOfTracks; i++) { 21 | scalingTrack[i] = new ScalingTrack(); 22 | scalingTrack[i].load(in); 23 | } 24 | } 25 | 26 | public void save(BlizzardDataOutputStream out) throws IOException { 27 | int nrOfTracks = scalingTrack.length; 28 | out.writeNByteString("KLAI", 4); 29 | out.writeInt(nrOfTracks); 30 | out.writeInt(interpolationType); 31 | out.writeInt(globalSequenceId); 32 | for (int i = 0; i < scalingTrack.length; i++) { 33 | scalingTrack[i].save(out); 34 | } 35 | 36 | } 37 | 38 | public int getSize() { 39 | int a = 0; 40 | a += 4; 41 | a += 4; 42 | a += 4; 43 | a += 4; 44 | for (int i = 0; i < scalingTrack.length; i++) { 45 | a += scalingTrack[i].getSize(); 46 | } 47 | 48 | return a; 49 | } 50 | 51 | public class ScalingTrack { 52 | public int time; 53 | public float intensity; 54 | public float inTan; 55 | public float outTan; 56 | 57 | public void load(BlizzardDataInputStream in) throws IOException { 58 | time = in.readInt(); 59 | intensity = in.readFloat(); 60 | if (interpolationType > 1) { 61 | inTan = in.readFloat(); 62 | outTan = in.readFloat(); 63 | } 64 | } 65 | 66 | public void save(BlizzardDataOutputStream out) throws IOException { 67 | out.writeInt(time); 68 | out.writeFloat(intensity); 69 | if (interpolationType > 1) { 70 | out.writeFloat(inTan); 71 | out.writeFloat(outTan); 72 | } 73 | 74 | } 75 | 76 | public int getSize() { 77 | int a = 0; 78 | a += 4; 79 | a += 4; 80 | if (interpolationType > 1) { 81 | a += 4; 82 | a += 4; 83 | } 84 | 85 | return a; 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/LightVisibility.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class LightVisibility { 8 | public int interpolationType; 9 | public int globalSequenceId; 10 | public ScalingTrack[] scalingTrack = new ScalingTrack[0]; 11 | 12 | public static final String key = "KLAV"; 13 | 14 | public void load(BlizzardDataInputStream in) throws IOException { 15 | StreamUtils.checkId(in, "KLAV"); 16 | int nrOfTracks = in.readInt(); 17 | interpolationType = in.readInt(); 18 | globalSequenceId = in.readInt(); 19 | scalingTrack = new ScalingTrack[nrOfTracks]; 20 | for (int i = 0; i < nrOfTracks; i++) { 21 | scalingTrack[i] = new ScalingTrack(); 22 | scalingTrack[i].load(in); 23 | } 24 | } 25 | 26 | public void save(BlizzardDataOutputStream out) throws IOException { 27 | int nrOfTracks = scalingTrack.length; 28 | out.writeNByteString("KLAV", 4); 29 | out.writeInt(nrOfTracks); 30 | out.writeInt(interpolationType); 31 | out.writeInt(globalSequenceId); 32 | for (int i = 0; i < scalingTrack.length; i++) { 33 | scalingTrack[i].save(out); 34 | } 35 | 36 | } 37 | 38 | public int getSize() { 39 | int a = 0; 40 | a += 4; 41 | a += 4; 42 | a += 4; 43 | a += 4; 44 | for (int i = 0; i < scalingTrack.length; i++) { 45 | a += scalingTrack[i].getSize(); 46 | } 47 | 48 | return a; 49 | } 50 | 51 | public class ScalingTrack { 52 | public int time; 53 | public float visibility; 54 | public float inTan; 55 | public float outTan; 56 | 57 | public void load(BlizzardDataInputStream in) throws IOException { 58 | time = in.readInt(); 59 | visibility = in.readFloat(); 60 | if (interpolationType > 1) { 61 | inTan = in.readFloat(); 62 | outTan = in.readFloat(); 63 | } 64 | } 65 | 66 | public void save(BlizzardDataOutputStream out) throws IOException { 67 | out.writeInt(time); 68 | out.writeFloat(visibility); 69 | if (interpolationType > 1) { 70 | out.writeFloat(inTan); 71 | out.writeFloat(outTan); 72 | } 73 | 74 | } 75 | 76 | public int getSize() { 77 | int a = 0; 78 | a += 4; 79 | a += 4; 80 | if (interpolationType > 1) { 81 | a += 4; 82 | a += 4; 83 | } 84 | 85 | return a; 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/MaterialAlpha.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class MaterialAlpha { 8 | public int interpolationType; 9 | public int globalSequenceId; 10 | public ScalingTrack[] scalingTrack = new ScalingTrack[0]; 11 | 12 | public static final String key = "KMTA"; 13 | 14 | public void load(BlizzardDataInputStream in) throws IOException { 15 | StreamUtils.checkId(in, "KMTA"); 16 | int nrOfTracks = in.readInt(); 17 | interpolationType = in.readInt(); 18 | globalSequenceId = in.readInt(); 19 | scalingTrack = new ScalingTrack[nrOfTracks]; 20 | for (int i = 0; i < nrOfTracks; i++) { 21 | scalingTrack[i] = new ScalingTrack(); 22 | scalingTrack[i].load(in); 23 | } 24 | } 25 | 26 | public void save(BlizzardDataOutputStream out) throws IOException { 27 | int nrOfTracks = scalingTrack.length; 28 | out.writeNByteString("KMTA", 4); 29 | out.writeInt(nrOfTracks); 30 | out.writeInt(interpolationType); 31 | out.writeInt(globalSequenceId); 32 | for (int i = 0; i < scalingTrack.length; i++) { 33 | scalingTrack[i].save(out); 34 | } 35 | 36 | } 37 | 38 | public int getSize() { 39 | int a = 0; 40 | a += 4; 41 | a += 4; 42 | a += 4; 43 | a += 4; 44 | for (int i = 0; i < scalingTrack.length; i++) { 45 | a += scalingTrack[i].getSize(); 46 | } 47 | 48 | return a; 49 | } 50 | 51 | public class ScalingTrack { 52 | public int time; 53 | public float alpha; 54 | public float inTan; 55 | public float outTan; 56 | 57 | public void load(BlizzardDataInputStream in) throws IOException { 58 | time = in.readInt(); 59 | alpha = in.readFloat(); 60 | if (interpolationType > 1) { 61 | inTan = in.readFloat(); 62 | outTan = in.readFloat(); 63 | } 64 | } 65 | 66 | public void save(BlizzardDataOutputStream out) throws IOException { 67 | out.writeInt(time); 68 | out.writeFloat(alpha); 69 | if (interpolationType > 1) { 70 | out.writeFloat(inTan); 71 | out.writeFloat(outTan); 72 | } 73 | 74 | } 75 | 76 | public int getSize() { 77 | int a = 0; 78 | a += 4; 79 | a += 4; 80 | if (interpolationType > 1) { 81 | a += 4; 82 | a += 4; 83 | } 84 | 85 | return a; 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/MaterialChunk.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class MaterialChunk { 8 | public Material[] material = new Material[0]; 9 | 10 | public static final String key = "MTLS"; 11 | 12 | public void load(BlizzardDataInputStream in) throws IOException { 13 | StreamUtils.checkId(in, "MTLS"); 14 | int chunkSize = in.readInt(); 15 | List materialList = new ArrayList(); 16 | int materialCounter = chunkSize; 17 | while (materialCounter > 0) { 18 | Material tempmaterial = new Material(); 19 | materialList.add(tempmaterial); 20 | tempmaterial.load(in); 21 | materialCounter -= tempmaterial.getSize(); 22 | } 23 | material = materialList.toArray(new Material[materialList.size()]); 24 | } 25 | 26 | public void save(BlizzardDataOutputStream out) throws IOException { 27 | int nrOfMaterials = material.length; 28 | out.writeNByteString("MTLS", 4); 29 | out.writeInt(getSize() - 8);// ChunkSize 30 | for (int i = 0; i < material.length; i++) { 31 | material[i].save(out); 32 | } 33 | 34 | } 35 | 36 | public int getSize() { 37 | int a = 0; 38 | a += 4; 39 | a += 4; 40 | for (int i = 0; i < material.length; i++) { 41 | a += material[i].getSize(); 42 | } 43 | 44 | return a; 45 | } 46 | 47 | public class Material { 48 | public int priorityPlane; 49 | public int flags; 50 | public LayerChunk layerChunk; 51 | 52 | public void load(BlizzardDataInputStream in) throws IOException { 53 | int inclusiveSize = in.readInt(); 54 | priorityPlane = in.readInt(); 55 | flags = in.readInt(); 56 | 57 | if (StreamUtils.checkOptionalId(in, layerChunk.key)) { 58 | layerChunk = new LayerChunk(); 59 | layerChunk.load(in); 60 | } 61 | 62 | } 63 | 64 | public void save(BlizzardDataOutputStream out) throws IOException { 65 | out.writeInt(getSize());// InclusiveSize 66 | out.writeInt(priorityPlane); 67 | out.writeInt(flags); 68 | if (layerChunk != null) { 69 | layerChunk.save(out); 70 | } 71 | 72 | } 73 | 74 | public int getSize() { 75 | int a = 0; 76 | a += 4; 77 | a += 4; 78 | a += 4; 79 | if (layerChunk != null) { 80 | a += layerChunk.getSize(); 81 | } 82 | 83 | return a; 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/MaterialTextureId.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class MaterialTextureId { 8 | public int interpolationType; 9 | public int globalSequenceId; 10 | public ScalingTrack[] scalingTrack = new ScalingTrack[0]; 11 | 12 | public static final String key = "KMTF"; 13 | 14 | public void load(BlizzardDataInputStream in) throws IOException { 15 | StreamUtils.checkId(in, "KMTF"); 16 | int nrOfTracks = in.readInt(); 17 | interpolationType = in.readInt(); 18 | globalSequenceId = in.readInt(); 19 | scalingTrack = new ScalingTrack[nrOfTracks]; 20 | for (int i = 0; i < nrOfTracks; i++) { 21 | scalingTrack[i] = new ScalingTrack(); 22 | scalingTrack[i].load(in); 23 | } 24 | } 25 | 26 | public void save(BlizzardDataOutputStream out) throws IOException { 27 | int nrOfTracks = scalingTrack.length; 28 | out.writeNByteString("KMTF", 4); 29 | out.writeInt(nrOfTracks); 30 | out.writeInt(interpolationType); 31 | out.writeInt(globalSequenceId); 32 | for (int i = 0; i < scalingTrack.length; i++) { 33 | scalingTrack[i].save(out); 34 | } 35 | 36 | } 37 | 38 | public int getSize() { 39 | int a = 0; 40 | a += 4; 41 | a += 4; 42 | a += 4; 43 | a += 4; 44 | for (int i = 0; i < scalingTrack.length; i++) { 45 | a += scalingTrack[i].getSize(); 46 | } 47 | 48 | return a; 49 | } 50 | 51 | public class ScalingTrack { 52 | public int time; 53 | public int textureId; 54 | public int inTan; 55 | public int outTan; 56 | 57 | public void load(BlizzardDataInputStream in) throws IOException { 58 | time = in.readInt(); 59 | textureId = in.readInt(); 60 | if (interpolationType > 1) { 61 | inTan = in.readInt(); 62 | outTan = in.readInt(); 63 | } 64 | } 65 | 66 | public void save(BlizzardDataOutputStream out) throws IOException { 67 | out.writeInt(time); 68 | out.writeInt(textureId); 69 | if (interpolationType > 1) { 70 | out.writeInt(inTan); 71 | out.writeInt(outTan); 72 | } 73 | 74 | } 75 | 76 | public int getSize() { 77 | int a = 0; 78 | a += 4; 79 | a += 4; 80 | if (interpolationType > 1) { 81 | a += 4; 82 | a += 4; 83 | } 84 | 85 | return a; 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/MdxModel.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class MdxModel { 8 | 9 | public VersionChunk versionChunk; 10 | public ModelChunk modelChunk; 11 | public SequenceChunk sequenceChunk; 12 | public GlobalSequenceChunk globalSequenceChunk; 13 | public MaterialChunk materialChunk; 14 | public TextureChunk textureChunk; 15 | public TextureAnimationChunk textureAnimationChunk; 16 | public GeosetChunk geosetChunk; 17 | public GeosetAnimationChunk geosetAnimationChunk; 18 | public BoneChunk boneChunk; 19 | public LightChunk lightChunk; 20 | public HelperChunk helperChunk; 21 | public AttachmentChunk attachmentChunk; 22 | public PivotPointChunk pivotPointChunk; 23 | public ParticleEmitterChunk particleEmitterChunk; 24 | public ParticleEmitter2Chunk particleEmitter2Chunk; 25 | public RibbonEmitterChunk ribbonEmitterChunk; 26 | public EventObjectChunk eventObjectChunk; 27 | public CameraChunk cameraChunk; 28 | public CollisionShapeChunk collisionShapeChunk; 29 | 30 | public static final String key = "MDLX"; 31 | 32 | public void load(BlizzardDataInputStream in) throws IOException { 33 | StreamUtils.checkId(in, "MDLX"); 34 | 35 | String chunkId; ; 36 | while ((chunkId= StreamUtils.readOptionalId(in)) != null) { 37 | 38 | switch (chunkId) { 39 | case VersionChunk.key: 40 | versionChunk = new VersionChunk(); 41 | versionChunk.load(in); 42 | break; 43 | case ModelChunk.key: 44 | modelChunk = new ModelChunk(); 45 | modelChunk.load(in); 46 | break; 47 | case SequenceChunk.key: 48 | sequenceChunk = new SequenceChunk(); 49 | sequenceChunk.load(in); 50 | break; 51 | case GlobalSequenceChunk.key: 52 | globalSequenceChunk = new GlobalSequenceChunk(); 53 | globalSequenceChunk.load(in); 54 | break; 55 | case MaterialChunk.key: 56 | materialChunk = new MaterialChunk(); 57 | materialChunk.load(in); 58 | break; 59 | case TextureChunk.key: 60 | textureChunk = new TextureChunk(); 61 | textureChunk.load(in); 62 | break; 63 | case TextureAnimationChunk.key: 64 | textureAnimationChunk = new TextureAnimationChunk(); 65 | textureAnimationChunk.load(in); 66 | break; 67 | case GeosetChunk.key: 68 | geosetChunk = new GeosetChunk(); 69 | geosetChunk.load(in); 70 | break; 71 | case GeosetAnimationChunk.key: 72 | geosetAnimationChunk = new GeosetAnimationChunk(); 73 | geosetAnimationChunk.load(in); 74 | break; 75 | case BoneChunk.key: 76 | boneChunk = new BoneChunk(); 77 | boneChunk.load(in); 78 | break; 79 | case LightChunk.key: 80 | lightChunk = new LightChunk(); 81 | lightChunk.load(in); 82 | break; 83 | case HelperChunk.key: 84 | helperChunk = new HelperChunk(); 85 | helperChunk.load(in); 86 | break; 87 | case AttachmentChunk.key: 88 | attachmentChunk = new AttachmentChunk(); 89 | attachmentChunk.load(in); 90 | break; 91 | case PivotPointChunk.key: 92 | pivotPointChunk = new PivotPointChunk(); 93 | pivotPointChunk.load(in); 94 | break; 95 | case ParticleEmitterChunk.key: 96 | particleEmitterChunk = new ParticleEmitterChunk(); 97 | particleEmitterChunk.load(in); 98 | break; 99 | case ParticleEmitter2Chunk.key: 100 | particleEmitter2Chunk = new ParticleEmitter2Chunk(); 101 | particleEmitter2Chunk.load(in); 102 | break; 103 | case RibbonEmitterChunk.key: 104 | ribbonEmitterChunk = new RibbonEmitterChunk(); 105 | ribbonEmitterChunk.load(in); 106 | break; 107 | case EventObjectChunk.key: 108 | eventObjectChunk = new EventObjectChunk(); 109 | eventObjectChunk.load(in); 110 | break; 111 | case CameraChunk.key: 112 | cameraChunk = new CameraChunk(); 113 | cameraChunk.load(in); 114 | break; 115 | case CollisionShapeChunk.key: 116 | collisionShapeChunk = new CollisionShapeChunk(); 117 | collisionShapeChunk.load(in); 118 | break; 119 | default: 120 | StreamUtils.checkId(in, chunkId); 121 | int chunkSize = in.readInt(); 122 | in.read(new byte[chunkSize]); 123 | } 124 | } 125 | } 126 | 127 | public void save(BlizzardDataOutputStream out) throws IOException { 128 | out.writeNByteString("MDLX", 4); 129 | if (versionChunk != null) { 130 | versionChunk.save(out); 131 | } 132 | if (modelChunk != null) { 133 | modelChunk.save(out); 134 | } 135 | if (sequenceChunk != null) { 136 | sequenceChunk.save(out); 137 | } 138 | if (globalSequenceChunk != null) { 139 | globalSequenceChunk.save(out); 140 | } 141 | if (materialChunk != null) { 142 | materialChunk.save(out); 143 | } 144 | if (textureChunk != null) { 145 | textureChunk.save(out); 146 | } 147 | if (textureAnimationChunk != null) { 148 | textureAnimationChunk.save(out); 149 | } 150 | if (geosetChunk != null) { 151 | geosetChunk.save(out); 152 | } 153 | if (geosetAnimationChunk != null) { 154 | geosetAnimationChunk.save(out); 155 | } 156 | if (boneChunk != null) { 157 | boneChunk.save(out); 158 | } 159 | if (lightChunk != null) { 160 | lightChunk.save(out); 161 | } 162 | if (helperChunk != null) { 163 | helperChunk.save(out); 164 | } 165 | if (attachmentChunk != null) { 166 | attachmentChunk.save(out); 167 | } 168 | if (pivotPointChunk != null) { 169 | pivotPointChunk.save(out); 170 | } 171 | if (particleEmitterChunk != null) { 172 | particleEmitterChunk.save(out); 173 | } 174 | if (particleEmitter2Chunk != null) { 175 | particleEmitter2Chunk.save(out); 176 | } 177 | if (ribbonEmitterChunk != null) { 178 | ribbonEmitterChunk.save(out); 179 | } 180 | if (eventObjectChunk != null) { 181 | eventObjectChunk.save(out); 182 | } 183 | if (cameraChunk != null) { 184 | cameraChunk.save(out); 185 | } 186 | if (collisionShapeChunk != null) { 187 | collisionShapeChunk.save(out); 188 | } 189 | 190 | } 191 | 192 | public int getSize() { 193 | int a = 0; 194 | a += 4; 195 | if (versionChunk != null) { 196 | a += versionChunk.getSize(); 197 | } 198 | if (modelChunk != null) { 199 | a += modelChunk.getSize(); 200 | } 201 | if (sequenceChunk != null) { 202 | a += sequenceChunk.getSize(); 203 | } 204 | if (globalSequenceChunk != null) { 205 | a += globalSequenceChunk.getSize(); 206 | } 207 | if (materialChunk != null) { 208 | a += materialChunk.getSize(); 209 | } 210 | if (textureChunk != null) { 211 | a += textureChunk.getSize(); 212 | } 213 | if (textureAnimationChunk != null) { 214 | a += textureAnimationChunk.getSize(); 215 | } 216 | if (geosetChunk != null) { 217 | a += geosetChunk.getSize(); 218 | } 219 | if (geosetAnimationChunk != null) { 220 | a += geosetAnimationChunk.getSize(); 221 | } 222 | if (boneChunk != null) { 223 | a += boneChunk.getSize(); 224 | } 225 | if (lightChunk != null) { 226 | a += lightChunk.getSize(); 227 | } 228 | if (helperChunk != null) { 229 | a += helperChunk.getSize(); 230 | } 231 | if (attachmentChunk != null) { 232 | a += attachmentChunk.getSize(); 233 | } 234 | if (pivotPointChunk != null) { 235 | a += pivotPointChunk.getSize(); 236 | } 237 | if (particleEmitterChunk != null) { 238 | a += particleEmitterChunk.getSize(); 239 | } 240 | if (particleEmitter2Chunk != null) { 241 | a += particleEmitter2Chunk.getSize(); 242 | } 243 | if (ribbonEmitterChunk != null) { 244 | a += ribbonEmitterChunk.getSize(); 245 | } 246 | if (eventObjectChunk != null) { 247 | a += eventObjectChunk.getSize(); 248 | } 249 | if (cameraChunk != null) { 250 | a += cameraChunk.getSize(); 251 | } 252 | if (collisionShapeChunk != null) { 253 | a += collisionShapeChunk.getSize(); 254 | } 255 | 256 | return a; 257 | } 258 | } 259 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/ModelChunk.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class ModelChunk { 8 | public String name = ""; 9 | public int unknownNull; 10 | public float boundsRadius; 11 | public float[] minimumExtent = new float[3]; 12 | public float[] maximumExtent = new float[3]; 13 | public int blendTime; 14 | 15 | public static final String key = "MODL"; 16 | 17 | public void load(BlizzardDataInputStream in) throws IOException { 18 | StreamUtils.checkId(in, "MODL"); 19 | int chunkSize = in.readInt(); 20 | name = in.readCharsAsString(336); 21 | unknownNull = in.readInt(); 22 | boundsRadius = in.readFloat(); 23 | minimumExtent = StreamUtils.loadFloatArray(in, 3); 24 | maximumExtent = StreamUtils.loadFloatArray(in, 3); 25 | blendTime = in.readInt(); 26 | } 27 | 28 | public void save(BlizzardDataOutputStream out) throws IOException { 29 | out.writeNByteString("MODL", 4); 30 | out.writeInt(getSize() - 8);// ChunkSize 31 | out.writeNByteString(name, 336); 32 | out.writeInt(unknownNull); 33 | out.writeFloat(boundsRadius); 34 | if (minimumExtent.length % 3 != 0) { 35 | throw new IllegalArgumentException( 36 | "The array minimumExtent needs either the length 3 or a multiple of this number. (got " 37 | + minimumExtent.length + ")"); 38 | } 39 | StreamUtils.saveFloatArray(out, minimumExtent); 40 | if (maximumExtent.length % 3 != 0) { 41 | throw new IllegalArgumentException( 42 | "The array maximumExtent needs either the length 3 or a multiple of this number. (got " 43 | + maximumExtent.length + ")"); 44 | } 45 | StreamUtils.saveFloatArray(out, maximumExtent); 46 | out.writeInt(blendTime); 47 | 48 | } 49 | 50 | public int getSize() { 51 | int a = 0; 52 | a += 4; 53 | a += 4; 54 | a += 336; 55 | a += 4; 56 | a += 4; 57 | a += 12; 58 | a += 12; 59 | a += 4; 60 | 61 | return a; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/ModelUtils.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.mdx.GeosetChunk; 4 | import de.wc3data.mdx.GeosetChunk.Geoset; 5 | import de.wc3data.mdx.MdxModel; 6 | import de.wc3data.mdx.ModelChunk; 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | 11 | /** 12 | * This class contains some useful functions to create/edit mdx models 13 | * @author Oger-Lord 14 | */ 15 | public class ModelUtils { 16 | 17 | /** 18 | * Converts a list of integer values into a short array. 19 | * @param list 20 | * @return 21 | */ 22 | public static short[] convert2ShortArrayI(List list) { 23 | short[] array = new short[list.size()]; 24 | 25 | for (int i = 0; i < list.size(); i++) { 26 | array[i] = (short)((int)list.get(i)); 27 | } 28 | 29 | return array; 30 | } 31 | 32 | /** 33 | * Converts a list of short values into a short array. 34 | * @param list 35 | * @return 36 | */ 37 | public static short[] convert2ShortArray(List list) { 38 | short[] array = new short[list.size()]; 39 | 40 | for (int i = 0; i < list.size(); i++) { 41 | array[i] = list.get(i); 42 | } 43 | 44 | return array; 45 | } 46 | 47 | /** 48 | * Converts a list of float values into a float array. 49 | * @param list 50 | * @return 51 | */ 52 | public static float[] convert2FloatArray(List list) { 53 | float[] array = new float[list.size()]; 54 | 55 | for (int i = 0; i < list.size(); i++) { 56 | array[i] = list.get(i); 57 | } 58 | 59 | return array; 60 | } 61 | 62 | /** 63 | * Generate the ModelChunk for a given model. 64 | * The ModelChunk contains the extents, blendtime and the name of the model. 65 | * Make sure to add the geosets befor using this function. 66 | * @param list 67 | * @return 68 | */ 69 | public static void generateModelChunk(MdxModel model, String name){ 70 | ModelChunk chunk = new ModelChunk(); 71 | 72 | float[] max = new float[3]; 73 | float[] min = new float[3]; 74 | 75 | if(model.geosetChunk != null && model.geosetChunk.geoset != null){ 76 | 77 | for(Geoset geoset : model.geosetChunk.geoset){ 78 | for(int a=0;a<3;a++){ 79 | 80 | if(geoset.maximumExtent[a] > max[a]) 81 | max[a] = geoset.maximumExtent[a]; 82 | if(geoset.minimumExtent[a] < min[a]) 83 | min[a] = geoset.minimumExtent[a]; 84 | } 85 | } 86 | 87 | float bounds = 0; 88 | for(int a=0;a<3;a++){ 89 | bounds += ((max[a]-min[a])*(max[a]-min[a]))/4; 90 | } 91 | bounds = (float)Math.sqrt(bounds); 92 | 93 | chunk.minimumExtent = min; 94 | chunk.maximumExtent = max; 95 | chunk.boundsRadius = bounds; 96 | } 97 | 98 | chunk.blendTime=150; 99 | chunk.name=name; 100 | 101 | model.modelChunk = chunk; 102 | } 103 | 104 | /** 105 | * Calculates the normals of a geoset. 106 | * Make sure you added the vertices befor calling this function! 107 | * @param geoset 108 | */ 109 | public static void calculateExtent(GeosetChunk.Geoset geoset){ 110 | if(geoset.vertexPositions == null || geoset.vertexPositions.length == 0){ 111 | throw new IllegalArgumentException("Error, the geoset does not have vertices."); 112 | } 113 | 114 | 115 | float[] max = new float[3]; 116 | float[] min = new float[3]; 117 | 118 | for(int i=0;i max[a]) 122 | max[a] = val; 123 | if(val < min[a]) 124 | min[a] = val; 125 | } 126 | } 127 | 128 | float bounds = 0; 129 | for(int a=0;a<3;a++){ 130 | bounds += ((max[a]-min[a])*(max[a]-min[a]))/4; 131 | } 132 | bounds = (float)Math.sqrt(bounds); 133 | 134 | geoset.minimumExtent = min; 135 | geoset.maximumExtent = max; 136 | geoset.boundsRadius = bounds; 137 | } 138 | 139 | 140 | 141 | /** 142 | * Calculates the vertex groups, face groups and facetypegroups of a geoset. 143 | * Make sure you added the vertices and faces befor calling this function! 144 | * @param geoset 145 | */ 146 | public static void calculateVertexGroup(GeosetChunk.Geoset geoset){ 147 | 148 | geoset.nrOfTextureVertexGroups=1; 149 | 150 | geoset.faceTypeGroups = new int[1]; 151 | geoset.faceTypeGroups[0] = 4; 152 | 153 | geoset.vertexGroups = new byte[geoset.vertexPositions.length/3]; 154 | geoset.faceGroups = new int[1]; 155 | geoset.faceGroups[0] = geoset.faces.length; 156 | } 157 | 158 | /** 159 | * Calculates the normals of a geoset. 160 | * Make sure you added the vertices and faces befor calling this function! 161 | * @param geoset 162 | */ 163 | public static void calculateNormals(GeosetChunk.Geoset geoset){ 164 | if(geoset.vertexPositions == null || geoset.vertexPositions.length == 0){ 165 | throw new IllegalArgumentException("Error, the geoset does not have vertices."); 166 | } 167 | 168 | geoset.vertexNormals = calculateNormals(geoset.vertexPositions, geoset.faces); 169 | } 170 | 171 | private static float[] calculateNormals(float[] vertices, short[] faces) { 172 | ArrayList vectorList[] = new ArrayList[vertices.length / 3]; 173 | 174 | for (int i = 0; i < vectorList.length; i++) { 175 | vectorList[i] = new ArrayList(); 176 | } 177 | 178 | for (int i = 0; i < faces.length; i += 3) { 179 | float[] n = calculateNormalFace(vertices, faces, i); 180 | 181 | for (int a = 0; a < 3; a++) { 182 | vectorList[faces[i + a]].add(n[0]); 183 | vectorList[faces[i + a]].add(n[1]); 184 | vectorList[faces[i + a]].add(n[2]); 185 | } 186 | } 187 | 188 | //Durchschnitts normal errechnen 189 | float[] normals = new float[vertices.length]; 190 | 191 | for (int i = 0; i < vectorList.length; i++) { 192 | 193 | int vertPos = i * 3; 194 | 195 | float x = 0; 196 | float y = 0; 197 | float z = 0; 198 | 199 | for (int a = 0; a < vectorList[i].size(); a += 3) { 200 | x += vectorList[i].get(a); 201 | y += vectorList[i].get(a + 1); 202 | z += vectorList[i].get(a + 2); 203 | } 204 | 205 | float dist = (float) Math.sqrt(x * x + y * y + z * z); 206 | x /= dist; 207 | y /= dist; 208 | z /= dist; 209 | 210 | normals[vertPos] = x; 211 | normals[vertPos + 1] = y; 212 | normals[vertPos + 2] = z; 213 | } 214 | 215 | return normals; 216 | } 217 | 218 | private static float[] calculateNormalFace(float[] vertices, short[] faces, int i) { 219 | 220 | if (i % 3 != 0) { 221 | throw new IllegalArgumentException("i%3 must be 0"); 222 | } 223 | 224 | float ax = vertices[faces[i] * 3]; 225 | float ay = vertices[faces[i] * 3 + 1]; 226 | float az = vertices[faces[i] * 3 + 2]; 227 | 228 | float bx = vertices[faces[i + 1] * 3]; 229 | float by = vertices[faces[i + 1] * 3 + 1]; 230 | float bz = vertices[faces[i + 1] * 3 + 2]; 231 | 232 | float cx = vertices[faces[i + 2] * 3]; 233 | float cy = vertices[faces[i + 2] * 3 + 1]; 234 | float cz = vertices[faces[i + 2] * 3 + 2]; 235 | 236 | float d1x = bx - ax; 237 | float d1y = by - ay; 238 | float d1z = bz - az; 239 | 240 | float d2x = cx - ax; 241 | float d2y = cy - ay; 242 | float d2z = cz - az; 243 | 244 | float nx = d1y * d2z - d1z * d2y; 245 | float ny = d1z * d2x - d1x * d2z; 246 | float nz = d1x * d2y - d1y * d2x; 247 | 248 | float dist = (float) Math.sqrt(nx * nx + ny * ny + nz * nz); 249 | nx = nx / dist; 250 | ny = ny / dist; 251 | nz = nz / dist; 252 | 253 | float n[] = {nx, ny, nz}; 254 | return n; 255 | } 256 | } 257 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/Node.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class Node { 8 | public String name = ""; 9 | public int objectId; 10 | public int parentId; 11 | public int flags; 12 | public GeosetTranslation geosetTranslation; 13 | public GeosetRotation geosetRotation; 14 | public GeosetScaling geosetScaling; 15 | 16 | public void load(BlizzardDataInputStream in) throws IOException { 17 | int inclusiveSize = in.readInt(); 18 | name = in.readCharsAsString(80); 19 | objectId = in.readInt(); 20 | parentId = in.readInt(); 21 | flags = in.readInt(); 22 | for (int i = 0; i < 3; i++) { 23 | if (StreamUtils.checkOptionalId(in, geosetTranslation.key)) { 24 | geosetTranslation = new GeosetTranslation(); 25 | geosetTranslation.load(in); 26 | } else if (StreamUtils.checkOptionalId(in, geosetRotation.key)) { 27 | geosetRotation = new GeosetRotation(); 28 | geosetRotation.load(in); 29 | } else if (StreamUtils.checkOptionalId(in, geosetScaling.key)) { 30 | geosetScaling = new GeosetScaling(); 31 | geosetScaling.load(in); 32 | } 33 | 34 | } 35 | } 36 | 37 | public void save(BlizzardDataOutputStream out) throws IOException { 38 | out.writeInt(getSize());// InclusiveSize 39 | out.writeNByteString(name, 80); 40 | out.writeInt(objectId); 41 | out.writeInt(parentId); 42 | out.writeInt(flags); 43 | if (geosetTranslation != null) { 44 | geosetTranslation.save(out); 45 | } 46 | if (geosetRotation != null) { 47 | geosetRotation.save(out); 48 | } 49 | if (geosetScaling != null) { 50 | geosetScaling.save(out); 51 | } 52 | 53 | } 54 | 55 | public int getSize() { 56 | int a = 0; 57 | a += 4; 58 | a += 80; 59 | a += 4; 60 | a += 4; 61 | a += 4; 62 | if (geosetTranslation != null) { 63 | a += geosetTranslation.getSize(); 64 | } 65 | if (geosetRotation != null) { 66 | a += geosetRotation.getSize(); 67 | } 68 | if (geosetScaling != null) { 69 | a += geosetScaling.getSize(); 70 | } 71 | 72 | return a; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/ParticleEmitter2Chunk.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class ParticleEmitter2Chunk { 8 | public ParticleEmitter2[] particleEmitter2 = new ParticleEmitter2[0]; 9 | 10 | public static final String key = "PRE2"; 11 | 12 | public void load(BlizzardDataInputStream in) throws IOException { 13 | StreamUtils.checkId(in, "PRE2"); 14 | int chunkSize = in.readInt(); 15 | List particleEmitter2List = new ArrayList(); 16 | int particleEmitter2Counter = chunkSize; 17 | while (particleEmitter2Counter > 0) { 18 | ParticleEmitter2 tempparticleEmitter2 = new ParticleEmitter2(); 19 | particleEmitter2List.add(tempparticleEmitter2); 20 | tempparticleEmitter2.load(in); 21 | particleEmitter2Counter -= tempparticleEmitter2.getSize(); 22 | } 23 | particleEmitter2 = particleEmitter2List 24 | .toArray(new ParticleEmitter2[particleEmitter2List.size()]); 25 | } 26 | 27 | public void save(BlizzardDataOutputStream out) throws IOException { 28 | int nrOfParticleEmitters2 = particleEmitter2.length; 29 | out.writeNByteString("PRE2", 4); 30 | out.writeInt(getSize() - 8);// ChunkSize 31 | for (int i = 0; i < particleEmitter2.length; i++) { 32 | particleEmitter2[i].save(out); 33 | } 34 | 35 | } 36 | 37 | public int getSize() { 38 | int a = 0; 39 | a += 4; 40 | a += 4; 41 | for (int i = 0; i < particleEmitter2.length; i++) { 42 | a += particleEmitter2[i].getSize(); 43 | } 44 | 45 | return a; 46 | } 47 | 48 | public class ParticleEmitter2 { 49 | public Node node = new Node(); 50 | public float speed; 51 | public float variation; 52 | public float latitude; 53 | public float gravity; 54 | public float lifespan; 55 | public float emissionRate; 56 | public float length; 57 | public float width; 58 | public int filterMode; 59 | public int rows; 60 | public int columns; 61 | public int headOrTail; 62 | public float tailLength; 63 | public float time; 64 | public float[] segmentColor = new float[9]; 65 | public byte[] segmentAlpha = new byte[3]; 66 | public float[] segmentScaling = new float[3]; 67 | public int headIntervalStart; 68 | public int headIntervalEnd; 69 | public int headIntervalRepeat; 70 | public int headDecayIntervalStart; 71 | public int headDecayIntervalEnd; 72 | public int headDecayIntervalRepeat; 73 | public int tailIntervalStart; 74 | public int tailIntervalEnd; 75 | public int tailIntervalRepeat; 76 | public int tailDecayIntervalStart; 77 | public int tailDecayIntervalEnd; 78 | public int tailDecayIntervalRepeat; 79 | public int textureId; 80 | public int squirt; 81 | public int priorityPlane; 82 | public int replaceableId; 83 | public ParticleEmitter2Visibility particleEmitter2Visibility; 84 | public ParticleEmitter2EmissionRate particleEmitter2EmissionRate; 85 | public ParticleEmitter2Width particleEmitter2Width; 86 | public ParticleEmitter2Length particleEmitter2Length; 87 | public ParticleEmitter2Speed particleEmitter2Speed; 88 | public ParticleEmitter2Latitude particleEmitter2Latitude; 89 | 90 | public void load(BlizzardDataInputStream in) throws IOException { 91 | int inclusiveSize = in.readInt(); 92 | node = new Node(); 93 | node.load(in); 94 | speed = in.readFloat(); 95 | variation = in.readFloat(); 96 | latitude = in.readFloat(); 97 | gravity = in.readFloat(); 98 | lifespan = in.readFloat(); 99 | emissionRate = in.readFloat(); 100 | length = in.readFloat(); 101 | width = in.readFloat(); 102 | filterMode = in.readInt(); 103 | rows = in.readInt(); 104 | columns = in.readInt(); 105 | headOrTail = in.readInt(); 106 | tailLength = in.readFloat(); 107 | time = in.readFloat(); 108 | segmentColor = StreamUtils.loadFloatArray(in, 9); 109 | segmentAlpha = StreamUtils.loadByteArray(in, 3); 110 | segmentScaling = StreamUtils.loadFloatArray(in, 3); 111 | headIntervalStart = in.readInt(); 112 | headIntervalEnd = in.readInt(); 113 | headIntervalRepeat = in.readInt(); 114 | headDecayIntervalStart = in.readInt(); 115 | headDecayIntervalEnd = in.readInt(); 116 | headDecayIntervalRepeat = in.readInt(); 117 | tailIntervalStart = in.readInt(); 118 | tailIntervalEnd = in.readInt(); 119 | tailIntervalRepeat = in.readInt(); 120 | tailDecayIntervalStart = in.readInt(); 121 | tailDecayIntervalEnd = in.readInt(); 122 | tailDecayIntervalRepeat = in.readInt(); 123 | textureId = in.readInt(); 124 | squirt = in.readInt(); 125 | priorityPlane = in.readInt(); 126 | replaceableId = in.readInt(); 127 | for (int i = 0; i < 6; i++) { 128 | if (StreamUtils 129 | .checkOptionalId(in, particleEmitter2Visibility.key)) { 130 | particleEmitter2Visibility = new ParticleEmitter2Visibility(); 131 | particleEmitter2Visibility.load(in); 132 | } else if (StreamUtils.checkOptionalId(in, 133 | particleEmitter2EmissionRate.key)) { 134 | particleEmitter2EmissionRate = new ParticleEmitter2EmissionRate(); 135 | particleEmitter2EmissionRate.load(in); 136 | } else if (StreamUtils.checkOptionalId(in, 137 | particleEmitter2Width.key)) { 138 | particleEmitter2Width = new ParticleEmitter2Width(); 139 | particleEmitter2Width.load(in); 140 | } else if (StreamUtils.checkOptionalId(in, 141 | particleEmitter2Length.key)) { 142 | particleEmitter2Length = new ParticleEmitter2Length(); 143 | particleEmitter2Length.load(in); 144 | } else if (StreamUtils.checkOptionalId(in, 145 | particleEmitter2Speed.key)) { 146 | particleEmitter2Speed = new ParticleEmitter2Speed(); 147 | particleEmitter2Speed.load(in); 148 | } else if (StreamUtils.checkOptionalId(in, 149 | particleEmitter2Latitude.key)) { 150 | particleEmitter2Latitude = new ParticleEmitter2Latitude(); 151 | particleEmitter2Latitude.load(in); 152 | } 153 | 154 | } 155 | } 156 | 157 | public void save(BlizzardDataOutputStream out) throws IOException { 158 | out.writeInt(getSize());// InclusiveSize 159 | node.save(out); 160 | out.writeFloat(speed); 161 | out.writeFloat(variation); 162 | out.writeFloat(latitude); 163 | out.writeFloat(gravity); 164 | out.writeFloat(lifespan); 165 | out.writeFloat(emissionRate); 166 | out.writeFloat(length); 167 | out.writeFloat(width); 168 | out.writeInt(filterMode); 169 | out.writeInt(rows); 170 | out.writeInt(columns); 171 | out.writeInt(headOrTail); 172 | out.writeFloat(tailLength); 173 | out.writeFloat(time); 174 | if (segmentColor.length % 9 != 0) { 175 | throw new IllegalArgumentException( 176 | "The array segmentColor needs either the length 9 or a multiple of this number. (got " 177 | + segmentColor.length + ")"); 178 | } 179 | StreamUtils.saveFloatArray(out, segmentColor); 180 | if (segmentAlpha.length % 3 != 0) { 181 | throw new IllegalArgumentException( 182 | "The array segmentAlpha needs either the length 3 or a multiple of this number. (got " 183 | + segmentAlpha.length + ")"); 184 | } 185 | StreamUtils.saveByteArray(out, segmentAlpha); 186 | if (segmentScaling.length % 3 != 0) { 187 | throw new IllegalArgumentException( 188 | "The array segmentScaling needs either the length 3 or a multiple of this number. (got " 189 | + segmentScaling.length + ")"); 190 | } 191 | StreamUtils.saveFloatArray(out, segmentScaling); 192 | out.writeInt(headIntervalStart); 193 | out.writeInt(headIntervalEnd); 194 | out.writeInt(headIntervalRepeat); 195 | out.writeInt(headDecayIntervalStart); 196 | out.writeInt(headDecayIntervalEnd); 197 | out.writeInt(headDecayIntervalRepeat); 198 | out.writeInt(tailIntervalStart); 199 | out.writeInt(tailIntervalEnd); 200 | out.writeInt(tailIntervalRepeat); 201 | out.writeInt(tailDecayIntervalStart); 202 | out.writeInt(tailDecayIntervalEnd); 203 | out.writeInt(tailDecayIntervalRepeat); 204 | out.writeInt(textureId); 205 | out.writeInt(squirt); 206 | out.writeInt(priorityPlane); 207 | out.writeInt(replaceableId); 208 | if (particleEmitter2Visibility != null) { 209 | particleEmitter2Visibility.save(out); 210 | } 211 | if (particleEmitter2EmissionRate != null) { 212 | particleEmitter2EmissionRate.save(out); 213 | } 214 | if (particleEmitter2Width != null) { 215 | particleEmitter2Width.save(out); 216 | } 217 | if (particleEmitter2Length != null) { 218 | particleEmitter2Length.save(out); 219 | } 220 | if (particleEmitter2Speed != null) { 221 | particleEmitter2Speed.save(out); 222 | } 223 | if (particleEmitter2Latitude != null) { 224 | particleEmitter2Latitude.save(out); 225 | } 226 | 227 | } 228 | 229 | public int getSize() { 230 | int a = 0; 231 | a += 4; 232 | a += node.getSize(); 233 | a += 4; 234 | a += 4; 235 | a += 4; 236 | a += 4; 237 | a += 4; 238 | a += 4; 239 | a += 4; 240 | a += 4; 241 | a += 4; 242 | a += 4; 243 | a += 4; 244 | a += 4; 245 | a += 4; 246 | a += 4; 247 | a += 36; 248 | a += 3; 249 | a += 12; 250 | a += 4; 251 | a += 4; 252 | a += 4; 253 | a += 4; 254 | a += 4; 255 | a += 4; 256 | a += 4; 257 | a += 4; 258 | a += 4; 259 | a += 4; 260 | a += 4; 261 | a += 4; 262 | a += 4; 263 | a += 4; 264 | a += 4; 265 | a += 4; 266 | if (particleEmitter2Visibility != null) { 267 | a += particleEmitter2Visibility.getSize(); 268 | } 269 | if (particleEmitter2EmissionRate != null) { 270 | a += particleEmitter2EmissionRate.getSize(); 271 | } 272 | if (particleEmitter2Width != null) { 273 | a += particleEmitter2Width.getSize(); 274 | } 275 | if (particleEmitter2Length != null) { 276 | a += particleEmitter2Length.getSize(); 277 | } 278 | if (particleEmitter2Speed != null) { 279 | a += particleEmitter2Speed.getSize(); 280 | } 281 | if (particleEmitter2Latitude != null) { 282 | a += particleEmitter2Latitude.getSize(); 283 | } 284 | 285 | return a; 286 | } 287 | } 288 | } 289 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/ParticleEmitter2EmissionRate.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class ParticleEmitter2EmissionRate { 8 | public int interpolationType; 9 | public int globalSequenceId; 10 | public ScalingTrack[] scalingTrack = new ScalingTrack[0]; 11 | 12 | public static final String key = "KP2E"; 13 | 14 | public void load(BlizzardDataInputStream in) throws IOException { 15 | StreamUtils.checkId(in, "KP2E"); 16 | int nrOfTracks = in.readInt(); 17 | interpolationType = in.readInt(); 18 | globalSequenceId = in.readInt(); 19 | scalingTrack = new ScalingTrack[nrOfTracks]; 20 | for (int i = 0; i < nrOfTracks; i++) { 21 | scalingTrack[i] = new ScalingTrack(); 22 | scalingTrack[i].load(in); 23 | } 24 | } 25 | 26 | public void save(BlizzardDataOutputStream out) throws IOException { 27 | int nrOfTracks = scalingTrack.length; 28 | out.writeNByteString("KP2E", 4); 29 | out.writeInt(nrOfTracks); 30 | out.writeInt(interpolationType); 31 | out.writeInt(globalSequenceId); 32 | for (int i = 0; i < scalingTrack.length; i++) { 33 | scalingTrack[i].save(out); 34 | } 35 | 36 | } 37 | 38 | public int getSize() { 39 | int a = 0; 40 | a += 4; 41 | a += 4; 42 | a += 4; 43 | a += 4; 44 | for (int i = 0; i < scalingTrack.length; i++) { 45 | a += scalingTrack[i].getSize(); 46 | } 47 | 48 | return a; 49 | } 50 | 51 | public class ScalingTrack { 52 | public int time; 53 | public float emissionRate; 54 | public float inTan; 55 | public float outTan; 56 | 57 | public void load(BlizzardDataInputStream in) throws IOException { 58 | time = in.readInt(); 59 | emissionRate = in.readFloat(); 60 | if (interpolationType > 1) { 61 | inTan = in.readFloat(); 62 | outTan = in.readFloat(); 63 | } 64 | } 65 | 66 | public void save(BlizzardDataOutputStream out) throws IOException { 67 | out.writeInt(time); 68 | out.writeFloat(emissionRate); 69 | if (interpolationType > 1) { 70 | out.writeFloat(inTan); 71 | out.writeFloat(outTan); 72 | } 73 | 74 | } 75 | 76 | public int getSize() { 77 | int a = 0; 78 | a += 4; 79 | a += 4; 80 | if (interpolationType > 1) { 81 | a += 4; 82 | a += 4; 83 | } 84 | 85 | return a; 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/ParticleEmitter2Latitude.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class ParticleEmitter2Latitude { 8 | public int interpolationType; 9 | public int globalSequenceId; 10 | public ScalingTrack[] scalingTrack = new ScalingTrack[0]; 11 | 12 | public static final String key = "KP2L"; 13 | 14 | public void load(BlizzardDataInputStream in) throws IOException { 15 | StreamUtils.checkId(in, "KP2L"); 16 | int nrOfTracks = in.readInt(); 17 | interpolationType = in.readInt(); 18 | globalSequenceId = in.readInt(); 19 | scalingTrack = new ScalingTrack[nrOfTracks]; 20 | for (int i = 0; i < nrOfTracks; i++) { 21 | scalingTrack[i] = new ScalingTrack(); 22 | scalingTrack[i].load(in); 23 | } 24 | } 25 | 26 | public void save(BlizzardDataOutputStream out) throws IOException { 27 | int nrOfTracks = scalingTrack.length; 28 | out.writeNByteString("KP2L", 4); 29 | out.writeInt(nrOfTracks); 30 | out.writeInt(interpolationType); 31 | out.writeInt(globalSequenceId); 32 | for (int i = 0; i < scalingTrack.length; i++) { 33 | scalingTrack[i].save(out); 34 | } 35 | 36 | } 37 | 38 | public int getSize() { 39 | int a = 0; 40 | a += 4; 41 | a += 4; 42 | a += 4; 43 | a += 4; 44 | for (int i = 0; i < scalingTrack.length; i++) { 45 | a += scalingTrack[i].getSize(); 46 | } 47 | 48 | return a; 49 | } 50 | 51 | public class ScalingTrack { 52 | public int time; 53 | public float speed; 54 | public float inTan; 55 | public float outTan; 56 | 57 | public void load(BlizzardDataInputStream in) throws IOException { 58 | time = in.readInt(); 59 | speed = in.readFloat(); 60 | if (interpolationType > 1) { 61 | inTan = in.readFloat(); 62 | outTan = in.readFloat(); 63 | } 64 | } 65 | 66 | public void save(BlizzardDataOutputStream out) throws IOException { 67 | out.writeInt(time); 68 | out.writeFloat(speed); 69 | if (interpolationType > 1) { 70 | out.writeFloat(inTan); 71 | out.writeFloat(outTan); 72 | } 73 | 74 | } 75 | 76 | public int getSize() { 77 | int a = 0; 78 | a += 4; 79 | a += 4; 80 | if (interpolationType > 1) { 81 | a += 4; 82 | a += 4; 83 | } 84 | 85 | return a; 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/ParticleEmitter2Length.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class ParticleEmitter2Length { 8 | public int interpolationType; 9 | public int globalSequenceId; 10 | public ScalingTrack[] scalingTrack = new ScalingTrack[0]; 11 | 12 | public static final String key = "KP2N"; 13 | 14 | public void load(BlizzardDataInputStream in) throws IOException { 15 | StreamUtils.checkId(in, "KP2N"); 16 | int nrOfTracks = in.readInt(); 17 | interpolationType = in.readInt(); 18 | globalSequenceId = in.readInt(); 19 | scalingTrack = new ScalingTrack[nrOfTracks]; 20 | for (int i = 0; i < nrOfTracks; i++) { 21 | scalingTrack[i] = new ScalingTrack(); 22 | scalingTrack[i].load(in); 23 | } 24 | } 25 | 26 | public void save(BlizzardDataOutputStream out) throws IOException { 27 | int nrOfTracks = scalingTrack.length; 28 | out.writeNByteString("KP2N", 4); 29 | out.writeInt(nrOfTracks); 30 | out.writeInt(interpolationType); 31 | out.writeInt(globalSequenceId); 32 | for (int i = 0; i < scalingTrack.length; i++) { 33 | scalingTrack[i].save(out); 34 | } 35 | 36 | } 37 | 38 | public int getSize() { 39 | int a = 0; 40 | a += 4; 41 | a += 4; 42 | a += 4; 43 | a += 4; 44 | for (int i = 0; i < scalingTrack.length; i++) { 45 | a += scalingTrack[i].getSize(); 46 | } 47 | 48 | return a; 49 | } 50 | 51 | public class ScalingTrack { 52 | public int time; 53 | public float length; 54 | public float inTan; 55 | public float outTan; 56 | 57 | public void load(BlizzardDataInputStream in) throws IOException { 58 | time = in.readInt(); 59 | length = in.readFloat(); 60 | if (interpolationType > 1) { 61 | inTan = in.readFloat(); 62 | outTan = in.readFloat(); 63 | } 64 | } 65 | 66 | public void save(BlizzardDataOutputStream out) throws IOException { 67 | out.writeInt(time); 68 | out.writeFloat(length); 69 | if (interpolationType > 1) { 70 | out.writeFloat(inTan); 71 | out.writeFloat(outTan); 72 | } 73 | 74 | } 75 | 76 | public int getSize() { 77 | int a = 0; 78 | a += 4; 79 | a += 4; 80 | if (interpolationType > 1) { 81 | a += 4; 82 | a += 4; 83 | } 84 | 85 | return a; 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/ParticleEmitter2Speed.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class ParticleEmitter2Speed { 8 | public int interpolationType; 9 | public int globalSequenceId; 10 | public ScalingTrack[] scalingTrack = new ScalingTrack[0]; 11 | 12 | public static final String key = "KP2S"; 13 | 14 | public void load(BlizzardDataInputStream in) throws IOException { 15 | StreamUtils.checkId(in, "KP2S"); 16 | int nrOfTracks = in.readInt(); 17 | interpolationType = in.readInt(); 18 | globalSequenceId = in.readInt(); 19 | scalingTrack = new ScalingTrack[nrOfTracks]; 20 | for (int i = 0; i < nrOfTracks; i++) { 21 | scalingTrack[i] = new ScalingTrack(); 22 | scalingTrack[i].load(in); 23 | } 24 | } 25 | 26 | public void save(BlizzardDataOutputStream out) throws IOException { 27 | int nrOfTracks = scalingTrack.length; 28 | out.writeNByteString("KP2S", 4); 29 | out.writeInt(nrOfTracks); 30 | out.writeInt(interpolationType); 31 | out.writeInt(globalSequenceId); 32 | for (int i = 0; i < scalingTrack.length; i++) { 33 | scalingTrack[i].save(out); 34 | } 35 | 36 | } 37 | 38 | public int getSize() { 39 | int a = 0; 40 | a += 4; 41 | a += 4; 42 | a += 4; 43 | a += 4; 44 | for (int i = 0; i < scalingTrack.length; i++) { 45 | a += scalingTrack[i].getSize(); 46 | } 47 | 48 | return a; 49 | } 50 | 51 | public class ScalingTrack { 52 | public int time; 53 | public float speed; 54 | public float inTan; 55 | public float outTan; 56 | 57 | public void load(BlizzardDataInputStream in) throws IOException { 58 | time = in.readInt(); 59 | speed = in.readFloat(); 60 | if (interpolationType > 1) { 61 | inTan = in.readFloat(); 62 | outTan = in.readFloat(); 63 | } 64 | } 65 | 66 | public void save(BlizzardDataOutputStream out) throws IOException { 67 | out.writeInt(time); 68 | out.writeFloat(speed); 69 | if (interpolationType > 1) { 70 | out.writeFloat(inTan); 71 | out.writeFloat(outTan); 72 | } 73 | 74 | } 75 | 76 | public int getSize() { 77 | int a = 0; 78 | a += 4; 79 | a += 4; 80 | if (interpolationType > 1) { 81 | a += 4; 82 | a += 4; 83 | } 84 | 85 | return a; 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/ParticleEmitter2Visibility.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class ParticleEmitter2Visibility { 8 | public int interpolationType; 9 | public int globalSequenceId; 10 | public ScalingTrack[] scalingTrack = new ScalingTrack[0]; 11 | 12 | public static final String key = "KP2V"; 13 | 14 | public void load(BlizzardDataInputStream in) throws IOException { 15 | StreamUtils.checkId(in, "KP2V"); 16 | int nrOfTracks = in.readInt(); 17 | interpolationType = in.readInt(); 18 | globalSequenceId = in.readInt(); 19 | scalingTrack = new ScalingTrack[nrOfTracks]; 20 | for (int i = 0; i < nrOfTracks; i++) { 21 | scalingTrack[i] = new ScalingTrack(); 22 | scalingTrack[i].load(in); 23 | } 24 | } 25 | 26 | public void save(BlizzardDataOutputStream out) throws IOException { 27 | int nrOfTracks = scalingTrack.length; 28 | out.writeNByteString("KP2V", 4); 29 | out.writeInt(nrOfTracks); 30 | out.writeInt(interpolationType); 31 | out.writeInt(globalSequenceId); 32 | for (int i = 0; i < scalingTrack.length; i++) { 33 | scalingTrack[i].save(out); 34 | } 35 | 36 | } 37 | 38 | public int getSize() { 39 | int a = 0; 40 | a += 4; 41 | a += 4; 42 | a += 4; 43 | a += 4; 44 | for (int i = 0; i < scalingTrack.length; i++) { 45 | a += scalingTrack[i].getSize(); 46 | } 47 | 48 | return a; 49 | } 50 | 51 | public class ScalingTrack { 52 | public int time; 53 | public float visibility; 54 | public float inTan; 55 | public float outTan; 56 | 57 | public void load(BlizzardDataInputStream in) throws IOException { 58 | time = in.readInt(); 59 | visibility = in.readFloat(); 60 | if (interpolationType > 1) { 61 | inTan = in.readFloat(); 62 | outTan = in.readFloat(); 63 | } 64 | } 65 | 66 | public void save(BlizzardDataOutputStream out) throws IOException { 67 | out.writeInt(time); 68 | out.writeFloat(visibility); 69 | if (interpolationType > 1) { 70 | out.writeFloat(inTan); 71 | out.writeFloat(outTan); 72 | } 73 | 74 | } 75 | 76 | public int getSize() { 77 | int a = 0; 78 | a += 4; 79 | a += 4; 80 | if (interpolationType > 1) { 81 | a += 4; 82 | a += 4; 83 | } 84 | 85 | return a; 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/ParticleEmitter2Width.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class ParticleEmitter2Width { 8 | public int interpolationType; 9 | public int globalSequenceId; 10 | public ScalingTrack[] scalingTrack = new ScalingTrack[0]; 11 | 12 | public static final String key = "KP2W"; 13 | 14 | public void load(BlizzardDataInputStream in) throws IOException { 15 | StreamUtils.checkId(in, "KP2W"); 16 | int nrOfTracks = in.readInt(); 17 | interpolationType = in.readInt(); 18 | globalSequenceId = in.readInt(); 19 | scalingTrack = new ScalingTrack[nrOfTracks]; 20 | for (int i = 0; i < nrOfTracks; i++) { 21 | scalingTrack[i] = new ScalingTrack(); 22 | scalingTrack[i].load(in); 23 | } 24 | } 25 | 26 | public void save(BlizzardDataOutputStream out) throws IOException { 27 | int nrOfTracks = scalingTrack.length; 28 | out.writeNByteString("KP2W", 4); 29 | out.writeInt(nrOfTracks); 30 | out.writeInt(interpolationType); 31 | out.writeInt(globalSequenceId); 32 | for (int i = 0; i < scalingTrack.length; i++) { 33 | scalingTrack[i].save(out); 34 | } 35 | 36 | } 37 | 38 | public int getSize() { 39 | int a = 0; 40 | a += 4; 41 | a += 4; 42 | a += 4; 43 | a += 4; 44 | for (int i = 0; i < scalingTrack.length; i++) { 45 | a += scalingTrack[i].getSize(); 46 | } 47 | 48 | return a; 49 | } 50 | 51 | public class ScalingTrack { 52 | public int time; 53 | public float width; 54 | public float inTan; 55 | public float outTan; 56 | 57 | public void load(BlizzardDataInputStream in) throws IOException { 58 | time = in.readInt(); 59 | width = in.readFloat(); 60 | if (interpolationType > 1) { 61 | inTan = in.readFloat(); 62 | outTan = in.readFloat(); 63 | } 64 | } 65 | 66 | public void save(BlizzardDataOutputStream out) throws IOException { 67 | out.writeInt(time); 68 | out.writeFloat(width); 69 | if (interpolationType > 1) { 70 | out.writeFloat(inTan); 71 | out.writeFloat(outTan); 72 | } 73 | 74 | } 75 | 76 | public int getSize() { 77 | int a = 0; 78 | a += 4; 79 | a += 4; 80 | if (interpolationType > 1) { 81 | a += 4; 82 | a += 4; 83 | } 84 | 85 | return a; 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/ParticleEmitterChunk.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class ParticleEmitterChunk { 8 | public ParticleEmitter[] particleEmitter = new ParticleEmitter[0]; 9 | 10 | public static final String key = "PREM"; 11 | 12 | public void load(BlizzardDataInputStream in) throws IOException { 13 | StreamUtils.checkId(in, "PREM"); 14 | int chunkSize = in.readInt(); 15 | List particleEmitterList = new ArrayList(); 16 | int particleEmitterCounter = chunkSize; 17 | while (particleEmitterCounter > 0) { 18 | ParticleEmitter tempparticleEmitter = new ParticleEmitter(); 19 | particleEmitterList.add(tempparticleEmitter); 20 | tempparticleEmitter.load(in); 21 | particleEmitterCounter -= tempparticleEmitter.getSize(); 22 | } 23 | particleEmitter = particleEmitterList 24 | .toArray(new ParticleEmitter[particleEmitterList.size()]); 25 | } 26 | 27 | public void save(BlizzardDataOutputStream out) throws IOException { 28 | int nrOfParticleEmitters = particleEmitter.length; 29 | out.writeNByteString("PREM", 4); 30 | out.writeInt(getSize() - 8);// ChunkSize 31 | for (int i = 0; i < particleEmitter.length; i++) { 32 | particleEmitter[i].save(out); 33 | } 34 | 35 | } 36 | 37 | public int getSize() { 38 | int a = 0; 39 | a += 4; 40 | a += 4; 41 | for (int i = 0; i < particleEmitter.length; i++) { 42 | a += particleEmitter[i].getSize(); 43 | } 44 | 45 | return a; 46 | } 47 | 48 | public class ParticleEmitter { 49 | public Node node = new Node(); 50 | public float emissionRate; 51 | public float gravity; 52 | public float longitude; 53 | public float latitude; 54 | public String spawnModelFileName = ""; 55 | public int unknownNull; 56 | public float lifeSpan; 57 | public float initialVelocity; 58 | public ParticleEmitterVisibility particleEmitterVisibility; 59 | 60 | public void load(BlizzardDataInputStream in) throws IOException { 61 | int inclusiveSize = in.readInt(); 62 | node = new Node(); 63 | node.load(in); 64 | emissionRate = in.readFloat(); 65 | gravity = in.readFloat(); 66 | longitude = in.readFloat(); 67 | latitude = in.readFloat(); 68 | spawnModelFileName = in.readCharsAsString(256); 69 | unknownNull = in.readInt(); 70 | lifeSpan = in.readFloat(); 71 | initialVelocity = in.readFloat(); 72 | if (StreamUtils.checkOptionalId(in, particleEmitterVisibility.key)) { 73 | particleEmitterVisibility = new ParticleEmitterVisibility(); 74 | particleEmitterVisibility.load(in); 75 | } 76 | 77 | } 78 | 79 | public void save(BlizzardDataOutputStream out) throws IOException { 80 | out.writeInt(getSize());// InclusiveSize 81 | node.save(out); 82 | out.writeFloat(emissionRate); 83 | out.writeFloat(gravity); 84 | out.writeFloat(longitude); 85 | out.writeFloat(latitude); 86 | out.writeNByteString(spawnModelFileName, 256); 87 | out.writeInt(unknownNull); 88 | out.writeFloat(lifeSpan); 89 | out.writeFloat(initialVelocity); 90 | if (particleEmitterVisibility != null) { 91 | particleEmitterVisibility.save(out); 92 | } 93 | 94 | } 95 | 96 | public int getSize() { 97 | int a = 0; 98 | a += 4; 99 | a += node.getSize(); 100 | a += 4; 101 | a += 4; 102 | a += 4; 103 | a += 4; 104 | a += 256; 105 | a += 4; 106 | a += 4; 107 | a += 4; 108 | if (particleEmitterVisibility != null) { 109 | a += particleEmitterVisibility.getSize(); 110 | } 111 | 112 | return a; 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/ParticleEmitterVisibility.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class ParticleEmitterVisibility { 8 | public int interpolationType; 9 | public int globalSequenceId; 10 | public ScalingTrack[] scalingTrack = new ScalingTrack[0]; 11 | 12 | public static final String key = "KPEV"; 13 | 14 | public void load(BlizzardDataInputStream in) throws IOException { 15 | StreamUtils.checkId(in, "KPEV"); 16 | int nrOfTracks = in.readInt(); 17 | interpolationType = in.readInt(); 18 | globalSequenceId = in.readInt(); 19 | scalingTrack = new ScalingTrack[nrOfTracks]; 20 | for (int i = 0; i < nrOfTracks; i++) { 21 | scalingTrack[i] = new ScalingTrack(); 22 | scalingTrack[i].load(in); 23 | } 24 | } 25 | 26 | public void save(BlizzardDataOutputStream out) throws IOException { 27 | int nrOfTracks = scalingTrack.length; 28 | out.writeNByteString("KPEV", 4); 29 | out.writeInt(nrOfTracks); 30 | out.writeInt(interpolationType); 31 | out.writeInt(globalSequenceId); 32 | for (int i = 0; i < scalingTrack.length; i++) { 33 | scalingTrack[i].save(out); 34 | } 35 | 36 | } 37 | 38 | public int getSize() { 39 | int a = 0; 40 | a += 4; 41 | a += 4; 42 | a += 4; 43 | a += 4; 44 | for (int i = 0; i < scalingTrack.length; i++) { 45 | a += scalingTrack[i].getSize(); 46 | } 47 | 48 | return a; 49 | } 50 | 51 | public class ScalingTrack { 52 | public int time; 53 | public float visibility; 54 | public float inTan; 55 | public float outTan; 56 | 57 | public void load(BlizzardDataInputStream in) throws IOException { 58 | time = in.readInt(); 59 | visibility = in.readFloat(); 60 | if (interpolationType > 1) { 61 | inTan = in.readFloat(); 62 | outTan = in.readFloat(); 63 | } 64 | } 65 | 66 | public void save(BlizzardDataOutputStream out) throws IOException { 67 | out.writeInt(time); 68 | out.writeFloat(visibility); 69 | if (interpolationType > 1) { 70 | out.writeFloat(inTan); 71 | out.writeFloat(outTan); 72 | } 73 | 74 | } 75 | 76 | public int getSize() { 77 | int a = 0; 78 | a += 4; 79 | a += 4; 80 | if (interpolationType > 1) { 81 | a += 4; 82 | a += 4; 83 | } 84 | 85 | return a; 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/PivotPointChunk.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class PivotPointChunk { 8 | public float[] pivotPoints = new float[0]; 9 | 10 | public static final String key = "PIVT"; 11 | 12 | public void load(BlizzardDataInputStream in) throws IOException { 13 | StreamUtils.checkId(in, "PIVT"); 14 | int chunkSize = in.readInt(); 15 | pivotPoints = StreamUtils.loadFloatArray(in, chunkSize / 4); 16 | } 17 | 18 | public void save(BlizzardDataOutputStream out) throws IOException { 19 | int nrOfPivotPoints = pivotPoints.length / 3; 20 | out.writeNByteString("PIVT", 4); 21 | out.writeInt(getSize() - 8);// ChunkSize 22 | if (pivotPoints.length % 3 != 0) { 23 | throw new IllegalArgumentException( 24 | "The array pivotPoints needs either the length 3 or a multiple of this number. (got " 25 | + pivotPoints.length + ")"); 26 | } 27 | StreamUtils.saveFloatArray(out, pivotPoints); 28 | 29 | } 30 | 31 | public int getSize() { 32 | int a = 0; 33 | a += 4; 34 | a += 4; 35 | a += 4 * pivotPoints.length; 36 | 37 | return a; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/RibbonEmitterChunk.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class RibbonEmitterChunk { 8 | public RibbonEmitter[] ribbonEmitter = new RibbonEmitter[0]; 9 | 10 | public static final String key = "RIBB"; 11 | 12 | public void load(BlizzardDataInputStream in) throws IOException { 13 | StreamUtils.checkId(in, "RIBB"); 14 | int chunkSize = in.readInt(); 15 | List ribbonEmitterList = new ArrayList(); 16 | int ribbonEmitterCounter = chunkSize; 17 | while (ribbonEmitterCounter > 0) { 18 | RibbonEmitter tempribbonEmitter = new RibbonEmitter(); 19 | ribbonEmitterList.add(tempribbonEmitter); 20 | tempribbonEmitter.load(in); 21 | ribbonEmitterCounter -= tempribbonEmitter.getSize(); 22 | } 23 | ribbonEmitter = ribbonEmitterList 24 | .toArray(new RibbonEmitter[ribbonEmitterList.size()]); 25 | } 26 | 27 | public void save(BlizzardDataOutputStream out) throws IOException { 28 | int nrOfRibbonEmitters = ribbonEmitter.length; 29 | out.writeNByteString("RIBB", 4); 30 | out.writeInt(getSize() - 8);// ChunkSize 31 | for (int i = 0; i < ribbonEmitter.length; i++) { 32 | ribbonEmitter[i].save(out); 33 | } 34 | 35 | } 36 | 37 | public int getSize() { 38 | int a = 0; 39 | a += 4; 40 | a += 4; 41 | for (int i = 0; i < ribbonEmitter.length; i++) { 42 | a += ribbonEmitter[i].getSize(); 43 | } 44 | 45 | return a; 46 | } 47 | 48 | public class RibbonEmitter { 49 | public Node node = new Node(); 50 | public float heightAbove; 51 | public float heightBelow; 52 | public float alpha; 53 | public float[] color = new float[3]; 54 | public float lifeSpan; 55 | public int unknownNull; 56 | public int emissionRate; 57 | public int rows; 58 | public int columns; 59 | public int materialId; 60 | public float gravity; 61 | public RibbonEmitterVisibility ribbonEmitterVisibility; 62 | public RibbonEmitterHeightAbove ribbonEmitterHeightAbove; 63 | public RibbonEmitterHeightBelow ribbonEmitterHeightBelow; 64 | 65 | public void load(BlizzardDataInputStream in) throws IOException { 66 | int inclusiveSize = in.readInt(); 67 | node = new Node(); 68 | node.load(in); 69 | heightAbove = in.readFloat(); 70 | heightBelow = in.readFloat(); 71 | alpha = in.readFloat(); 72 | color = StreamUtils.loadFloatArray(in, 3); 73 | lifeSpan = in.readFloat(); 74 | unknownNull = in.readInt(); 75 | emissionRate = in.readInt(); 76 | rows = in.readInt(); 77 | columns = in.readInt(); 78 | materialId = in.readInt(); 79 | gravity = in.readFloat(); 80 | for (int i = 0; i < 3; i++) { 81 | if (StreamUtils.checkOptionalId(in, ribbonEmitterVisibility.key)) { 82 | ribbonEmitterVisibility = new RibbonEmitterVisibility(); 83 | ribbonEmitterVisibility.load(in); 84 | } else if (StreamUtils.checkOptionalId(in, 85 | ribbonEmitterHeightAbove.key)) { 86 | ribbonEmitterHeightAbove = new RibbonEmitterHeightAbove(); 87 | ribbonEmitterHeightAbove.load(in); 88 | } else if (StreamUtils.checkOptionalId(in, 89 | ribbonEmitterHeightBelow.key)) { 90 | ribbonEmitterHeightBelow = new RibbonEmitterHeightBelow(); 91 | ribbonEmitterHeightBelow.load(in); 92 | } 93 | 94 | } 95 | } 96 | 97 | public void save(BlizzardDataOutputStream out) throws IOException { 98 | out.writeInt(getSize());// InclusiveSize 99 | node.save(out); 100 | out.writeFloat(heightAbove); 101 | out.writeFloat(heightBelow); 102 | out.writeFloat(alpha); 103 | if (color.length % 3 != 0) { 104 | throw new IllegalArgumentException( 105 | "The array color needs either the length 3 or a multiple of this number. (got " 106 | + color.length + ")"); 107 | } 108 | StreamUtils.saveFloatArray(out, color); 109 | out.writeFloat(lifeSpan); 110 | out.writeInt(unknownNull); 111 | out.writeInt(emissionRate); 112 | out.writeInt(rows); 113 | out.writeInt(columns); 114 | out.writeInt(materialId); 115 | out.writeFloat(gravity); 116 | if (ribbonEmitterVisibility != null) { 117 | ribbonEmitterVisibility.save(out); 118 | } 119 | if (ribbonEmitterHeightAbove != null) { 120 | ribbonEmitterHeightAbove.save(out); 121 | } 122 | if (ribbonEmitterHeightBelow != null) { 123 | ribbonEmitterHeightBelow.save(out); 124 | } 125 | 126 | } 127 | 128 | public int getSize() { 129 | int a = 0; 130 | a += 4; 131 | a += node.getSize(); 132 | a += 4; 133 | a += 4; 134 | a += 4; 135 | a += 12; 136 | a += 4; 137 | a += 4; 138 | a += 4; 139 | a += 4; 140 | a += 4; 141 | a += 4; 142 | a += 4; 143 | if (ribbonEmitterVisibility != null) { 144 | a += ribbonEmitterVisibility.getSize(); 145 | } 146 | if (ribbonEmitterHeightAbove != null) { 147 | a += ribbonEmitterHeightAbove.getSize(); 148 | } 149 | if (ribbonEmitterHeightBelow != null) { 150 | a += ribbonEmitterHeightBelow.getSize(); 151 | } 152 | 153 | return a; 154 | } 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/RibbonEmitterHeightAbove.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class RibbonEmitterHeightAbove { 8 | public int interpolationType; 9 | public int globalSequenceId; 10 | public ScalingTrack[] scalingTrack = new ScalingTrack[0]; 11 | 12 | public static final String key = "KRHA"; 13 | 14 | public void load(BlizzardDataInputStream in) throws IOException { 15 | StreamUtils.checkId(in, "KRHA"); 16 | int nrOfTracks = in.readInt(); 17 | interpolationType = in.readInt(); 18 | globalSequenceId = in.readInt(); 19 | scalingTrack = new ScalingTrack[nrOfTracks]; 20 | for (int i = 0; i < nrOfTracks; i++) { 21 | scalingTrack[i] = new ScalingTrack(); 22 | scalingTrack[i].load(in); 23 | } 24 | } 25 | 26 | public void save(BlizzardDataOutputStream out) throws IOException { 27 | int nrOfTracks = scalingTrack.length; 28 | out.writeNByteString("KRHA", 4); 29 | out.writeInt(nrOfTracks); 30 | out.writeInt(interpolationType); 31 | out.writeInt(globalSequenceId); 32 | for (int i = 0; i < scalingTrack.length; i++) { 33 | scalingTrack[i].save(out); 34 | } 35 | 36 | } 37 | 38 | public int getSize() { 39 | int a = 0; 40 | a += 4; 41 | a += 4; 42 | a += 4; 43 | a += 4; 44 | for (int i = 0; i < scalingTrack.length; i++) { 45 | a += scalingTrack[i].getSize(); 46 | } 47 | 48 | return a; 49 | } 50 | 51 | public class ScalingTrack { 52 | public int time; 53 | public float heightAbove; 54 | public float inTan; 55 | public float outTan; 56 | 57 | public void load(BlizzardDataInputStream in) throws IOException { 58 | time = in.readInt(); 59 | heightAbove = in.readFloat(); 60 | if (interpolationType > 1) { 61 | inTan = in.readFloat(); 62 | outTan = in.readFloat(); 63 | } 64 | } 65 | 66 | public void save(BlizzardDataOutputStream out) throws IOException { 67 | out.writeInt(time); 68 | out.writeFloat(heightAbove); 69 | if (interpolationType > 1) { 70 | out.writeFloat(inTan); 71 | out.writeFloat(outTan); 72 | } 73 | 74 | } 75 | 76 | public int getSize() { 77 | int a = 0; 78 | a += 4; 79 | a += 4; 80 | if (interpolationType > 1) { 81 | a += 4; 82 | a += 4; 83 | } 84 | 85 | return a; 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/RibbonEmitterHeightBelow.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class RibbonEmitterHeightBelow { 8 | public int interpolationType; 9 | public int globalSequenceId; 10 | public ScalingTrack[] scalingTrack = new ScalingTrack[0]; 11 | 12 | public static final String key = "KRHB"; 13 | 14 | public void load(BlizzardDataInputStream in) throws IOException { 15 | StreamUtils.checkId(in, "KRHB"); 16 | int nrOfTracks = in.readInt(); 17 | interpolationType = in.readInt(); 18 | globalSequenceId = in.readInt(); 19 | scalingTrack = new ScalingTrack[nrOfTracks]; 20 | for (int i = 0; i < nrOfTracks; i++) { 21 | scalingTrack[i] = new ScalingTrack(); 22 | scalingTrack[i].load(in); 23 | } 24 | } 25 | 26 | public void save(BlizzardDataOutputStream out) throws IOException { 27 | int nrOfTracks = scalingTrack.length; 28 | out.writeNByteString("KRHB", 4); 29 | out.writeInt(nrOfTracks); 30 | out.writeInt(interpolationType); 31 | out.writeInt(globalSequenceId); 32 | for (int i = 0; i < scalingTrack.length; i++) { 33 | scalingTrack[i].save(out); 34 | } 35 | 36 | } 37 | 38 | public int getSize() { 39 | int a = 0; 40 | a += 4; 41 | a += 4; 42 | a += 4; 43 | a += 4; 44 | for (int i = 0; i < scalingTrack.length; i++) { 45 | a += scalingTrack[i].getSize(); 46 | } 47 | 48 | return a; 49 | } 50 | 51 | public class ScalingTrack { 52 | public int time; 53 | public float heightBelow; 54 | public float inTan; 55 | public float outTan; 56 | 57 | public void load(BlizzardDataInputStream in) throws IOException { 58 | time = in.readInt(); 59 | heightBelow = in.readFloat(); 60 | if (interpolationType > 1) { 61 | inTan = in.readFloat(); 62 | outTan = in.readFloat(); 63 | } 64 | } 65 | 66 | public void save(BlizzardDataOutputStream out) throws IOException { 67 | out.writeInt(time); 68 | out.writeFloat(heightBelow); 69 | if (interpolationType > 1) { 70 | out.writeFloat(inTan); 71 | out.writeFloat(outTan); 72 | } 73 | 74 | } 75 | 76 | public int getSize() { 77 | int a = 0; 78 | a += 4; 79 | a += 4; 80 | if (interpolationType > 1) { 81 | a += 4; 82 | a += 4; 83 | } 84 | 85 | return a; 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/RibbonEmitterVisibility.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class RibbonEmitterVisibility { 8 | public int interpolationType; 9 | public int globalSequenceId; 10 | public ScalingTrack[] scalingTrack = new ScalingTrack[0]; 11 | 12 | public static final String key = "KRVS"; 13 | 14 | public void load(BlizzardDataInputStream in) throws IOException { 15 | StreamUtils.checkId(in, "KRVS"); 16 | int nrOfTracks = in.readInt(); 17 | interpolationType = in.readInt(); 18 | globalSequenceId = in.readInt(); 19 | scalingTrack = new ScalingTrack[nrOfTracks]; 20 | for (int i = 0; i < nrOfTracks; i++) { 21 | scalingTrack[i] = new ScalingTrack(); 22 | scalingTrack[i].load(in); 23 | } 24 | } 25 | 26 | public void save(BlizzardDataOutputStream out) throws IOException { 27 | int nrOfTracks = scalingTrack.length; 28 | out.writeNByteString("KRVS", 4); 29 | out.writeInt(nrOfTracks); 30 | out.writeInt(interpolationType); 31 | out.writeInt(globalSequenceId); 32 | for (int i = 0; i < scalingTrack.length; i++) { 33 | scalingTrack[i].save(out); 34 | } 35 | 36 | } 37 | 38 | public int getSize() { 39 | int a = 0; 40 | a += 4; 41 | a += 4; 42 | a += 4; 43 | a += 4; 44 | for (int i = 0; i < scalingTrack.length; i++) { 45 | a += scalingTrack[i].getSize(); 46 | } 47 | 48 | return a; 49 | } 50 | 51 | public class ScalingTrack { 52 | public int time; 53 | public float visibility; 54 | public float inTan; 55 | public float outTan; 56 | 57 | public void load(BlizzardDataInputStream in) throws IOException { 58 | time = in.readInt(); 59 | visibility = in.readFloat(); 60 | if (interpolationType > 1) { 61 | inTan = in.readFloat(); 62 | outTan = in.readFloat(); 63 | } 64 | } 65 | 66 | public void save(BlizzardDataOutputStream out) throws IOException { 67 | out.writeInt(time); 68 | out.writeFloat(visibility); 69 | if (interpolationType > 1) { 70 | out.writeFloat(inTan); 71 | out.writeFloat(outTan); 72 | } 73 | 74 | } 75 | 76 | public int getSize() { 77 | int a = 0; 78 | a += 4; 79 | a += 4; 80 | if (interpolationType > 1) { 81 | a += 4; 82 | a += 4; 83 | } 84 | 85 | return a; 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/SequenceChunk.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class SequenceChunk { 8 | public Sequence[] sequence = new Sequence[0]; 9 | 10 | public static final String key = "SEQS"; 11 | 12 | public void load(BlizzardDataInputStream in) throws IOException { 13 | StreamUtils.checkId(in, "SEQS"); 14 | int chunkSize = in.readInt(); 15 | List sequenceList = new ArrayList(); 16 | int sequenceCounter = chunkSize; 17 | while (sequenceCounter > 0) { 18 | Sequence tempsequence = new Sequence(); 19 | sequenceList.add(tempsequence); 20 | tempsequence.load(in); 21 | sequenceCounter -= tempsequence.getSize(); 22 | } 23 | sequence = sequenceList.toArray(new Sequence[sequenceList.size()]); 24 | } 25 | 26 | public void save(BlizzardDataOutputStream out) throws IOException { 27 | int nrOfSequences = sequence.length; 28 | out.writeNByteString("SEQS", 4); 29 | out.writeInt(getSize() - 8);// ChunkSize 30 | for (int i = 0; i < sequence.length; i++) { 31 | sequence[i].save(out); 32 | } 33 | 34 | } 35 | 36 | public int getSize() { 37 | int a = 0; 38 | a += 4; 39 | a += 4; 40 | for (int i = 0; i < sequence.length; i++) { 41 | a += sequence[i].getSize(); 42 | } 43 | 44 | return a; 45 | } 46 | 47 | public class Sequence { 48 | public String name = ""; 49 | public int intervalStart; 50 | public int intervalEnd; 51 | public float moveSpeed; 52 | public int nonLooping; 53 | public float rarity; 54 | public int unknownNull; 55 | public float boundsRadius; 56 | public float[] minimumExtent = new float[3]; 57 | public float[] maximumExtent = new float[3]; 58 | 59 | public void load(BlizzardDataInputStream in) throws IOException { 60 | name = in.readCharsAsString(80); 61 | intervalStart = in.readInt(); 62 | intervalEnd = in.readInt(); 63 | moveSpeed = in.readFloat(); 64 | nonLooping = in.readInt(); 65 | rarity = in.readFloat(); 66 | unknownNull = in.readInt(); 67 | boundsRadius = in.readFloat(); 68 | minimumExtent = StreamUtils.loadFloatArray(in, 3); 69 | maximumExtent = StreamUtils.loadFloatArray(in, 3); 70 | } 71 | 72 | public void save(BlizzardDataOutputStream out) throws IOException { 73 | out.writeNByteString(name, 80); 74 | out.writeInt(intervalStart); 75 | out.writeInt(intervalEnd); 76 | out.writeFloat(moveSpeed); 77 | out.writeInt(nonLooping); 78 | out.writeFloat(rarity); 79 | out.writeInt(unknownNull); 80 | out.writeFloat(boundsRadius); 81 | if (minimumExtent.length % 3 != 0) { 82 | throw new IllegalArgumentException( 83 | "The array minimumExtent needs either the length 3 or a multiple of this number. (got " 84 | + minimumExtent.length + ")"); 85 | } 86 | StreamUtils.saveFloatArray(out, minimumExtent); 87 | if (maximumExtent.length % 3 != 0) { 88 | throw new IllegalArgumentException( 89 | "The array maximumExtent needs either the length 3 or a multiple of this number. (got " 90 | + maximumExtent.length + ")"); 91 | } 92 | StreamUtils.saveFloatArray(out, maximumExtent); 93 | 94 | } 95 | 96 | public int getSize() { 97 | int a = 0; 98 | a += 80; 99 | a += 4; 100 | a += 4; 101 | a += 4; 102 | a += 4; 103 | a += 4; 104 | a += 4; 105 | a += 4; 106 | a += 12; 107 | a += 12; 108 | 109 | return a; 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/TextureAnimationChunk.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class TextureAnimationChunk { 8 | public TextureAnimation[] textureAnimation = new TextureAnimation[0]; 9 | 10 | public static final String key = "TXAN"; 11 | 12 | public void load(BlizzardDataInputStream in) throws IOException { 13 | StreamUtils.checkId(in, "TXAN"); 14 | int chunkSize = in.readInt(); 15 | List textureAnimationList = new ArrayList(); 16 | int textureAnimationCounter = chunkSize; 17 | while (textureAnimationCounter > 0) { 18 | TextureAnimation temptextureAnimation = new TextureAnimation(); 19 | textureAnimationList.add(temptextureAnimation); 20 | temptextureAnimation.load(in); 21 | textureAnimationCounter -= temptextureAnimation.getSize(); 22 | } 23 | textureAnimation = textureAnimationList 24 | .toArray(new TextureAnimation[textureAnimationList.size()]); 25 | } 26 | 27 | public void save(BlizzardDataOutputStream out) throws IOException { 28 | int nrOfTextureAnimations = textureAnimation.length; 29 | out.writeNByteString("TXAN", 4); 30 | out.writeInt(getSize() - 8);// ChunkSize 31 | for (int i = 0; i < textureAnimation.length; i++) { 32 | textureAnimation[i].save(out); 33 | } 34 | 35 | } 36 | 37 | public int getSize() { 38 | int a = 0; 39 | a += 4; 40 | a += 4; 41 | for (int i = 0; i < textureAnimation.length; i++) { 42 | a += textureAnimation[i].getSize(); 43 | } 44 | 45 | return a; 46 | } 47 | 48 | public class TextureAnimation { 49 | public TextureTranslation textureTranslation; 50 | public TextureRotation textureRotation; 51 | public TextureScaling textureScaling; 52 | 53 | public void load(BlizzardDataInputStream in) throws IOException { 54 | int inclusiveSize = in.readInt(); 55 | for (int i = 0; i < 3; i++) { 56 | if (StreamUtils.checkOptionalId(in, textureTranslation.key)) { 57 | textureTranslation = new TextureTranslation(); 58 | textureTranslation.load(in); 59 | } else if (StreamUtils.checkOptionalId(in, textureRotation.key)) { 60 | textureRotation = new TextureRotation(); 61 | textureRotation.load(in); 62 | } else if (StreamUtils.checkOptionalId(in, textureScaling.key)) { 63 | textureScaling = new TextureScaling(); 64 | textureScaling.load(in); 65 | } 66 | 67 | } 68 | } 69 | 70 | public void save(BlizzardDataOutputStream out) throws IOException { 71 | out.writeInt(getSize());// InclusiveSize 72 | if (textureTranslation != null) { 73 | textureTranslation.save(out); 74 | } 75 | if (textureRotation != null) { 76 | textureRotation.save(out); 77 | } 78 | if (textureScaling != null) { 79 | textureScaling.save(out); 80 | } 81 | 82 | } 83 | 84 | public int getSize() { 85 | int a = 0; 86 | a += 4; 87 | if (textureTranslation != null) { 88 | a += textureTranslation.getSize(); 89 | } 90 | if (textureRotation != null) { 91 | a += textureRotation.getSize(); 92 | } 93 | if (textureScaling != null) { 94 | a += textureScaling.getSize(); 95 | } 96 | 97 | return a; 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/TextureChunk.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class TextureChunk { 8 | public Texture[] texture = new Texture[0]; 9 | 10 | public static final String key = "TEXS"; 11 | 12 | public void load(BlizzardDataInputStream in) throws IOException { 13 | StreamUtils.checkId(in, "TEXS"); 14 | int chunkSize = in.readInt(); 15 | List textureList = new ArrayList(); 16 | int textureCounter = chunkSize; 17 | while (textureCounter > 0) { 18 | Texture temptexture = new Texture(); 19 | textureList.add(temptexture); 20 | temptexture.load(in); 21 | textureCounter -= temptexture.getSize(); 22 | } 23 | texture = textureList.toArray(new Texture[textureList.size()]); 24 | } 25 | 26 | public void save(BlizzardDataOutputStream out) throws IOException { 27 | int nrOfTextures = texture.length; 28 | out.writeNByteString("TEXS", 4); 29 | out.writeInt(getSize() - 8);// ChunkSize 30 | for (int i = 0; i < texture.length; i++) { 31 | texture[i].save(out); 32 | } 33 | 34 | } 35 | 36 | public int getSize() { 37 | int a = 0; 38 | a += 4; 39 | a += 4; 40 | for (int i = 0; i < texture.length; i++) { 41 | a += texture[i].getSize(); 42 | } 43 | 44 | return a; 45 | } 46 | 47 | public class Texture { 48 | public int replaceableId; 49 | public String fileName = ""; 50 | public int unknownNull; 51 | public int flags; 52 | 53 | public void load(BlizzardDataInputStream in) throws IOException { 54 | replaceableId = in.readInt(); 55 | fileName = in.readCharsAsString(256); 56 | unknownNull = in.readInt(); 57 | flags = in.readInt(); 58 | } 59 | 60 | public void save(BlizzardDataOutputStream out) throws IOException { 61 | out.writeInt(replaceableId); 62 | out.writeNByteString(fileName, 256); 63 | out.writeInt(unknownNull); 64 | out.writeInt(flags); 65 | 66 | } 67 | 68 | public int getSize() { 69 | int a = 0; 70 | a += 4; 71 | a += 256; 72 | a += 4; 73 | a += 4; 74 | 75 | return a; 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/TextureRotation.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class TextureRotation { 8 | public int interpolationType; 9 | public int globalSequenceId; 10 | public TranslationTrack[] translationTrack = new TranslationTrack[0]; 11 | 12 | public static final String key = "KTAR"; 13 | 14 | public void load(BlizzardDataInputStream in) throws IOException { 15 | StreamUtils.checkId(in, "KTAR"); 16 | int nrOfTracks = in.readInt(); 17 | interpolationType = in.readInt(); 18 | globalSequenceId = in.readInt(); 19 | translationTrack = new TranslationTrack[nrOfTracks]; 20 | for (int i = 0; i < nrOfTracks; i++) { 21 | translationTrack[i] = new TranslationTrack(); 22 | translationTrack[i].load(in); 23 | } 24 | } 25 | 26 | public void save(BlizzardDataOutputStream out) throws IOException { 27 | int nrOfTracks = translationTrack.length; 28 | out.writeNByteString("KTAR", 4); 29 | out.writeInt(nrOfTracks); 30 | out.writeInt(interpolationType); 31 | out.writeInt(globalSequenceId); 32 | for (int i = 0; i < translationTrack.length; i++) { 33 | translationTrack[i].save(out); 34 | } 35 | 36 | } 37 | 38 | public int getSize() { 39 | int a = 0; 40 | a += 4; 41 | a += 4; 42 | a += 4; 43 | a += 4; 44 | for (int i = 0; i < translationTrack.length; i++) { 45 | a += translationTrack[i].getSize(); 46 | } 47 | 48 | return a; 49 | } 50 | 51 | public class TranslationTrack { 52 | public int time; 53 | public float[] rotation = new float[4]; 54 | public float[] inTan = new float[4]; 55 | public float[] outTan = new float[4]; 56 | 57 | public void load(BlizzardDataInputStream in) throws IOException { 58 | time = in.readInt(); 59 | rotation = StreamUtils.loadFloatArray(in, 4); 60 | if (interpolationType > 1) { 61 | inTan = StreamUtils.loadFloatArray(in, 4); 62 | outTan = StreamUtils.loadFloatArray(in, 4); 63 | } 64 | } 65 | 66 | public void save(BlizzardDataOutputStream out) throws IOException { 67 | out.writeInt(time); 68 | if (rotation.length % 4 != 0) { 69 | throw new IllegalArgumentException( 70 | "The array rotation needs either the length 4 or a multiple of this number. (got " 71 | + rotation.length + ")"); 72 | } 73 | StreamUtils.saveFloatArray(out, rotation); 74 | if (interpolationType > 1) { 75 | if (inTan.length % 4 != 0) { 76 | throw new IllegalArgumentException( 77 | "The array inTan needs either the length 4 or a multiple of this number. (got " 78 | + inTan.length + ")"); 79 | } 80 | StreamUtils.saveFloatArray(out, inTan); 81 | if (outTan.length % 4 != 0) { 82 | throw new IllegalArgumentException( 83 | "The array outTan needs either the length 4 or a multiple of this number. (got " 84 | + outTan.length + ")"); 85 | } 86 | StreamUtils.saveFloatArray(out, outTan); 87 | } 88 | 89 | } 90 | 91 | public int getSize() { 92 | int a = 0; 93 | a += 4; 94 | a += 16; 95 | if (interpolationType > 1) { 96 | a += 16; 97 | a += 16; 98 | } 99 | 100 | return a; 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/TextureScaling.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class TextureScaling { 8 | public int interpolationType; 9 | public int globalSequenceId; 10 | public TranslationTrack[] translationTrack = new TranslationTrack[0]; 11 | 12 | public static final String key = "KTAS"; 13 | 14 | public void load(BlizzardDataInputStream in) throws IOException { 15 | StreamUtils.checkId(in, "KTAS"); 16 | int nrOfTracks = in.readInt(); 17 | interpolationType = in.readInt(); 18 | globalSequenceId = in.readInt(); 19 | translationTrack = new TranslationTrack[nrOfTracks]; 20 | for (int i = 0; i < nrOfTracks; i++) { 21 | translationTrack[i] = new TranslationTrack(); 22 | translationTrack[i].load(in); 23 | } 24 | } 25 | 26 | public void save(BlizzardDataOutputStream out) throws IOException { 27 | int nrOfTracks = translationTrack.length; 28 | out.writeNByteString("KTAS", 4); 29 | out.writeInt(nrOfTracks); 30 | out.writeInt(interpolationType); 31 | out.writeInt(globalSequenceId); 32 | for (int i = 0; i < translationTrack.length; i++) { 33 | translationTrack[i].save(out); 34 | } 35 | 36 | } 37 | 38 | public int getSize() { 39 | int a = 0; 40 | a += 4; 41 | a += 4; 42 | a += 4; 43 | a += 4; 44 | for (int i = 0; i < translationTrack.length; i++) { 45 | a += translationTrack[i].getSize(); 46 | } 47 | 48 | return a; 49 | } 50 | 51 | public class TranslationTrack { 52 | public int time; 53 | public float[] scaling = new float[3]; 54 | public float[] inTan = new float[3]; 55 | public float[] outTan = new float[3]; 56 | 57 | public void load(BlizzardDataInputStream in) throws IOException { 58 | time = in.readInt(); 59 | scaling = StreamUtils.loadFloatArray(in, 3); 60 | if (interpolationType > 1) { 61 | inTan = StreamUtils.loadFloatArray(in, 3); 62 | outTan = StreamUtils.loadFloatArray(in, 3); 63 | } 64 | } 65 | 66 | public void save(BlizzardDataOutputStream out) throws IOException { 67 | out.writeInt(time); 68 | if (scaling.length % 3 != 0) { 69 | throw new IllegalArgumentException( 70 | "The array scaling needs either the length 3 or a multiple of this number. (got " 71 | + scaling.length + ")"); 72 | } 73 | StreamUtils.saveFloatArray(out, scaling); 74 | if (interpolationType > 1) { 75 | if (inTan.length % 3 != 0) { 76 | throw new IllegalArgumentException( 77 | "The array inTan needs either the length 3 or a multiple of this number. (got " 78 | + inTan.length + ")"); 79 | } 80 | StreamUtils.saveFloatArray(out, inTan); 81 | if (outTan.length % 3 != 0) { 82 | throw new IllegalArgumentException( 83 | "The array outTan needs either the length 3 or a multiple of this number. (got " 84 | + outTan.length + ")"); 85 | } 86 | StreamUtils.saveFloatArray(out, outTan); 87 | } 88 | 89 | } 90 | 91 | public int getSize() { 92 | int a = 0; 93 | a += 4; 94 | a += 12; 95 | if (interpolationType > 1) { 96 | a += 12; 97 | a += 12; 98 | } 99 | 100 | return a; 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/TextureTranslation.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class TextureTranslation { 8 | public int interpolationType; 9 | public int globalSequenceId; 10 | public TranslationTrack[] translationTrack = new TranslationTrack[0]; 11 | 12 | public static final String key = "KTAT"; 13 | 14 | public void load(BlizzardDataInputStream in) throws IOException { 15 | StreamUtils.checkId(in, "KTAT"); 16 | int nrOfTracks = in.readInt(); 17 | interpolationType = in.readInt(); 18 | globalSequenceId = in.readInt(); 19 | translationTrack = new TranslationTrack[nrOfTracks]; 20 | for (int i = 0; i < nrOfTracks; i++) { 21 | translationTrack[i] = new TranslationTrack(); 22 | translationTrack[i].load(in); 23 | } 24 | } 25 | 26 | public void save(BlizzardDataOutputStream out) throws IOException { 27 | int nrOfTracks = translationTrack.length; 28 | out.writeNByteString("KTAT", 4); 29 | out.writeInt(nrOfTracks); 30 | out.writeInt(interpolationType); 31 | out.writeInt(globalSequenceId); 32 | for (int i = 0; i < translationTrack.length; i++) { 33 | translationTrack[i].save(out); 34 | } 35 | 36 | } 37 | 38 | public int getSize() { 39 | int a = 0; 40 | a += 4; 41 | a += 4; 42 | a += 4; 43 | a += 4; 44 | for (int i = 0; i < translationTrack.length; i++) { 45 | a += translationTrack[i].getSize(); 46 | } 47 | 48 | return a; 49 | } 50 | 51 | public class TranslationTrack { 52 | public int time; 53 | public float[] translation = new float[3]; 54 | public float[] inTan = new float[3]; 55 | public float[] outTan = new float[3]; 56 | 57 | public void load(BlizzardDataInputStream in) throws IOException { 58 | time = in.readInt(); 59 | translation = StreamUtils.loadFloatArray(in, 3); 60 | if (interpolationType > 1) { 61 | inTan = StreamUtils.loadFloatArray(in, 3); 62 | outTan = StreamUtils.loadFloatArray(in, 3); 63 | } 64 | } 65 | 66 | public void save(BlizzardDataOutputStream out) throws IOException { 67 | out.writeInt(time); 68 | if (translation.length % 3 != 0) { 69 | throw new IllegalArgumentException( 70 | "The array translation needs either the length 3 or a multiple of this number. (got " 71 | + translation.length + ")"); 72 | } 73 | StreamUtils.saveFloatArray(out, translation); 74 | if (interpolationType > 1) { 75 | if (inTan.length % 3 != 0) { 76 | throw new IllegalArgumentException( 77 | "The array inTan needs either the length 3 or a multiple of this number. (got " 78 | + inTan.length + ")"); 79 | } 80 | StreamUtils.saveFloatArray(out, inTan); 81 | if (outTan.length % 3 != 0) { 82 | throw new IllegalArgumentException( 83 | "The array outTan needs either the length 3 or a multiple of this number. (got " 84 | + outTan.length + ")"); 85 | } 86 | StreamUtils.saveFloatArray(out, outTan); 87 | } 88 | 89 | } 90 | 91 | public int getSize() { 92 | int a = 0; 93 | a += 4; 94 | a += 12; 95 | if (interpolationType > 1) { 96 | a += 12; 97 | a += 12; 98 | } 99 | 100 | return a; 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/Tracks.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class Tracks { 8 | public int globalSequenceId; 9 | public int[] tracks = new int[0]; 10 | 11 | public static final String key = "KEVT"; 12 | 13 | public void load(BlizzardDataInputStream in) throws IOException { 14 | StreamUtils.checkId(in, "KEVT"); 15 | int nrOfTracks = in.readInt(); 16 | globalSequenceId = in.readInt(); 17 | tracks = StreamUtils.loadIntArray(in, nrOfTracks); 18 | } 19 | 20 | public void save(BlizzardDataOutputStream out) throws IOException { 21 | int nrOfTracks = tracks.length; 22 | out.writeNByteString("KEVT", 4); 23 | out.writeInt(nrOfTracks); 24 | out.writeInt(globalSequenceId); 25 | StreamUtils.saveIntArray(out, tracks); 26 | 27 | } 28 | 29 | public int getSize() { 30 | int a = 0; 31 | a += 4; 32 | a += 4; 33 | a += 4; 34 | a += 4 * tracks.length; 35 | 36 | return a; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/de/wc3data/mdx/VersionChunk.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.mdx; 2 | 3 | import de.wc3data.stream.StreamUtils; 4 | import java.io.IOException; 5 | import java.util.*; 6 | 7 | public class VersionChunk { 8 | public int version; 9 | 10 | public static final String key = "VERS"; 11 | 12 | public void load(BlizzardDataInputStream in) throws IOException { 13 | StreamUtils.checkId(in, "VERS"); 14 | int chunkSize = in.readInt(); 15 | version = in.readInt(); 16 | } 17 | 18 | public void save(BlizzardDataOutputStream out) throws IOException { 19 | out.writeNByteString("VERS", 4); 20 | out.writeInt(getSize() - 8);// ChunkSize 21 | out.writeInt(version); 22 | 23 | } 24 | 25 | public int getSize() { 26 | int a = 0; 27 | a += 4; 28 | a += 4; 29 | a += 4; 30 | 31 | return a; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/de/wc3data/stream/BlizzardDataInputStream.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.stream; 2 | 3 | import java.io.BufferedInputStream; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.io.PrintStream; 7 | 8 | public class BlizzardDataInputStream 9 | extends BufferedInputStream { 10 | 11 | private long offset = 0L; 12 | 13 | public BlizzardDataInputStream(InputStream in) { 14 | super(in); 15 | } 16 | 17 | private static int convertToInt(byte[] b) { 18 | return b[0] & 0xFF 19 | | (b[1] & 0xFF) << 8 20 | | (b[2] & 0xFF) << 16 21 | | (b[3] & 0xFF) << 24; 22 | } 23 | 24 | private static int convertNToInt(byte[] b) { 25 | int result = 0; 26 | for (int i = 0; i < b.length; i++) { 27 | result |= (b[i] & 0xFF) << i * 8; 28 | } 29 | return result; 30 | } 31 | 32 | private static short convertToShort(byte[] b) { 33 | int result = 0; 34 | 35 | for (int i = 0; i < b.length; i++) { 36 | result |= (b[i] & 0xFF) << i * 8; 37 | } 38 | return (short) result; 39 | // return (short)(b[0] << 8 | b[1] & 0xFF); 40 | } 41 | 42 | /*public long skip(long count) 43 | throws IOException 44 | { 45 | System.out.println("Skipping: " + count); 46 | throw new Error("BDIS: skip is buggy!"); 47 | }*/ 48 | public long getOffset() { 49 | return this.offset; 50 | } 51 | 52 | public byte readByte() 53 | throws IOException { 54 | byte[] b = new byte[1]; 55 | this.offset += 1L; 56 | read(b); 57 | return b[0]; 58 | } 59 | 60 | public int read(byte[] b) 61 | throws IOException { 62 | this.offset += b.length; 63 | return super.read(b); 64 | } 65 | 66 | public void skipUntilZeroInt() 67 | throws IOException { 68 | int numZeroBytes = 0; 69 | for (;;) { 70 | this.offset += 1L; 71 | int readByte; 72 | if ((readByte = read()) == 0) { 73 | numZeroBytes++; 74 | if (numZeroBytes != 4) { 75 | } 76 | } else { 77 | if (readByte == -1) { 78 | return; 79 | } 80 | numZeroBytes = 0; 81 | } 82 | } 83 | } 84 | 85 | public short readShort() 86 | throws IOException { 87 | byte[] b = new byte[2]; 88 | this.offset += 2L; 89 | read(b, 0, 2); 90 | return convertToShort(b); 91 | } 92 | 93 | public int readInt() 94 | throws IOException { 95 | byte[] b = new byte[4]; 96 | this.offset += 4L; 97 | read(b, 0, 4); 98 | return convertToInt(b); 99 | } 100 | 101 | public int readNByteInt(int numBytes) 102 | throws IOException { 103 | byte[] b = new byte[numBytes]; 104 | this.offset += numBytes; 105 | read(b, 0, numBytes); 106 | return convertNToInt(b); 107 | } 108 | 109 | public boolean readBool() 110 | throws IOException { 111 | return readInt() == 1; 112 | } 113 | 114 | public float readFloat() 115 | throws IOException { 116 | return Float.intBitsToFloat(readInt()); 117 | } 118 | 119 | public char readChar() 120 | throws IOException { 121 | this.offset += 1L; 122 | return (char) read(); 123 | } 124 | 125 | public char[] readChars(int charCount) 126 | throws IOException { 127 | char[] c = new char[charCount]; 128 | for (int i = 0; i < charCount; i++) { 129 | c[i] = readChar(); 130 | } 131 | return c; 132 | } 133 | 134 | public String readCharsAsString(int charCount) 135 | throws IOException { 136 | char[] c = readChars(charCount); 137 | for (int i = 0; i < charCount; i++) { 138 | if (c[i] == 0) { 139 | return String.valueOf(c, 0, i); 140 | } 141 | } 142 | return String.valueOf(c); 143 | } 144 | 145 | public String readCharsAsStringCheckNull(int charCount) 146 | throws IOException { 147 | char[] result = readChars(charCount); 148 | boolean isNull = true; 149 | for (int i = 0; i < charCount; i++) { 150 | if (result[i] != 0) { 151 | isNull = false; 152 | } 153 | } 154 | if (isNull) { 155 | return null; 156 | } 157 | return String.valueOf(result); 158 | } 159 | 160 | public String readExportSig() 161 | throws IOException { 162 | char[] c = readChars(4); 163 | for (int i = 0; i < 4; i++) { 164 | if (c[i] == 65535) { 165 | return null; 166 | } 167 | } 168 | return String.valueOf(c); 169 | } 170 | 171 | public String readString() 172 | throws IOException { 173 | StringBuilder sb = new StringBuilder(16); 174 | int curVal = read(); 175 | while (curVal != 0) { 176 | if (curVal == -1) { 177 | return null; 178 | } 179 | sb.append((char) curVal); 180 | curVal = read(); 181 | this.offset += 1L; 182 | } 183 | this.offset += 1L; 184 | return sb.toString(); 185 | } 186 | 187 | public void close() 188 | throws IOException { 189 | this.in.close(); 190 | } 191 | } -------------------------------------------------------------------------------- /src/de/wc3data/stream/BlizzardDataOutputStream.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.stream; 2 | 3 | import java.io.BufferedOutputStream; 4 | import java.io.File; 5 | import java.io.FileNotFoundException; 6 | import java.io.FileOutputStream; 7 | import java.io.IOException; 8 | 9 | public class BlizzardDataOutputStream 10 | extends BufferedOutputStream { 11 | 12 | public BlizzardDataOutputStream(File file) 13 | throws FileNotFoundException { 14 | super(new FileOutputStream(file)); 15 | } 16 | 17 | public BlizzardDataOutputStream(File file, boolean append) 18 | throws FileNotFoundException { 19 | super(new FileOutputStream(file, append)); 20 | } 21 | 22 | static byte[] convertIntToByteArray(int i) { 23 | byte[] result = new byte[4]; 24 | long l = i >= 0 ? i : 4294967296L + i; 25 | for (int j = 0; j < 4; j++) { 26 | result[j] = ((byte) (int) (l % 256L)); 27 | l /= 256L; 28 | } 29 | return result; 30 | } 31 | 32 | static byte[] convertIntToNByteArray(int i, int numBytes) { 33 | byte[] result = new byte[numBytes]; 34 | long l = i >= 0 ? i : 4294967296L + i; 35 | for (int j = 0; j < numBytes; j++) { 36 | result[j] = ((byte) (int) (l % 256L)); 37 | l /= 256L; 38 | } 39 | return result; 40 | } 41 | 42 | public void writeChars(char[] toWrite) 43 | throws IOException { 44 | byte[] b = new byte[toWrite.length]; 45 | for (int i = 0; i < toWrite.length; i++) { 46 | b[i] = ((byte) toWrite[i]); 47 | } 48 | write(b); 49 | } 50 | 51 | public void writeInt(int toWrite) 52 | throws IOException { 53 | write(convertIntToByteArray(toWrite)); 54 | } 55 | 56 | public void writeNByteInt(int toWrite, int numBytes) 57 | throws IOException { 58 | write(convertIntToNByteArray(toWrite, numBytes)); 59 | } 60 | 61 | public void writeBool(boolean toWrite) 62 | throws IOException { 63 | writeInt(toWrite ? 1 : 0); 64 | } 65 | 66 | public void writeByte(int toWrite) 67 | throws IOException { 68 | write(new byte[]{(byte) toWrite}); 69 | } 70 | 71 | public void writeFloat(float toWrite) 72 | throws IOException { 73 | writeInt(Float.floatToIntBits(toWrite)); 74 | } 75 | 76 | public void writeFourByteString(String toWrite) 77 | throws IOException { 78 | byte[] result = new byte[4]; 79 | for (int i = 0; i < 4; i++) { 80 | if ((toWrite != null) && (i < toWrite.length())) { 81 | result[i] = ((byte) toWrite.charAt(i)); 82 | } else { 83 | result[i] = 0; 84 | } 85 | } 86 | write(result); 87 | } 88 | 89 | public void writeNByteString(String toWrite, int charCount) 90 | throws IOException { 91 | byte[] result = new byte[charCount]; 92 | for (int i = 0; i < charCount; i++) { 93 | if ((toWrite != null) && (i < toWrite.length())) { 94 | result[i] = ((byte) toWrite.charAt(i)); 95 | } else { 96 | result[i] = 0; 97 | } 98 | } 99 | write(result); 100 | } 101 | 102 | public void writeString(String toWrite) 103 | throws IOException { 104 | int length; 105 | if (toWrite == null) { 106 | length = 0; 107 | } else { 108 | length = toWrite.length(); 109 | } 110 | byte[] result = new byte[length + 1]; 111 | for (int i = 0; i < length; i++) { 112 | result[i] = ((byte) toWrite.charAt(i)); 113 | } 114 | result[length] = 0; 115 | write(result); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/de/wc3data/stream/StreamUtils.java: -------------------------------------------------------------------------------- 1 | package de.wc3data.stream; 2 | 3 | import de.wc3data.mdx.BlizzardDataInputStream; 4 | import de.wc3data.mdx.BlizzardDataOutputStream; 5 | import de.wc3data.mdx.MdxModel; 6 | import java.io.IOException; 7 | 8 | public class StreamUtils { 9 | 10 | /* 11 | * private static Set optionalPool = new HashSet(); 12 | * 13 | * public void addOptionalPool(MdxComponent component){ 14 | * optionalPool.add(component); } 15 | * 16 | * 17 | * public void executeOptionalPool(){ 18 | * 19 | * } 20 | */ 21 | 22 | public static MdxModel loadModel(BlizzardDataInputStream in) 23 | throws IOException { 24 | MdxModel model = new MdxModel(); 25 | model.load(in); 26 | return model; 27 | } 28 | 29 | public static boolean checkOptionalId(BlizzardDataInputStream in, 30 | String name) throws IOException { 31 | 32 | in.mark(8); 33 | 34 | if (name.equals(in.readCharsAsString(4))) { 35 | in.reset(); 36 | return true; 37 | } 38 | 39 | in.reset(); 40 | return false; 41 | } 42 | 43 | public static String readOptionalId(BlizzardDataInputStream in) throws IOException { 44 | in.mark(8); 45 | char[] c = in.readChars(4); 46 | in.reset(); 47 | 48 | int allEmpty = 0; 49 | for(int i = 0;i<4; i++){ 50 | if((short)c[0] == -1){ 51 | allEmpty++; 52 | } 53 | } 54 | 55 | if(allEmpty == 4){ 56 | return null; 57 | } 58 | 59 | return ""+c[0] + c[1]+ c[2]+ c[3]; 60 | } 61 | 62 | public static void checkId(BlizzardDataInputStream in, String name) 63 | throws IOException { 64 | String found = in.readCharsAsString(4); 65 | if (!found.equals(name)) { 66 | throw new IOException( 67 | "Error loading model: CheckID failed, required " + name 68 | + " found " + found); 69 | } 70 | } 71 | 72 | /* 73 | * public static boolean checkOptionalId(BlizzardDataInputStream in, String 74 | * name) throws IOException { if(lastCheck == null){ lastCheck = 75 | * in.readCharsAsString(4); } 76 | * 77 | * return lastCheck.equals(name); } 78 | * 79 | * public static void checkId(BlizzardDataInputStream in, String name) 80 | * throws IOException { 81 | * 82 | * if(lastCheck != null){ 83 | * 84 | * if(!name.equals(lastCheck)){ throw new IOException( 85 | * "Error loading model: CheckID failed after optinal check, required " + 86 | * name + " found " + lastCheck); } 87 | * 88 | * lastCheck=null; 89 | * 90 | * }else{ 91 | * 92 | * String found = in.readCharsAsString(4); if (!found.equals(name)) { throw 93 | * new IOException("Error loading model: CheckID failed, required " + name + 94 | * " found " + found); } } } 95 | */ 96 | 97 | public static float[] loadFloatArray(BlizzardDataInputStream in, int size) 98 | throws IOException { 99 | float array[] = new float[size]; 100 | 101 | for (int i = 0; i < size; i++) { 102 | array[i] = in.readFloat(); 103 | } 104 | return array; 105 | } 106 | 107 | public static int[] loadIntArray(BlizzardDataInputStream in, int size) 108 | throws IOException { 109 | int array[] = new int[size]; 110 | 111 | for (int i = 0; i < size; i++) { 112 | array[i] = in.readInt(); 113 | } 114 | 115 | return array; 116 | } 117 | 118 | public static short[] loadShortArray(BlizzardDataInputStream in, int size) 119 | throws IOException { 120 | short array[] = new short[size]; 121 | 122 | for (int i = 0; i < size; i++) { 123 | array[i] = (short) (in.readShort() & 0xFFFF); 124 | } 125 | 126 | return array; 127 | } 128 | 129 | public static byte[] loadByteArray(BlizzardDataInputStream in, int size) 130 | throws IOException { 131 | byte array[] = new byte[size]; 132 | 133 | for (int i = 0; i < size; i++) { 134 | array[i] = in.readByte(); 135 | } 136 | return array; 137 | } 138 | 139 | public static char[] loadCharArray(BlizzardDataInputStream in, int size) 140 | throws IOException { 141 | char array[] = new char[size]; 142 | 143 | for (int i = 0; i < size; i++) { 144 | array[i] = in.readChar(); 145 | } 146 | return array; 147 | } 148 | 149 | public static void saveFloatArray(BlizzardDataOutputStream out, 150 | float[] array) throws IOException { 151 | for (int i = 0; i < array.length; i++) { 152 | out.writeFloat(array[i]); 153 | } 154 | } 155 | 156 | public static void saveIntArray(BlizzardDataOutputStream out, int[] array) 157 | throws IOException { 158 | for (int i = 0; i < array.length; i++) { 159 | out.writeInt(array[i]); 160 | } 161 | } 162 | 163 | public static void saveShortArray(BlizzardDataOutputStream out, 164 | short[] array) throws IOException { 165 | for (int i = 0; i < array.length; i++) { 166 | out.writeNByteInt(array[i], 2); 167 | } 168 | } 169 | 170 | public static void saveByteArray(BlizzardDataOutputStream out, byte[] array) 171 | throws IOException { 172 | for (int i = 0; i < array.length; i++) { 173 | out.writeByte(array[i]); 174 | } 175 | } 176 | 177 | public static void saveCharArray(BlizzardDataOutputStream out, char[] array) 178 | throws IOException { 179 | out.writeChars(array); 180 | } 181 | } 182 | --------------------------------------------------------------------------------