示例#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();
            }
        }
        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);
                    }
                }
            }
        }
 public void SetLevel(BlastCorpsLevel level)
 {
     this.level = level;
     computeBounds();
     Invalidate();
 }
示例#4
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;
                    }
                }
            }
        }
示例#5
0
 public Model3D(BlastCorpsLevel level)
 {
     parseModel(level);
 }
示例#6
0
        static void Main(string[] args)
        {
            if (args.Length < 1)
            {
                System.Console.WriteLine("Usage: BlastCorpsConsole <DIR with .raw levels> [DIR to output <level>.txt]");
                return;
            }
            string tmpDir    = Path.GetTempPath();
            string inputDir  = args[0];
            string outputDir = null;

            if (args.Length > 1)
            {
                outputDir = args[1];
                System.Console.WriteLine("Outputing data to {0}", outputDir);
            }

            tmpDir = Path.Combine(tmpDir, "BlastCorps");
            System.Console.WriteLine("Saving generated levels to: " + tmpDir);

            Directory.CreateDirectory(tmpDir);

            foreach (BlastCorpsLevelMeta levelMeta in BlastCorpsRom.levelMeta)
            {
                string          inputFile  = Path.Combine(inputDir, levelMeta.filename + ".raw");
                string          outputFile = Path.Combine(tmpDir, levelMeta.filename + ".raw");
                byte[]          inData     = File.ReadAllBytes(inputFile);
                BlastCorpsLevel level      = BlastCorpsLevel.decodeLevel(inData, inData);

                if (outputDir != null)
                {
                    string txtFile = Path.Combine(outputDir, levelMeta.filename + ".txt");
                    using (StreamWriter writer = new StreamWriter(txtFile))
                    {
                        level.Write(writer, levelMeta);
                    }
                }

                byte[]     outData   = level.ToBytes();
                FileStream outStream = File.OpenWrite(outputFile);
                outStream.Write(outData, 0, outData.Length);
                outStream.Close();
                bool passed = true;
                if (levelMeta.id == 14)
                {
                    StatusPrint(ConsoleColor.Yellow, "level14 fails square hole off", "0175A5");
                }
                if (inData.Length != outData.Length)
                {
                    StatusPrint(ConsoleColor.Red, "Fail", levelMeta.filename + ".raw, lengths differ: " + inData.Length + " -> " + outData.Length);
                    passed = false;
                }
                for (int i = 0; i < Math.Min(inData.Length, outData.Length); i++)
                {
                    if (inData[i] != outData[i])
                    {
                        StatusPrint(ConsoleColor.Red, "Fail", levelMeta.filename + ".raw, mismatch at " + i.ToString("X6"));
                        passed = false;
                        break;
                    }
                }
                if (passed)
                {
                    StatusPrint(ConsoleColor.Green, "Pass", levelMeta.filename + ".raw");
                }
            }
        }