Пример #1
0
        public void SetLevel(BlastCorpsLevel level)
        {
            this.level = level;
             levelModel = new Model3D(level);

             foreach (Vehicle veh in level.vehicles)
             {
            if (veh.type == 0) // player
            {
               location = new Vector3((veh.x + 20) * scale, (veh.y + 400) * scale, (veh.z - 400) * scale);
               pitch = -MathHelper.PiOver6;
               facing = MathHelper.PiOver2 + MathHelper.PiOver6;
               SetupViewport();
               glControlViewer.Invalidate();
               break;
            }
             }

             if (loaded)
             {
            glControlViewer.Invalidate();
             }
        }
Пример #2
0
        public void parseModel(BlastCorpsLevel level)
        {
            byte[] displayList = level.displayList;
             Vertex[] vertexBuffer = new Vertex[16];
             Stack<uint> dlStack = new Stack<uint>();
             uint segAddress;
             uint segOffset;
             byte bank;
             Texture nextTexture = new Texture();
             Triangle nextTri = new Triangle();
             List<UInt32> displayLists = new List<UInt32>();
             displayLists.Add(level.header.offsets[(0x88 - 0x20) / 4]);
             displayLists.Add(level.header.offsets[(0x90 - 0x20) / 4]);
             displayLists.Add(level.header.offsets[(0x94 - 0x20) / 4]);
             displayLists.Add(level.header.offsets[(0x98 - 0x20) / 4]);
             displayLists.Add(level.header.offsets[(0x9C - 0x20) / 4]);

             foreach (uint startOffset in displayLists)
             {
            bool done = false;
            for (uint offset = startOffset - level.header.dlOffset; offset < displayList.Length && !done; offset += 8)
            {
               UInt32 w0 = BE.U32(displayList, offset);
               UInt32 w1 = BE.U32(displayList, offset + 4);
               byte command = displayList[offset];
               switch (command)
               {
                  case F3D_MOVEMEM:
                     break;
                  case F3D_VTX:
                     int count = ((displayList[offset + 1] >> 4) & 0xF) + 1;
                     int index = (displayList[offset + 1]) & 0xF;
                     segAddress = w1;
                     bank = displayList[offset + 4];
                     segOffset = segAddress & 0x00FFFFFF;
                     LoadVertices(level.vertData, segOffset, index, count, vertexBuffer);
                     break;
                  case F3D_DL:
                     segAddress = w1;
                     bank = displayList[offset + 4];
                     segOffset = segAddress & 0x00FFFFFF;
                     dlStack.Push(offset);
                     offset = segOffset - 8; // subtract 8 since for loop will increment by 8
                     break;
                  case F3D_QUAD:
                     break;
                  case F3D_CLRGEOMODE:
                     break;
                  case F3D_SETGEOMODE:
                     break;
                  case F3D_ENDDL:
                     if (dlStack.Count == 0)
                     {
                        done = true;
                     }
                     else
                     {
                        offset = dlStack.Pop();
                     }
                     break;
                  case F3D_TEXTURE:
                     // reset tile sizes
                     nextTexture = new Texture();
                     break;
                  case F3D_TRI1:
                     int vertex0 = displayList[offset + 5] / 0x0A;
                     int vertex1 = displayList[offset + 6] / 0x0A;
                     int vertex2 = displayList[offset + 7] / 0x0A;
                     Triangle tri = new Triangle(vertexBuffer[vertex0], vertexBuffer[vertex1], vertexBuffer[vertex2]);
                     tri.texture = nextTexture;
                     triangles.Add(tri);
                     break;
                  case G_SETTILESIZE:
                     if (nextTexture.width < 0)
                     {
                        nextTexture.width = (((displayList[offset + 5] << 8) | (displayList[offset + 6] & 0xF0)) >> 6) + 1;
                        nextTexture.height = (((displayList[offset + 6] & 0x0F) << 8 | displayList[offset + 7]) >> 2) + 1;
                     }
                     if (nextTexture.IsComplete())
                     {
                        textures.Add(nextTexture);
                     }
                     break;
                  case G_LOADBLOCK:
                     break;
                  case G_SETTILE:
                     break;
                  case G_SETFOGCOLOR:
                     break;
                  case G_SETENVCOLOR:
                     break;
                  case G_SETCOMBINE:
                     break;
                  case G_SETTIMG:
                     segAddress = w1;
                     bank = displayList[offset + 4];
                     segOffset = segAddress & 0x00FFFFFF;
                     nextTexture.address = segAddress;
                     if (nextTexture.IsComplete())
                     {
                        textures.Add(nextTexture);
                     }
                     break;
               }
            }
             }
        }
