Пример #1
0
        private void OnEnable()
        {
            _target = (MaterialDef)target;

            // Try to refresh the database!
            SharedEditorDataManager.TryRefreshDatabaseAtStart();
        }
Пример #2
0
        public MaterialDef addMaterial(string name)
        {
            MaterialDef mat = new MaterialDef(name);

            materials.Add(name, mat);
            return(mat);
        }
Пример #3
0
 public IEnumerable <Tri> TrianglesFor(MaterialDef material)
 {
     if (datas.ContainsKey(material.name))
     {
         foreach (Tri t in datas[material.name].tris)
         {
             yield return(t);
         }
     }
 }
Пример #4
0
    private Color TraceLight(Vector3 pos, Vector3 normal, Color diffuseColor, MaterialDef materialDef)
    {
        Color color = RGBAZero;

        foreach (Light light in lights)
        {
            if (light.enabled)
            {
                Color colorToAdd = LightTrace(light, pos, normal, diffuseColor, materialDef);
                colorToAdd.a = 1;

                color += colorToAdd;
            }
        }

        return(color);
    }
Пример #5
0
        private Imgd FileLoader(string filePath, MaterialDef matDef, MapGenConfig config)
        {
            logger.Debug($"Load image from \"{filePath}\"");

            if (FileExtUtil.IsExtension(filePath, ".imd"))
            {
                return(ImageResizer.NormalizeImageSize(File.OpenRead(filePath).Using(s => Imgd.Read(s))));
            }
            if (FileExtUtil.IsExtension(filePath, ".png"))
            {
                var imdFile = Path.ChangeExtension(filePath, ".imd");

                if (config.skipConversionIfExists && File.Exists(imdFile))
                {
                    logger.Debug($"Skipping png to imd conversion, due to imd file existence and skipConversionIfExists option.");
                }
                else
                {
                    try
                    {
                        logger.Debug($"Using ImgTool for png to imd conversion.");

                        var imgtoolOptions = matDef.imgtoolOptions ?? config.imgtoolOptions ?? "-b 8";

                        var result = new RunCmd(
                            "OpenKh.Command.ImgTool.exe",
                            $"imd \"{filePath}\" -o \"{imdFile}\" {imgtoolOptions}"
                            );

                        if (result.ExitCode != 0)
                        {
                            throw new Exception($"ImgTool failed ({result.ExitCode})");
                        }
                    }
                    catch (Win32Exception ex)
                    {
                        throw new Exception("ImgTool failed.", ex);
                    }
                }

                return(FileLoader(imdFile, matDef, config));
            }

            throw new NotSupportedException(Path.GetExtension(filePath));
        }
Пример #6
0
        private void cbMaterialsFromMatFile_SelectedIndexChanged(object sender, EventArgs e)
        {
            string  path = getCurrentMatFileNamePath();
            MtrFile mf   = ms.findMtrFile(path);

            if (mf == null)
            {
                return;
            }
            string      matName = cbMaterialsFromMatFile.Text;
            MaterialDef md      = mf.findMaterialDef(matName);

            if (md == null)
            {
                return;
            }
            string txt = mf.getMaterialDefText(matName);

            tbMaterialText.Text = txt;
        }
