Exemple #1
0
        public unsafe static void ApplyEmissiveColor(FastBitmap emissiveMap, SColor color)
        {
            if (!emissiveMap.Locked)
            {
                emissiveMap.Lock();
            }

            byte *sourceScan = (byte *)emissiveMap.Scan0;

            for (int yOffset = 0; yOffset < emissiveMap.Height; ++yOffset)
            {
                int destPixelOffsetPart = yOffset * emissiveMap.Stride;

                for (int xOffset = 0; xOffset < emissiveMap.Width; ++xOffset)
                {
                    int sourceYStart = yOffset;
                    int sourceXStart = xOffset;

                    int pixelOffsetPart = sourceYStart * emissiveMap.Stride + sourceXStart;

                    int pixelOffset = (pixelOffsetPart) * FastBitmap.BytesPerPixel;

                    int destPixelOffset = (destPixelOffsetPart + xOffset) * FastBitmap.BytesPerPixel;

                    if (sourceScan[destPixelOffset + 3] != 0)
                    {
                        sourceScan[destPixelOffset + 0] = color.B;
                        sourceScan[destPixelOffset + 1] = color.G;
                        sourceScan[destPixelOffset + 2] = color.R;
                    }
                }
            }
        }
Exemple #2
0
        public unsafe static void SetFlatColor(FastBitmap diffuseMap, SColor color)
        {
            if (!diffuseMap.Locked)
            {
                diffuseMap.Lock();
            }

            byte *sourceScan = (byte *)diffuseMap.Scan0;

            for (int yOffset = 0; yOffset < diffuseMap.Height; ++yOffset)
            {
                int destPixelOffsetPart = yOffset * diffuseMap.Stride;

                for (int xOffset = 0; xOffset < diffuseMap.Width; ++xOffset)
                {
                    int sourceYStart = yOffset;
                    int sourceXStart = xOffset;

                    int pixelOffsetPart = sourceYStart * diffuseMap.Stride + sourceXStart;

                    int pixelOffset = (pixelOffsetPart) * FastBitmap.BytesPerPixel;

                    int destPixelOffset = (destPixelOffsetPart + xOffset) * FastBitmap.BytesPerPixel;

                    sourceScan[destPixelOffset + 0] = color.B;
                    sourceScan[destPixelOffset + 1] = color.G;
                    sourceScan[destPixelOffset + 2] = color.R;
                    sourceScan[destPixelOffset + 3] = color.A;
                }
            }
        }