Пример #3
0
 public Model3D(BlastCorpsLevel level)
 {
     parseModel(level);
 }
        public static void ExportDisplayList(BlastCorpsRom rom, BlastCorpsLevel level, string filename, float scale)
        {
            Model3D model = new Model3D(level);

             string mtlFileName = filename + ".mtl";

             using (System.IO.StreamWriter file = new System.IO.StreamWriter(filename))
             {
            int vertCount = 1;
            file.WriteLine(fileHeader());
            file.WriteLine("mtllib {0}", Path.GetFileName(mtlFileName));
            foreach (Triangle tri in model.triangles)
            {
               float uScale = 32.0f * tri.texture.width;
               float vScale = 32.0f * tri.texture.height;
               file.WriteLine();
               file.WriteLine("usemtl Texture{0:X4}", tri.texture.address);
               file.WriteLine(toObjVert(tri.vertices[0], scale, uScale, vScale));
               file.WriteLine(toObjVert(tri.vertices[1], scale, uScale, vScale));
               file.WriteLine(toObjVert(tri.vertices[2], scale, uScale, vScale));
               file.WriteLine("f {0}/{0}/{0} {1}/{1}/{1} {2}/{2}/{2}", vertCount, (vertCount + 1), (vertCount + 2));
               vertCount += 3;
            }
             }

             // create textures directory
             string textureDirName = "textures";
             string textureDir = Path.Combine(Path.GetDirectoryName(filename), textureDirName);
             Directory.CreateDirectory(textureDir);
             using (System.IO.StreamWriter file = new System.IO.StreamWriter(mtlFileName))
             {
            List<uint> processedTextures = new List<uint>();
            file.WriteLine(fileHeader());
            foreach (Texture t in model.textures)
            {
               if (!processedTextures.Contains(t.address))
               {
                  string textureFilename = String.Format("{0:X4}.png", t.address);
                  string textureFile = String.Format(textureDirName + "/" + textureFilename);
                  file.WriteLine("newmtl Texture{0:X4}", t.address);
                  file.WriteLine("Ka 0.0 0.0 0.0"); // ambiant color
                  file.WriteLine("Kd 1.0 1.0 1.0"); // diffuse color
                  file.WriteLine("Ks 0.3 0.3 0.3"); // specular color
                  file.WriteLine("d 1");            // dissolved
                  file.WriteLine("map_Kd {0}", textureFile);
                  file.WriteLine();

                  BlastCorpsTexture bct = new BlastCorpsTexture(rom.GetRawData(), t.address, 0);
                  bct.decode();
                  byte[] n64Texture = bct.GetInflated();
                  N64Format format = N64Format.RGBA;
                  int depth = 16;

                  switch (bct.type)
                  {
                     case 0: // IA8?
                        // TODO: memcpy, no info
                        format = N64Format.IA;
                        depth = 8;
                        break;
                     case 1: // RBGA16?
                        format = N64Format.RGBA;
                        depth = 16;
                        break;
                     case 2: // RGBA32?
                        format = N64Format.RGBA;
                        depth = 32;
                        break;
                     case 3: // IA8?
                        format = N64Format.IA;
                        depth = 8;
                        break;
                     case 4: // IA16?
                        format = N64Format.IA;
                        depth = 16;
                        break;
                     case 5: // RGBA32?
                        format = N64Format.RGBA;
                        depth = 32;
                        break;
                     case 6: // IA8?
                        format = N64Format.IA;
                        depth = 8;
                        break;
                  }

                  Bitmap loadedBitmap;
                  switch (format)
                  {
                     case N64Format.RGBA:
                        loadedBitmap = N64Graphics.RGBA(n64Texture, t.width, t.height, depth);
                        break;
                     case N64Format.IA:
                     default:
                        loadedBitmap = N64Graphics.IA(n64Texture, t.width, t.height, depth);
                        break;
                  }
                  loadedBitmap.RotateFlip(RotateFlipType.RotateNoneFlipY);
                  loadedBitmap.Save(Path.Combine(textureDir, textureFilename));

                  processedTextures.Add(t.address);
               }
            }
             }
        }
Пример #5
0
 public static BlastCorpsLevel decodeLevel(byte[] levelData, byte[] displayListData)
 {
     BlastCorpsLevel level = new BlastCorpsLevel();
      level.decodeHeader(levelData);          // 0x00-0x1F
      level.saveVertices(levelData);          // 0xC8-ammo
      level.decodeAmmoBoxes(levelData);       // 0x20
      level.decodeCollision24(levelData);     // 0x24
      level.decodeCommPoints(levelData);      // 0x28
      level.decodeAnimatedTextures(levelData);// 0x2C
      level.decodeTerrain(levelData);         // 0x30
      level.decodeRDUs(levelData);            // 0x34
      level.decodeTNTCrates(levelData);       // 0x38
      level.decodeSquareBlocks(levelData);    // 0x3C
      level.decodeBounds40(levelData);        // 0x40
      level.decodeBounds44(levelData);        // 0x44
      level.decode48(levelData);              // 0x48 TODO: decode these U32s
      level.decodeLevelBounds(levelData);     // 0x4C
      level.decodeVehicles(levelData);        // 0x50
      level.decodeMissileCarrier(levelData);  // 0x54
      level.decode58(levelData);              // 0x58 TODO
      level.decodeBuildings(levelData);       // 0x5C
      level.decode60(levelData);              // 0x60 TODO
      level.decode64(levelData);              // 0x64 TODO
      level.decodeTrainPlatform(levelData);   // 0x68
      level.decodeCollision6C(levelData);     // 0x6C
      level.decodeCollision70(levelData);     // 0x70
      level.decode74(levelData);              // 0x74 TODO
      // 0x78-0x9C are located in the display list data
      level.copyLevelData = levelData;
      level.displayList = displayListData;
      return level;
 }
Пример #6
0
 public void SetLevel(BlastCorpsLevel level)
 {
     this.level = level;
      computeBounds();
      Invalidate();
 }