Пример #7
0
        private void ConvertModelIntoMapModel(string modelFile, MapGenConfig config)
        {
            logger.Debug($"Loading 3D model file \"{modelFile}\" using Assimp.");

            var assimp = new Assimp.AssimpContext();
            var scene  = assimp.ImportFile(modelFile, Assimp.PostProcessSteps.PreTransformVertices);

            bigMeshContainer = new BigMeshContainer();

            var scale = config.scale;

            Matrix4x4 matrix = Matrix4x4.Identity;

            if (config.applyMatrix != null)
            {
                var m = config.applyMatrix;

                if (m.Length == 16)
                {
                    matrix = new Matrix4x4(
                        m[0], m[1], m[2], m[3],
                        m[4], m[5], m[6], m[7],
                        m[8], m[9], m[10], m[11],
                        m[12], m[13], m[14], m[15]
                        );

                    logger.Debug($"Apply matrix: {matrix}");
                }
            }
            else
            {
                matrix *= scale;
            }

            logger.Debug($"Starting triangle strip conversion for {scene.Meshes.Count} meshes.");

            foreach (var inputMesh in scene.Meshes)
            {
                logger.Debug($"Mesh: {inputMesh.Name} ({inputMesh.FaceCount:#,##0} faces, {inputMesh.VertexCount:#,##0} vertices)");

                var modelMat = scene.Materials[inputMesh.MaterialIndex];

                var matDef = config.FindMaterial(modelMat.Name ?? "default") ?? MaterialDef.CreateFallbackFor(modelMat.Name);
                if (matDef.ignore)
                {
                    logger.Info($"This mesh \"{inputMesh.Name}\" is not rendered due to ignore flag of material \"{modelMat.Name}\".");
                    continue;
                }

                var kh2Mesh = bigMeshContainer.AllocateBigMeshForMaterial(matDef);

                var diffuseTextureFile = modelMat.TextureDiffuse.FilePath;
                if (!string.IsNullOrEmpty(diffuseTextureFile))
                {
                    if (config.reuseImd)
                    {
                        logger.Debug($"The mesh \"{inputMesh.Name}\" material \"{matDef.name}\" has filepath \"{diffuseTextureFile}\" for diffuse texture. It will be associated with material's fromFile3. Setting preferable imd file to fromFile2 due to reuseImd flag.");

                        matDef.fromFile2 = Path.ChangeExtension(diffuseTextureFile, ".imd");
                        matDef.fromFile3 = diffuseTextureFile;
                    }
                    else
                    {
                        logger.Debug($"The mesh \"{inputMesh.Name}\" material \"{matDef.name}\" has filepath \"{diffuseTextureFile}\" for diffuse texture. It will be associated with material's fromFile2.");

                        matDef.fromFile3 = diffuseTextureFile;
                    }
                }

                var kh2BaseVert = kh2Mesh.vertexList.Count;

                List <int> vertexToLocal = new List <int>();

                foreach (var inputVertex in inputMesh.Vertices)
                {
                    var vertex = Vector3.Transform(
                        new Vector3(inputVertex.X, inputVertex.Y, inputVertex.Z),
                        matrix
                        );

                    var index = kh2Mesh.vertexList.IndexOf(vertex);
                    if (index < 0)
                    {
                        index = kh2Mesh.vertexList.Count;
                        kh2Mesh.vertexList.Add(vertex);
                    }

                    vertexToLocal.Add(index);
                }

                var localFaces = inputMesh.Faces
                                 .Select(
                    set => set.Indices
                    .Select(index => new VertPair {
                    uvColorIndex = index, vertexIndex = vertexToLocal[index]
                })
                    .ToArray()
                    )
                                 .ToArray();

                var inputTexCoords       = inputMesh.TextureCoordinateChannels.First();
                var inputVertexColorList = inputMesh.VertexColorChannels.First();

                var hasVertexColor = inputMesh.VertexColorChannelCount >= 1;

                var maxIntensity = matDef.maxColorIntensity
                                   ?? config.maxColorIntensity
                                   ?? 128;
                var maxAlpha = matDef.maxAlpha
                               ?? config.maxAlpha
                               ?? 128;

                var triConverter =
                    config.disableTriangleStripsOptimization
                    ? (TriangleFansToTriangleStripsConverter)TriangleFansToTriangleStripsNoOpts
                    : (TriangleFansToTriangleStripsConverter)TriangleFansToTriangleStripsOptimized;

                foreach (var triStripInput in triConverter(localFaces))
                {
                    var triStripOut = new BigMesh.TriangleStrip();

                    foreach (var vertPair in triStripInput)
                    {
                        triStripOut.vertexIndices.Add(kh2BaseVert + vertPair.vertexIndex);

                        triStripOut.uvList.Add(Get2DCoord(inputTexCoords[vertPair.uvColorIndex]));

                        if (hasVertexColor)
                        {
                            triStripOut.vertexColorList.Add(ConvertVertexColor(inputVertexColorList[vertPair.uvColorIndex], maxIntensity, maxAlpha));
                        }
                        else
                        {
                            triStripOut.vertexColorList.Add(new Color(maxIntensity, maxIntensity, maxIntensity, maxAlpha));
                        }
                    }

                    kh2Mesh.triangleStripList.Add(triStripOut);
                }

                logger.Debug($"Output: {kh2Mesh.vertexList.Count:#,##0} vertices, {kh2Mesh.triangleStripList.Count:#,##0} triangle strips.");
            }

            logger.Debug($"The conversion has done.");

            logger.Debug($"Starting mesh splitter and vif packets builder.");

            mapModel = new Mdlx.M4
            {
                VifPackets = new List <Mdlx.VifPacketDescriptor>(),
            };

            foreach (var bigMesh in bigMeshContainer.MeshList
                     .Where(it => it.textureIndex != -1)
                     )
            {
                foreach (var smallMesh in BigMeshSplitter.Split(bigMesh))
                {
                    var dmaPack = new MapVifPacketBuilder(smallMesh);

                    smallMeshList.Add(smallMesh);

                    bigMesh.vifPacketIndices.Add(Convert.ToUInt16(mapModel.VifPackets.Count));
                    smallMesh.vifPacketIndices.Add(Convert.ToUInt16(mapModel.VifPackets.Count));

                    mapModel.VifPackets.Add(
                        new Mdlx.VifPacketDescriptor
                    {
                        VifPacket = dmaPack.vifPacket.ToArray(),
                        TextureId = smallMesh.textureIndex,
                        DmaPerVif = new ushort[] {
                            dmaPack.firstVifPacketQwc,
                            0,
                        },
                        IsTransparentFlag = smallMesh.matDef.transparentFlag ?? 0,
                    }
                        );
                }
            }

            logger.Debug($"Output: {mapModel.VifPackets.Count:#,##0} vif packets.");

            logger.Debug($"The builder has done.");

            logger.Debug($"Starting vifPacketRenderingGroup builder.");

            // first group: render all

            mapModel.vifPacketRenderingGroup = new List <ushort[]>(
                new ushort[][] {
                Enumerable.Range(0, mapModel.VifPackets.Count)
                .Select(it => Convert.ToUInt16(it))
                .ToArray()
            }
                );

            logger.Debug($"Output: {mapModel.vifPacketRenderingGroup.Count:#,##0} groups.");

            mapModel.DmaChainIndexRemapTable = new List <ushort>(
                Enumerable.Range(0, mapModel.VifPackets.Count)
                .Select(it => Convert.ToUInt16(it))
                .ToArray()
                );
        }
        internal void ReadXML(string xmlFile)
        {
            XmlDocument xml = new XmlDocument();

            xml.Load(xmlFile);

            DefaultFallbackMTDName = xml.SelectSingleNode("material_info_bank/default_fallback_mtd_name").InnerText.ToLower();

            var materialDefNodes = xml.SelectNodes("material_info_bank/material_def_list/material_def");

            MaterialDefs.Clear();

            foreach (XmlNode mdn in materialDefNodes)
            {
                var mat = new MaterialDef();
                mat.ReadXML(mdn);
                if (!MaterialDefs.ContainsKey(mat.MTD))
                {
                    MaterialDefs.Add(mat.MTD, mat);
                }
                else
                {
                    //throw new Exception($"MTD '{mat.MTD}' defined twice in material info bank.");
                    MaterialDefs[mat.MTD] = mat;
                }
            }

            GXItemStructs.Clear();

            var gxItemNodes = xml.SelectNodes("material_info_bank/gx_item_struct_list/gx_item_struct");

            foreach (XmlNode gin in gxItemNodes)
            {
                string gxid      = gin.SafeGetAttribute("gxid");
                var    structDef = new XmlStructDef(gin);
                GXItemStructs.Add(gxid, structDef);
            }

            DefaultGXItemDataExamples.Clear();

            var matExamples = xml.SelectNodes("material_info_bank/MATERIAL_INSTANCE_EXAMPLE_LIST/MATERIAL_INSTANCE_EXAMPLE");

            foreach (XmlNode matExNode in matExamples)
            {
                var mtd     = matExNode.SafeGetAttribute("mtd").ToLower();
                var exNodes = matExNode.SelectNodes("material_data_example");

                List <byte[]> gxExamplesForThisMtd = new List <byte[]>();

                foreach (XmlNode mx in exNodes)
                {
                    var gxExamples = mx.SelectNodes("gx_item_list/gx_item");
                    foreach (XmlNode gn in gxExamples)
                    {
                        byte[] gxData = gn.InnerText.Split(' ').Select(x => byte.Parse(x, System.Globalization.NumberStyles.HexNumber)).ToArray();
                        gxExamplesForThisMtd.Add(gxData);
                    }

                    break; // Read only one for now
                }

                if (!DefaultGXItemDataExamples.ContainsKey(mtd))
                {
                    DefaultGXItemDataExamples.Add(mtd, gxExamplesForThisMtd);
                }
            }
        }