Exemple #3
0
        public static void DoMakeObjFile(string outputDir, string inputFile, string gradient, string emissive)
        {
            byte[] gradientColors = gradient.Split(new char[] { '[', ']', ',' }, StringSplitOptions.RemoveEmptyEntries).Select(cur => byte.Parse(cur.Trim())).ToArray();

            SColor[] gradientObj = new SColor[] {
                new SColor {
                    R = gradientColors[0], B = gradientColors[1], G = gradientColors[2]
                },
                new SColor {
                    R = gradientColors[3], B = gradientColors[4], G = gradientColors[5]
                },
                new SColor {
                    R = gradientColors[6], B = gradientColors[7], G = gradientColors[8]
                },
            };

            byte[] emissiveColors = emissive.Split(new char[] { '[', ']', ',' }, StringSplitOptions.RemoveEmptyEntries).Select(cur => byte.Parse(cur.Trim())).ToArray();

            SColor emissiveObj = new SColor {
                R = emissiveColors[0], B = emissiveColors[1], G = emissiveColors[2]
            };

            string inputOrg = inputFile;

            bool isJson    = inputFile.EndsWith(".json", StringComparison.OrdinalIgnoreCase);
            bool isMsgpack = inputFile.EndsWith(".msgpack", StringComparison.OrdinalIgnoreCase);

            if (!File.Exists(inputFile) || (!isMsgpack && !isJson))
            {
                throw new Exception("Input file must be .msgpack or .json");
            }

            if (!Directory.Exists(outputDir))
            {
                throw new Exception("Output directory does not exist!");
            }

            if (isMsgpack)
            {
                Parser.DoParse(outputDir, inputFile);
                inputFile = Path.Combine(outputDir, $"{Path.GetFileNameWithoutExtension(inputFile)}.json");
            }

            string materialName     = Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(inputFile));
            string materialFile     = $"{materialName}.mtl";
            string materialFilePath = Path.Combine(outputDir, materialFile);

            JObject root = JObject.Parse(File.ReadAllText(inputFile));

            Dictionary <string, Dictionary <string, string> > materialLookup = new Dictionary <string, Dictionary <string, string> >();

            foreach (var curNode in root["nodes"].Value <JObject>())
            {
                if (!curNode.Value.Value <JObject>().ContainsKey("geometryinstances"))
                {
                    continue;
                }

                foreach (var curGeom in curNode.Value["geometryinstances"].Value <JObject>())
                {
                    string geometry = curGeom.Value["geometry"].Value <string>();
                    string surface  = curGeom.Value["surface"].Value <string>();
                    string material = curGeom.Value["material"].Value <string>();

                    if (!materialLookup.TryGetValue(geometry, out Dictionary <string, string> curGeomLookup))
                    {
                        curGeomLookup = new Dictionary <string, string>();
                        materialLookup.Add(geometry, curGeomLookup);
                    }

                    curGeomLookup[surface] = material;
                }
            }

            bool failMat = false;

            string outputFile = Path.Combine(outputDir, $"{Path.GetFileNameWithoutExtension(inputFile)}.obj");

            using (StreamWriter sw = new StreamWriter(outputFile))
            {
                sw.WriteLine($"mtllib {materialFile}");

                int vOffset  = 0;
                int vtOffset = 0;
                int vnOffset = 0;

                foreach (var curGeom in root["geometries"].Value <JObject>())
                {
                    // TODO: handle TANGENT and BINORMAL. Anymore?

                    //if (curGeom.Value["inputs"].Count() != 3)
                    //{
                    //    throw new Exception("Invalid source input count...");
                    //}

                    double[][] vertLocs = ReadShit <double>(curGeom.Value, "POSITION", out int vertOffset);
                    foreach (double[] curVert in vertLocs)
                    {
                        sw.WriteLine($"v {curVert[0]} {curVert[1]} {curVert[2]}");
                    }

                    double[][] texCoords = ReadShit <double>(curGeom.Value, "TEXCOORD0", out int texOffset);
                    foreach (double[] curTex in texCoords)
                    {
                        sw.WriteLine($"vt {curTex[0]} {1-curTex[1]}");
                    }

                    double[][] normals = ReadShit <double>(curGeom.Value, "NORMAL", out int normOffset);
                    foreach (double[] curNorm in normals)
                    {
                        sw.WriteLine($"vn {curNorm[0]} {curNorm[1]} {curNorm[2]}");
                    }

                    foreach (var curSurf in curGeom.Value["surfaces"].Value <JObject>())
                    {
                        sw.WriteLine($"g {curSurf.Key}");

                        try
                        {
                            sw.WriteLine($"usemtl {materialLookup[curGeom.Key][curSurf.Key]}");
                        }
                        catch
                        {
                            failMat = true;
                            sw.WriteLine($"usemtl failMat");
                            Console.WriteLine("material not found...");
                        }

                        var blarg         = curSurf.Value["triangles"].Select(cur => cur.Value <int>());
                        int numPrimitives = curSurf.Value["numPrimitives"].Value <int>();

                        if ((blarg.Count() % numPrimitives) != 0)
                        {
                            throw new Exception("Invalid stride");
                        }

                        int stride = blarg.Count() / numPrimitives;

                        if ((stride % 3) != 0)
                        {
                            throw new Exception("Invalid stride");
                        }

                        int pointLength = stride / 3;

                        int[][] triangles = FuckinReadIt(blarg, stride);

                        foreach (int[] curTri in triangles)
                        {
                            if (pointLength >= 1)
                            {
                                if ((curTri[pointLength * 0 + 0] >= vertLocs.Length) ||
                                    (curTri[pointLength * 1 + 0] >= vertLocs.Length) ||
                                    (curTri[pointLength * 2 + 0] >= vertLocs.Length))
                                {
                                    Console.WriteLine("vert index out of range");
                                    continue;
                                }
                            }

                            if (pointLength >= 2)
                            {
                                if ((curTri[pointLength * 0 + 1] >= texCoords.Length) ||
                                    (curTri[pointLength * 1 + 1] >= texCoords.Length) ||
                                    (curTri[pointLength * 2 + 1] >= texCoords.Length))
                                {
                                    Console.WriteLine("tex index out of range");
                                    continue;
                                }
                            }

                            if (pointLength >= 3)
                            {
                                if ((curTri[pointLength * 0 + 2] >= normals.Length) ||
                                    (curTri[pointLength * 1 + 2] >= normals.Length) ||
                                    (curTri[pointLength * 2 + 2] >= normals.Length))
                                {
                                    Console.WriteLine("norm index out of range");
                                    continue;
                                }
                            }

                            sw.Write("f");

                            for (int i = 0; i < 3; ++i)
                            {
                                sw.Write(" ");

                                if (pointLength >= 1)
                                {
                                    sw.Write($"{curTri[pointLength * i + 0] + 1 + vOffset}");
                                }

                                if (pointLength >= 2)
                                {
                                    sw.Write($"/{curTri[pointLength * i + 1] + 1 + vtOffset}");
                                }

                                if (pointLength >= 3)
                                {
                                    sw.Write($"/{curTri[pointLength * i + 2] + 1 + vnOffset}");
                                }
                            }

                            sw.WriteLine();
                        }
                    }

                    vOffset  += vertLocs.Length;
                    vtOffset += texCoords.Length;
                    vnOffset += normals.Length;
                }

                sw.Flush();
                sw.Close();
                sw.Dispose();
            }

            string rootDir = inputOrg;

            while (Path.GetFileName(rootDir) != "assets")
            {
                rootDir = Path.GetDirectoryName(rootDir);
            }

            using (StreamWriter sw = new StreamWriter(materialFilePath))
            {
                foreach (var curMat in root["materials"].Value <JObject>())
                {
                    sw.WriteLine($"newmtl {curMat.Key}");

                    var material = curMat.Value.Value <JObject>();

                    int usedTextures = 0;

                    if (material["parameters"].Value <JObject>().ContainsKey("diffuse") ||
                        material["parameters"].Value <JObject>().ContainsKey("gradient_mask"))
                    {
                        string     diffuse;
                        FastBitmap diffuseTexture;

                        if (material["parameters"].Value <JObject>().ContainsKey("diffuse"))
                        {
                            ++usedTextures;
                            diffuse = material["parameters"]["diffuse"].Value <string>().Replace('/', '\\');

                            try
                            {
                                diffuseTexture = DDS.LoadImage(Path.Combine(rootDir, diffuse)).FastLock();
                            }
                            catch
                            {
                                diffuseTexture = null;
                                Console.WriteLine("Error loading texture");
                            }
                        }
                        else
                        {
                            diffuse        = material["parameters"]["gradient_mask"].Value <string>().Replace('/', '\\');
                            diffuseTexture = null;
                        }

                        if (material["parameters"].Value <JObject>().ContainsKey("gradient_mask"))
                        {
                            ++usedTextures;
                            string gradient_mask = material["parameters"]["gradient_mask"].Value <string>().Replace('/', '\\');

                            FastBitmap gradient_maskTexture = null;
                            bool       fail = false;

                            try
                            {
                                gradient_maskTexture = DDS.LoadImage(Path.Combine(rootDir, gradient_mask)).FastLock();
                            }
                            catch
                            {
                                fail = true;
                                Console.WriteLine("Error loading texture");
                            }

                            if (!fail)
                            {
                                if (diffuseTexture == null)
                                {
                                    diffuseTexture = new Bitmap(gradient_maskTexture.Width, gradient_maskTexture.Height, PixelFormat.Format32bppArgb).FastLock();
                                }

                                ApplyGradientToDiffuse(diffuseTexture, gradient_maskTexture, gradientObj);

                                gradient_maskTexture.Unlock();
                                gradient_maskTexture.Bitmap.Dispose();
                                gradient_maskTexture.Dispose();
                            }
                        }

                        if (diffuseTexture == null)
                        {
                            diffuseTexture = new Bitmap(512, 512, PixelFormat.Format32bppArgb).FastLock();
                            SetFlatColor(diffuseTexture, new SColor {
                                R = 255, G = 0, B = 255
                            });
                        }

                        diffuseTexture.Unlock();

                        string saveFilePath = Path.Combine(outputDir, $"{Path.GetFileNameWithoutExtension(diffuse)}.png");
                        sw.WriteLine($"map_Kd {Path.GetFileName(saveFilePath)}");

                        try
                        {
                            diffuseTexture.Bitmap.Save(saveFilePath, ImageFormat.Png);
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine($"Failed to save image {saveFilePath}\r\n{ex.Message}");
                        }

                        diffuseTexture.Bitmap.Dispose();
                        diffuseTexture.Dispose();
                    }

                    if (material["parameters"].Value <JObject>().ContainsKey("normal"))
                    {
                        ++usedTextures;
                        string normal = material["parameters"]["normal"].Value <string>().Replace('/', '\\');

                        FastBitmap normalTexture = null;
                        bool       fail          = false;

                        try
                        {
                            normalTexture = DDS.LoadImage(Path.Combine(rootDir, normal)).FastLock();
                        }
                        catch
                        {
                            fail = true;
                            Console.WriteLine("Error loading texture");
                        }

                        if (!fail)
                        {
                            normalTexture.Unlock();

                            string saveFilePath = Path.Combine(outputDir, $"{Path.GetFileNameWithoutExtension(normal)}.png");
                            sw.WriteLine($"map_Bump {Path.GetFileName(saveFilePath)}");

                            try
                            {
                                normalTexture.Bitmap.Save(saveFilePath, ImageFormat.Png);
                            }
                            catch (Exception ex)
                            {
                                Console.WriteLine($"Failed to save image {saveFilePath}\r\n{ex.Message}");
                            }

                            normalTexture.Bitmap.Dispose();
                            normalTexture.Dispose();
                        }
                    }

                    if (material["parameters"].Value <JObject>().ContainsKey("specular_emissive"))
                    {
                        ++usedTextures;
                        string specular_emissive = material["parameters"]["specular_emissive"].Value <string>().Replace('/', '\\');

                        FastBitmap specular_emissiveTexture = null;

                        bool fail = false;
                        try
                        {
                            specular_emissiveTexture = DDS.LoadImage(Path.Combine(rootDir, specular_emissive)).FastLock();
                        }
                        catch
                        {
                            fail = true;
                            Console.WriteLine("Error loading texture");
                        }

                        if (!fail)
                        {
                            ApplyEmissiveColor(specular_emissiveTexture, emissiveObj);

                            specular_emissiveTexture.Unlock();

                            string saveFilePath = Path.Combine(outputDir, $"{Path.GetFileNameWithoutExtension(specular_emissive)}.png");
                            sw.WriteLine($"map_Ke {Path.GetFileName(saveFilePath)}");

                            try
                            {
                                specular_emissiveTexture.Bitmap.Save(saveFilePath, ImageFormat.Png);
                            }
                            catch (Exception ex)
                            {
                                Console.WriteLine($"Failed to save image {saveFilePath}\r\n{ex.Message}");
                            }

                            specular_emissiveTexture.Bitmap.Dispose();
                            specular_emissiveTexture.Dispose();
                        }
                    }

                    if (material["parameters"].Value <JObject>().Count != usedTextures)
                    {
                        Console.WriteLine($"Warning, unused texture(s) on {curMat.Key}...");
                    }
                }

                if (failMat)
                {
                    FastBitmap failTexture = new Bitmap(512, 512, PixelFormat.Format32bppArgb).FastLock();
                    SetFlatColor(failTexture, new SColor {
                        R = 255, G = 0, B = 255
                    });

                    sw.WriteLine($"newmtl failMat");

                    failTexture.Unlock();

                    string saveFilePath = Path.Combine(outputDir, $"failMat.png");
                    sw.WriteLine($"map_Kd {Path.GetFileName(saveFilePath)}");

                    try
                    {
                        failTexture.Bitmap.Save(saveFilePath, ImageFormat.Png);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine($"Failed to save image {saveFilePath}\r\n{ex.Message}");
                    }

                    failTexture.Bitmap.Dispose();
                    failTexture.Dispose();
                }

                sw.Flush();
                sw.Close();
                sw.Dispose();
            }

            Console.WriteLine("Done Done!!!");
        }