Пример #9
0
        // TODO: Clean up this method, split in smaller parts, update it as more info is available
        private bool Read(BinaryReader br)
        {
            try
            {
                Header header = new Header();
                header.Read(br);
                NodesTree nodesTree = new NodesTree();
                nodesTree.Read(br);
                Name = nodesTree.name;
                br.BaseStream.Seek(header.ContentsTableOffset, SeekOrigin.Begin);
                ContentsTable contentsTable = new ContentsTable();
                contentsTable.Read(br);
                MaterialsHeader materialsHeader = new MaterialsHeader();
                materialsHeader.Read(br);
                ObjectsTable objectsTable = new ObjectsTable();
                objectsTable.SetCount(contentsTable.objectsCount);
                objectsTable.Read(br);
                SubObjectsTable subObjectsTable = new SubObjectsTable();
                subObjectsTable.SetCount(contentsTable.subObjectsCount);
                subObjectsTable.Read(br);

                // In theory, it could be read all the data from current stream position
                //      but it would be safer to read by using the already read offsets

                // Read the materials table
                MaterialsTable materialsTable = new MaterialsTable();
                materialsTable.SetCount(materialsHeader.materialsCount);
                br.BaseStream.Seek(materialsHeader.materialsTableOffset, SeekOrigin.Begin);
                materialsTable.Read(br);
                // Build the materials list
                for (int i = 0; i < materialsTable.GetCount(); i++)
                {
                    Material mat = materialsTable[i].GetMaterial(br);
                    Materials.Add(mat);
                }

                // TODO: Read data for all the subobjects


                // Read data for all the objects
                for (int i = 0; i < objectsTable.GetCount(); i++)
                {
                    Model model = new Model();
                    br.BaseStream.Seek(objectsTable[i].nameAddress, SeekOrigin.Begin);
                    model.name = Text.ReadText(br);
                    if (objectsTable[i].materialDefsAddress != null && objectsTable[i].materialDefsCount > 0)
                    {
                        br.BaseStream.Seek(objectsTable[i].materialDefsAddress.Value, SeekOrigin.Begin);
                        MaterialDef matDef = new MaterialDef();
                        matDef.Read(br);
                        model.materialIndices = matDef.materialIndices;
                    }
                    if (objectsTable[i].childDefsAddress != null && objectsTable[i].childsDefsCount > 0)
                    {
                        br.BaseStream.Seek(objectsTable[i].childDefsAddress.Value, SeekOrigin.Begin);
                        ChildsDef childsDef = new ChildsDef();
                        childsDef.SetCount(objectsTable[i].childsDefsCount);
                        childsDef.Read(br);
                        // TODO: Decide how to add it to the model
                    }
                    if (objectsTable[i].data1Address != null && objectsTable[i].data1Count > 0)
                    {
                        List <int> meshesAddress = new List <int>();
                        br.BaseStream.Seek(objectsTable[i].data1Address.Value, SeekOrigin.Begin);
                        for (int j = 0; j < objectsTable[i].data1Count; j++)
                        {
                            int address = (int)ReadRelativeOffset(br);
                            meshesAddress.Add(address);
                        }
                        for (int j = 0; j < objectsTable[i].data1Count; j++)
                        {
                            br.BaseStream.Seek(meshesAddress[j], SeekOrigin.Begin);
                            Def def = new Def();
                            if (!def.Read(br))
                            {
                                return(false);
                            }
                            if (def.nextChunk != null && def.nextChunk is MeshDef)
                            {
                                MeshDef md = (MeshDef)def.nextChunk;
                                for (int k = 0; k < md.meshesData.Count; k++)
                                {
                                    MeshData data = md.meshesData[k];
                                    Mesh     mesh = new Mesh(data.boundingBox, data.vertices, data.triangles, data.textureVertices);
                                    model.meshes.Add(mesh);
                                }
                            }
                        }
                    }
                    Models.Add(model);
                }
            }
            catch
            {
                // TODO: Handle here any error reading
                return(false);
            }
            return(true);
        }
Пример #10
0
    private Color LightTrace(Light light, Vector3 pos, Vector3 normal, Color diffuseColor, MaterialDef materialDef)
    {
        float diffuse;

        if (light.type == LightType.Directional)
        {
            diffuse = Vector3.Dot(-light.transform.forward, normal);
            if (diffuse > 0)
            {
                if (Physics.Raycast(pos, -light.transform.forward, Mathf.Infinity, collisionMask))
                {
                    return(RGBAZero);
                }

                Vector3 viewVector = (cameraToTrace.transform.position - pos).normalized;
                Vector3 halfVector = (-light.transform.forward + viewVector).normalized;
                float   dot        = Vector3.Dot(halfVector, normal);
                float   spec       = 0;
                if (dot > 0)
                {
                    spec = Mathf.Pow(dot, 128);
                }


                return(light.color * light.intensity * spec * materialDef.Ks + diffuseColor * diffuse * materialDef.Kd);
            }
        }
        else
        {
            float   distance  = Vector3.Distance(pos, light.transform.position);
            Vector3 direction = (light.transform.position - pos).normalized;
            diffuse = Vector3.Dot(normal, direction);

            if (distance < light.range && diffuse > 0)
            {
                if (light.type == LightType.Point)
                {
                    if (Physics.Raycast(pos, direction, distance, collisionMask))
                    {
                        return(RGBAZero);
                    }

                    Vector3 viewVector = (cameraToTrace.transform.position - pos).normalized;
                    Vector3 halfVector = (direction + viewVector).normalized;
                    float   dot        = Vector3.Dot(halfVector, normal);
                    float   spec       = 0;
                    if (dot > 0)
                    {
                        spec = Mathf.Pow(dot, 128);
                    }

                    float r           = distance / light.range;
                    float Attenuation = 1.0f + 25.0f * r * r;
                    return((light.color * spec * materialDef.Ks + diffuseColor * diffuse * materialDef.Kd) * light.intensity / Attenuation);
                }
                else if (light.type == LightType.Spot)
                {
                    float spotFactor  = Vector3.Dot(-light.transform.forward, direction);
                    float spotCulloff = Mathf.Cos((light.spotAngle / 2.0f) * Mathf.Deg2Rad);
                    if (spotFactor > spotCulloff)
                    {
                        if (Physics.Raycast(pos, direction, distance, collisionMask))
                        {
                            return(RGBAZero);
                        }

                        Vector3 viewVector = (cameraToTrace.transform.position - pos).normalized;
                        Vector3 halfVector = (direction + viewVector).normalized;
                        float   dot        = Vector3.Dot(halfVector, normal);
                        float   spec       = 0;
                        if (dot > 0)
                        {
                            spec = Mathf.Pow(dot, 128);
                        }


                        return((light.color * spec * materialDef.Ks + diffuseColor * diffuse * materialDef.Kd) * light.intensity * (1.0f - distance / light.range) * (1.0f - (1.0f - spotFactor) / (1.0f - spotCulloff)));
                    }
                }
                else if (light.type == LightType.Area)
                {
                    Color color = RGBAZero;

                    float   sampleNumber = 2;
                    Vector2 lightArea    = light.areaSize;
                    float   sampleRengeX = lightArea.x / sampleNumber;
                    float   sampleRengeY = lightArea.y / sampleNumber;
                    int     sampleX      = (int)(lightArea.x / sampleRengeX);
                    int     sampleY      = (int)(lightArea.y / sampleRengeY);
                    float   r            = distance / light.range;
                    float   Attenuation  = 1.0f + 25.0f * r * r;
                    for (int i = 0; i < sampleY; i++)
                    {
                        for (int j = 0; j < sampleX; j++)
                        {
                            float offsetRight = lightArea.x * (((sampleX - j) / sampleX) - 0.5f);
                            float offsetUp    = lightArea.y * (((sampleY - i) / sampleY) - 0.5f);
                            float u           = Random.Range(0.0f, 1f);
                            float v           = Random.Range(0.0f, 1f);
                            float sida        = 2 * Mathf.PI * u;
                            float radius      = Mathf.Sqrt(v);

                            //offsetRight = lightArea.x * Mathf.Cos(sida) * radius;
                            //offsetUp = lightArea.y * Mathf.Sin(sida) * radius;
                            Vector3 lightPos = light.transform.position + light.transform.right * offsetRight + light.transform.up * offsetUp;
                            if (Physics.Raycast(pos, (lightPos - pos).normalized, distance, collisionMask))
                            {
                                break;
                            }
                            Vector3 Ldirection = (lightPos - pos).normalized;
                            Vector3 viewVector = (cameraToTrace.transform.position - pos).normalized;
                            Vector3 halfVector = (Ldirection + viewVector).normalized;
                            float   dot        = Vector3.Dot(halfVector, normal);
                            float   spec       = 0;
                            if (dot > 0)
                            {
                                spec = Mathf.Pow(dot, 128);
                            }
                            color += (light.color * spec * materialDef.Ks + diffuseColor * diffuse * materialDef.Kd) / (sampleX * sampleY);
                            //integrate += (spec) * sampleRengeX * sampleRengeY;
                        }
                    }
                    color *= light.intensity / Attenuation;
                    //return (light.color * spec * materialDef.Ks + diffuseColor * diffuse * materialDef.Kd) * light.intensity / Attenuation;
                    return(color);
                }
            }
        }

        return(RGBAZero);
    }
Пример #11
0
    private Color TraceRay(Ray ray, int depth, MeshCollider lastHitCollider, bool innerRay, out Vector3 hitPosition)
    {
        Color color = RGBAZero;

        RaycastHit hit = new RaycastHit();

        hitPosition = Vector3.zero;

        if (depth < 5)
        {
            if (innerRay)
            {
                Ray inverseRay = new Ray();
                inverseRay.origin    = ray.GetPoint(999.0f);
                inverseRay.direction = -ray.direction;

                RaycastHit[] hits;
                hits = Physics.RaycastAll(inverseRay, 999, collisionMask);

                if (hits.Length <= 0)
                {
                    return(color);
                }
                else
                {
                    Vector3 offsetOrigin = ray.GetPoint(0.0001f);
                    float   maxDist      = -1;
                    for (int hitId = 0; hitId < hits.Length; ++hitId)
                    {
                        Vector3 hitDir = (hits[hitId].point - offsetOrigin).normalized;
                        if (Vector3.Dot(hitDir, ray.direction) > 0)
                        {
                            float distToOrigin = Vector3.Distance(hits[hitId].point, inverseRay.origin);
                            if (distToOrigin > maxDist)
                            {
                                maxDist = distToOrigin;
                                hit     = hits[hitId];
                            }
                        }
                    }

                    if (maxDist < 0)
                    {
                        return(color);
                    }
                }
            }
            else
            {
                if (!Physics.Raycast(ray, out hit, Mathf.Infinity, collisionMask))
                {
                    return(color);
                }
            }


            MaterialDef  materialDef       = hit.transform.GetComponent <MaterialDef>();
            MeshCollider collider          = hit.collider as MeshCollider;
            Mesh         mesh              = collider.sharedMesh;
            int[]        triangles         = mesh.triangles;
            Vector3[]    normals           = mesh.normals;
            Vector3      barycentry        = hit.barycentricCoordinate;
            Vector3      interpolateNormal = normals[triangles[hit.triangleIndex * 3 + 0]] * barycentry.x +
                                             normals[triangles[hit.triangleIndex * 3 + 1]] * barycentry.y +
                                             normals[triangles[hit.triangleIndex * 3 + 2]] * barycentry.z;
            interpolateNormal.Normalize();
            interpolateNormal = hit.transform.TransformDirection(interpolateNormal);

            if (innerRay)
            {
                interpolateNormal = -interpolateNormal;
            }

            hitPosition = hit.point;

            switch (materialDef.materialType)
            {
            case MaterialType.REFLECTION_AND_REFRACTION:
            {
                Vector3 inDir           = ray.direction;
                Color   newDiffuseColor = RGBAZero;

                float kr;
                fresnel(inDir, interpolateNormal, materialDef.Ior, out kr);

                //reflect
                Vector3 reflectionDir    = Vector3.Reflect(inDir, interpolateNormal);
                Vector3 reflectionOrigin = (Vector3.Dot(reflectionDir, interpolateNormal) < 0) ? (hit.point - interpolateNormal * 0.00001f) : (hit.point + interpolateNormal * 0.00001f);
                Vector3 reflectionHitPosition;
                Color   reflectionColor = TraceRay(new Ray(reflectionOrigin, reflectionDir), depth + 1, collider, innerRay, out reflectionHitPosition);
                newDiffuseColor += reflectionColor * kr;

                Vector3 refractionDir         = Vector3.zero;
                Vector3 refractionOrigin      = Vector3.zero;
                Vector3 refractionHitPosition = Vector3.zero;
                //refract
                if (kr < 1.0f)
                {
                    refractionDir    = refract(inDir, interpolateNormal, materialDef.Ior);
                    refractionOrigin = (Vector3.Dot(refractionDir, interpolateNormal) < 0) ? (hit.point - interpolateNormal * 0.00001f) : (hit.point + interpolateNormal * 0.00001f);
                    Color refractionColor = TraceRay(new Ray(refractionOrigin, refractionDir), depth + 1, collider, !innerRay, out refractionHitPosition);


                    float absorbDist = 0;
                    float absorbR    = 1;
                    float absorbG    = 1;
                    float absorbB    = 1;
                    if ((depth + 1 < 5) && !innerRay)
                    {
                        absorbDist = Vector3.Distance(hit.point, refractionHitPosition);
                        absorbR    = Mathf.Exp(-materialDef.ColorAbsorb.x * absorbDist);
                        absorbG    = Mathf.Exp(-materialDef.ColorAbsorb.y * absorbDist);
                        absorbB    = Mathf.Exp(-materialDef.ColorAbsorb.z * absorbDist);
                    }


                    newDiffuseColor += refractionColor * (1 - kr) * new Color(absorbR, absorbG, absorbB);
                }



                if (drawDebugRay)
                {
                    if (kr < 1.0f)
                    {
                        Debug.DrawLine(refractionOrigin, refractionHitPosition, Color.blue, 10.0f);
                    }
                    Debug.DrawLine(reflectionOrigin, reflectionHitPosition, Color.black, 10.0f);
                    Debug.DrawLine(hit.point, hit.point + interpolateNormal * 5, Color.green, 10.0f);
                }

                color = TraceLight(hit.point + interpolateNormal * 0.00001f, interpolateNormal, RGBAZero, materialDef) + newDiffuseColor;
            }
            break;

            case MaterialType.REFLECTION:
            {
                Vector3 inDir = ray.direction;
                float   kr;
                fresnel(inDir, interpolateNormal, materialDef.Ior, out kr);
                Vector3 reflectionDir    = Vector3.Reflect(inDir, interpolateNormal);
                Vector3 reflectionOrigin = (Vector3.Dot(reflectionDir, interpolateNormal) < 0) ? (hit.point + interpolateNormal * 0.00001f) : (hit.point - interpolateNormal * 0.00001f);
                Ray     reflectionRay    = new Ray(reflectionOrigin, reflectionDir);

                Vector3 reflectionHitPosition;
                color = TraceRay(reflectionRay, depth + 1, collider, innerRay, out reflectionHitPosition) * kr + TraceLight(hit.point + interpolateNormal * 0.00001f, interpolateNormal, RGBAZero, materialDef);

                if (drawDebugRay)
                {
                    Debug.DrawLine(reflectionOrigin, reflectionHitPosition, Color.red, 10.0f);
                    Debug.DrawLine(hit.point, hit.point + interpolateNormal * 5, Color.green, 10.0f);
                }
            }
            break;

            case MaterialType.DIFFUSE_AND_GLOSSY:
            {
                Color    diffuseColor = RGBAZero;
                Material mat          = hit.transform.GetComponent <Renderer>().material;
                if (mat.mainTexture != null)
                {
                    Vector2 texCoord = hit.textureCoord;
                    diffuseColor += (mat.mainTexture as Texture2D).GetPixelBilinear(texCoord.x, texCoord.y);
                }
                else
                {
                    diffuseColor += mat.color;
                }

                color = TraceLight(hit.point + interpolateNormal * 0.00001f, interpolateNormal, diffuseColor, materialDef);

                if (drawDebugRay)
                {
                    Debug.DrawLine(hit.point, hit.point + interpolateNormal * 5, Color.green, 10.0f);
                }
            }
            break;

            default:
                break;
            }
        }

        return(color);
    }
Пример #12
0
        public bool hasTrianglesFor(MaterialDef m)
        {
            List <Tri> t = new List <Tri>(TrianglesFor(m));

            return(t.Count != 0);
        }