コード例 #1
0
ファイル: SceneImporter.cs プロジェクト: vardrop/KWEngine2
        private static void ProcessMeshes(Scene scene, ref GeoModel model)
        {
            model.MeshHitboxes = new List <GeoMeshHitbox>();

            string        currentMeshName = null;
            GeoMeshHitbox meshHitBox = null;
            float         minX = float.MaxValue, minY = float.MaxValue, minZ = float.MaxValue;
            float         maxX = float.MinValue, maxY = float.MinValue, maxZ = float.MinValue;
            Matrix4       nodeTransform = Matrix4.Identity;
            Mesh          mesh          = null;

            for (int m = 0; m < scene.MeshCount; m++)
            {
                mesh = scene.Meshes[m];
                bool isNewMesh = currentMeshName != null && mesh.Name != currentMeshName && model.Filename != "kwcube6.obj";

                if (mesh.PrimitiveType != PrimitiveType.Triangle)
                {
                    throw new Exception("Model's primitive type is not set to 'triangles'. Cannot import model.");
                }

                if (isNewMesh)
                {
                    if (currentMeshName != null)
                    {
                        // Generate hitbox for the previous mesh:
                        meshHitBox           = new GeoMeshHitbox(maxX, maxY, maxZ, minX, minY, minZ, currentMeshName.ToLower().Contains("_fullhitbox") ? mesh : null);
                        meshHitBox.Model     = model;
                        meshHitBox.Name      = currentMeshName;
                        meshHitBox.Transform = nodeTransform;
                        meshHitBox.IsActive  = !currentMeshName.ToLower().Contains("_nohitbox");
                        model.MeshHitboxes.Add(meshHitBox);
                    }
                    minX = float.MaxValue;
                    minY = float.MaxValue;
                    minZ = float.MaxValue;

                    maxX = float.MinValue;
                    maxY = float.MinValue;
                    maxZ = float.MinValue;
                }

                currentMeshName = mesh.Name;

                GeoMesh geoMesh         = new GeoMesh();
                Matrix4 parentTransform = Matrix4.Identity;
                bool    transformFound  = FindTransformForMesh(scene, scene.RootNode, mesh, ref nodeTransform, out string nodeName, ref parentTransform);
                geoMesh.Transform = nodeTransform;
                geoMesh.Terrain   = null;
                geoMesh.BoneTranslationMatrixCount = mesh.BoneCount;
                geoMesh.Name      = mesh.Name + " #" + m.ToString().PadLeft(4, '0') + " (Node: " + nodeName + ")";
                geoMesh.NameOrg   = mesh.Name;
                geoMesh.Vertices  = new GeoVertex[mesh.VertexCount];
                geoMesh.Primitive = OpenTK.Graphics.OpenGL4.PrimitiveType.Triangles;
                geoMesh.VAOGenerateAndBind();

                for (int i = 0; i < mesh.VertexCount; i++)
                {
                    Vector3D vertex = mesh.Vertices[i];
                    if (vertex.X > maxX)
                    {
                        maxX = vertex.X;
                    }
                    if (vertex.Y > maxY)
                    {
                        maxY = vertex.Y;
                    }
                    if (vertex.Z > maxZ)
                    {
                        maxZ = vertex.Z;
                    }
                    if (vertex.X < minX)
                    {
                        minX = vertex.X;
                    }
                    if (vertex.Y < minY)
                    {
                        minY = vertex.Y;
                    }
                    if (vertex.Z < minZ)
                    {
                        minZ = vertex.Z;
                    }

                    GeoVertex geoVertex = new GeoVertex(i, vertex.X, vertex.Y, vertex.Z);
                    geoMesh.Vertices[i] = geoVertex;
                }
                geoMesh.Indices = mesh.GetUnsignedIndices();

                if (model.HasBones)
                {
                    for (int i = 0; i < mesh.BoneCount; i++)
                    {
                        Bone bone = mesh.Bones[i];

                        geoMesh.BoneNames.Add(bone.Name);
                        geoMesh.BoneIndices.Add(i);
                        geoMesh.BoneOffset.Add(HelperMatrix.ConvertAssimpToOpenTKMatrix(bone.OffsetMatrix));

                        foreach (VertexWeight vw in bone.VertexWeights)
                        {
                            int weightIndexToBeSet = geoMesh.Vertices[vw.VertexID].WeightSet;
                            if (weightIndexToBeSet >= KWEngine.MAX_BONE_WEIGHTS)
                            {
                                throw new Exception("Model's bones have more than three weights per vertex. Cannot import model.");
                            }

                            //Debug.WriteLine("Setting Vertex " + vw.VertexID + " with BoneID " + i + " and Weight: " + vw.Weight + " to Slot #" + weightIndexToBeSet);
                            geoMesh.Vertices[vw.VertexID].Weights[weightIndexToBeSet] = vw.Weight;
                            geoMesh.Vertices[vw.VertexID].BoneIDs[weightIndexToBeSet] = i;
                            geoMesh.Vertices[vw.VertexID].WeightSet++;
                        }
                    }
                }

                geoMesh.VBOGenerateIndices();
                geoMesh.VBOGenerateVerticesAndBones(model.HasBones);
                geoMesh.VBOGenerateNormals(mesh);
                geoMesh.VBOGenerateTangents(mesh);
                if (model.Filename == "kwcube.obj")
                {
                    geoMesh.VBOGenerateTextureCoords1(mesh, scene, 1);
                }
                else if (model.Filename == "kwcube6.obj")
                {
                    geoMesh.VBOGenerateTextureCoords1(mesh, scene, 6);
                }
                else if (model.Filename == "kwsphere.obj")
                {
                    geoMesh.VBOGenerateTextureCoords1(mesh, scene, 2);
                }
                else
                {
                    geoMesh.VBOGenerateTextureCoords1(mesh, scene);
                }
                geoMesh.VBOGenerateTextureCoords2(mesh);

                ProcessMaterialsForMesh(scene, mesh, ref model, ref geoMesh, model.Filename == "kwcube.obj" || model.Filename == "kwcube6.obj");



                geoMesh.VAOUnbind();

                model.Meshes.Add(geoMesh.Name, geoMesh);
            }

            // Generate hitbox for the last mesh:
            if (currentMeshName != null)
            {
                meshHitBox           = new GeoMeshHitbox(maxX, maxY, maxZ, minX, minY, minZ, currentMeshName.ToLower().Contains("_fullhitbox") ? mesh : null);
                meshHitBox.Model     = model;
                meshHitBox.Name      = model.Filename == "kwcube6.obj" ? "KWCube6" : currentMeshName;
                meshHitBox.Transform = nodeTransform;
                meshHitBox.IsActive  = !currentMeshName.ToLower().Contains("_nohitbox");
                model.MeshHitboxes.Add(meshHitBox);
            }

            foreach (GeoMeshHitbox hitbox in model.MeshHitboxes)
            {
                foreach (GeoMesh m in model.Meshes.Values)
                {
                    if (m.NameOrg == hitbox.Name)
                    {
                        hitbox.Mesh = m;
                        break;
                    }
                }
            }
        }
コード例 #2
0
ファイル: GeoTerrain.cs プロジェクト: vardrop/KWEngine2
        internal GeoMesh BuildTerrain(Vector3 position, string heightMap, float width, float height, float depth, float texRepeatX = 1, float texRepeatY = 1, bool isFile = true)
        {
            GeoMesh mmp;

            try
            {
                Assembly a = Assembly.GetEntryAssembly();
                using (Stream s = isFile ? File.Open(heightMap, FileMode.Open) : a.GetManifestResourceStream(a.GetName().Name + "." + heightMap))
                {
                    using (Bitmap image = new Bitmap(s))
                    {
                        mDots = image.Width * image.Height;

                        mWidth       = width;
                        mDepth       = depth;
                        mScaleFactor = height > 0 ? height : 1;
                        mTexX        = texRepeatX > 0 ? texRepeatX : 1;
                        mTexY        = texRepeatY > 0 ? texRepeatY : 1;

                        if (image.Width < 4 || image.Height < 4 || image.Height > 256 || image.Width > 256)
                        {
                            throw new Exception("Image size too small or too big: width and height need to be >= 4 and <= 256 pixels.");
                        }

                        Debug.WriteLine("Generating terrain from height map: " + heightMap);
                        double mp = Math.Round(mDots / 1000000.0, 3);
                        if (mDots > 1000)
                        {
                            Debug.WriteLine("\tImage pixel count:\t\t" + mp + " megapixel");
                            if (mp >= 0.5)
                            {
                                Debug.WriteLine("(WARNING: pixel count > 0.5 megapixel! You will experience SERIOUS performance issues with this terrain mapping.)");
                            }
                        }
                        else
                        {
                            Debug.WriteLine("\tImage pixel count:\t\t" + mDots);
                        }
                        long start = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;

                        mSectorSize = image.Width < image.Height ? (int)Math.Sqrt(image.Width) : (int)Math.Sqrt(image.Height);
                        while (mSectorSize % 4 != 0)
                        {
                            mSectorSize++;
                        }
                        mSectorSizeCoarse = mSectorSize / 4;

                        if (mSectorSize > 144)
                        {
                            mSectorSize       = 144;
                            mSectorSizeCoarse = 12;
                        }
                        mSectorWidth    = mWidth / mSectorSize;
                        mSectorDepth    = mDepth / mSectorSize;
                        mSectorDiameter = (float)Math.Sqrt(mSectorWidth * mSectorWidth + mSectorDepth * mSectorDepth);

                        mSectorWidthCoarse = mWidth / mSectorSizeCoarse;
                        mSectorDepthCoarse = mDepth / mSectorSizeCoarse;


                        for (int i = 0; i < mSectorSizeCoarse; i++)
                        {
                            for (int j = 0; j < mSectorSizeCoarse; j++)
                            {
                                Sector sec = new Sector(
                                    (position.X - mWidth / 2) + i * mSectorWidthCoarse,
                                    (position.X - mWidth / 2) + (i + 1) * mSectorWidthCoarse,

                                    (position.Z + mDepth / 2) - (j + 1) * mSectorDepthCoarse,
                                    (position.Z + mDepth / 2) - j * mSectorDepthCoarse
                                    );
                                mSectorsCoarse.Add(sec);
                                mSectorCoarseMap.Add(sec, new List <Sector>());
                            }
                        }

                        for (int i = 0; i < mSectorSize; i++)
                        {
                            for (int j = 0; j < mSectorSize; j++)
                            {
                                Sector sec = new Sector(
                                    (position.X - mWidth / 2) + i * mSectorWidth,
                                    (position.X - mWidth / 2) + (i + 1) * mSectorWidth,

                                    (position.Z + mDepth / 2) - (j + 1) * mSectorDepth,
                                    (position.Z + mDepth / 2) - j * mSectorDepth
                                    );
                                sec.ID = mSectors.Count;
                                mSectors.Add(sec);
                                Sector coarseSector = GetSectorCoarseForSector(sec);
                                mSectorCoarseMap[coarseSector].Add(sec);
                                mSectorTriangleMap.Add(mSectors.Count - 1, new List <GeoTerrainTriangle>());
                            }
                        }

                        float[,] mHeightMap = new float[image.Width, image.Height];
                        mCompleteDiameter   = (float)Math.Sqrt(mWidth * mWidth + mDepth * mDepth + mScaleFactor * mScaleFactor);

                        float     stepWidth                          = mWidth / (image.Width - 1);
                        float     stepDepth                          = mDepth / (image.Height - 1);
                        Vector3[] points                             = new Vector3[mDots];
                        int       c                                  = 0;
                        int       cFBuffer                           = 0;
                        int       cFBufferUV                         = 0;
                        float[]   VBOVerticesBuffer                  = new float[mDots * 3];
                        float[]   VBONormalsBuffer                   = new float[mDots * 3];
                        float[]   VBOUVBuffer                        = new float[mDots * 2];
                        float[]   VBOTangentBuffer                   = new float[mDots * 3];
                        float[]   VBOBiTangentBuffer                 = new float[mDots * 3];
                        Dictionary <int, Vector3> normalMapping      = new Dictionary <int, Vector3>();
                        Dictionary <int, Vector3> tangentMapping     = new Dictionary <int, Vector3>();
                        Dictionary <int, Vector3> bitangentMapping   = new Dictionary <int, Vector3>();
                        Dictionary <int, int>     normalMappingCount = new Dictionary <int, int>();

                        for (int i = 0; i < image.Width; i++)
                        {
                            for (int j = 0; j < image.Height; j++)
                            {
                                Color tmpColor      = image.GetPixel(i, j);
                                float normalizedRGB = ((tmpColor.R + tmpColor.G + tmpColor.B) / 3f) / 255f;
                                mHeightMap[i, j] = normalizedRGB;

                                Vector3 tmp = new Vector3(
                                    position.X + i * stepWidth - mWidth / 2,
                                    position.Y + mScaleFactor * normalizedRGB,
                                    position.Z - mDepth / 2 + j * stepDepth
                                    );
                                points[c] = tmp;
                                VBOVerticesBuffer[cFBuffer + 0] = points[c].X;
                                VBOVerticesBuffer[cFBuffer + 1] = points[c].Y;
                                VBOVerticesBuffer[cFBuffer + 2] = points[c].Z;

                                VBOUVBuffer[cFBufferUV + 0] = i * (1f / (image.Width - 1));  //* mTexX;
                                VBOUVBuffer[cFBufferUV + 1] = j * (1f / (image.Height - 1)); // * mTexY;

                                normalMapping.Add(c, new Vector3(0, 0, 0));
                                tangentMapping.Add(c, new Vector3(0, 0, 0));
                                bitangentMapping.Add(c, new Vector3(0, 0, 0));
                                normalMappingCount.Add(c, 0);

                                //increase counter:
                                c++;
                                cFBuffer   += 3;
                                cFBufferUV += 2;
                            }
                        }

                        mmp      = new GeoMesh();
                        mmp.Name = heightMap;

                        // Build indices and triangles:
                        mmp.VAO = GL.GenVertexArray();
                        GL.BindVertexArray(mmp.VAO);

                        int         triangles   = 0;
                        List <uint> mIndices    = new List <uint>();
                        int         imageHeight = image.Height;
                        Vector3     normalT1    = new Vector3(0, 0, 0);
                        Vector3     normalT2    = new Vector3(0, 0, 0);

                        float   deltaU1   = 0;
                        float   deltaV1   = 0;
                        float   deltaU2   = 0;
                        float   deltaV2   = 0;
                        float   f         = 1.0f;
                        Vector3 tangent   = new Vector3(0, 0, 0);
                        Vector3 bitangent = new Vector3(0, 0, 0);
                        for (int i = 0; i < points.Length - imageHeight - 1; i++)
                        {
                            Vector3 tmp;

                            if ((i + 1) % imageHeight == 0)
                            {
                                continue;
                            }

                            // Generate Indices:
                            mIndices.Add((uint)(i + imageHeight + 1));
                            mIndices.Add((uint)(i + imageHeight));
                            mIndices.Add((uint)(i));


                            mIndices.Add((uint)(i));
                            mIndices.Add((uint)(i + 1));
                            mIndices.Add((uint)(i + imageHeight + 1));

                            // Generate Triangle objects:

                            // T1:
                            Vector3            v1   = new Vector3(points[i + imageHeight + 1]);
                            Vector3            v2   = new Vector3(points[i + imageHeight]);
                            Vector3            v3   = new Vector3(points[i]);
                            GeoTerrainTriangle t123 = new GeoTerrainTriangle(v1, v2, v3);
                            normalT1 = t123.Normal;
                            List <int> sectorIds = GetSectorsForGeoTriangle(t123);
                            foreach (int sID in sectorIds)
                            {
                                mSectorTriangleMap[sID].Add(t123);
                            }

                            // tangents and bitangent generation
                            deltaU1 = VBOUVBuffer[(i + imageHeight) * 2] - VBOUVBuffer[(i + imageHeight + 1) * 2];
                            deltaV1 = VBOUVBuffer[(i + imageHeight) * 2 + 1] - VBOUVBuffer[(i + imageHeight + 1) * 2 + 1];
                            deltaU2 = VBOUVBuffer[(i + 0) * 2] - VBOUVBuffer[(i + imageHeight + 1) * 2];
                            deltaV2 = VBOUVBuffer[(i + 0) * 2 + 1] - VBOUVBuffer[(i + imageHeight + 1) * 2 + 1];
                            f       = 1.0f / (deltaU1 * deltaV2 - deltaU2 * deltaV1);

                            tangent.X = f * (deltaV2 * t123.edge1.X - deltaV1 * t123.edge2.X);
                            tangent.Y = f * (deltaV2 * t123.edge1.Y - deltaV1 * t123.edge2.Y);
                            tangent.Z = f * (deltaV2 * t123.edge1.Z - deltaV1 * t123.edge2.Z);

                            bitangent.X = f * (-deltaU2 * t123.edge1.X - deltaU1 * t123.edge2.X);
                            bitangent.Y = f * (-deltaU2 * t123.edge1.Y - deltaU1 * t123.edge2.Y);
                            bitangent.Z = f * (-deltaU2 * t123.edge1.Z - deltaU1 * t123.edge2.Z);

                            // Generate their normals for VBO:
                            normalMapping.TryGetValue(i, out tmp);
                            tmp += normalT1;
                            normalMapping[i] = tmp;
                            normalMappingCount[i]++;

                            normalMapping.TryGetValue(i + imageHeight, out tmp);
                            tmp += normalT1;
                            normalMapping[i + imageHeight] = tmp;
                            normalMappingCount[i + imageHeight]++;

                            normalMapping.TryGetValue(i + imageHeight + 1, out tmp);
                            tmp += normalT1;
                            normalMapping[i + imageHeight + 1] = tmp;
                            normalMappingCount[i + imageHeight + 1]++;

                            // map tangents & bitangent here:
                            tangentMapping.TryGetValue(i, out tmp);
                            tmp += tangent;
                            tangentMapping[i] = tmp;
                            tangentMapping.TryGetValue(i + imageHeight, out tmp);
                            tmp += tangent;
                            tangentMapping[i + imageHeight] = tmp;
                            tangentMapping.TryGetValue(i + imageHeight + 1, out tmp);
                            tmp += tangent;
                            tangentMapping[i + imageHeight + 1] = tmp;

                            bitangentMapping.TryGetValue(i, out tmp);
                            tmp += bitangent;
                            bitangentMapping[i] = tmp;
                            bitangentMapping.TryGetValue(i + imageHeight, out tmp);
                            tmp += bitangent;
                            bitangentMapping[i + imageHeight] = tmp;
                            bitangentMapping.TryGetValue(i + imageHeight + 1, out tmp);
                            tmp += bitangent;
                            bitangentMapping[i + imageHeight + 1] = tmp;



                            // ============================ T2 ======================

                            Vector3            v4   = new Vector3(points[i]);
                            Vector3            v5   = new Vector3(points[i + 1]);
                            Vector3            v6   = new Vector3(points[i + imageHeight + 1]);
                            GeoTerrainTriangle t456 = new GeoTerrainTriangle(v4, v5, v6);
                            normalT2 = t456.Normal;
                            sectorIds.Clear();
                            sectorIds = GetSectorsForGeoTriangle(t456);
                            foreach (int sID in sectorIds)
                            {
                                mSectorTriangleMap[sID].Add(t456);
                            }

                            // tangents and bitangent generation
                            deltaU1 = VBOUVBuffer[(i + 1) * 2] - VBOUVBuffer[(i) * 2];
                            deltaV1 = VBOUVBuffer[(i + 1) * 2 + 1] - VBOUVBuffer[(i) * 2 + 1];
                            deltaU2 = VBOUVBuffer[(i + imageHeight + 1) * 2] - VBOUVBuffer[(i) * 2];
                            deltaV2 = VBOUVBuffer[(i + imageHeight + 1) * 2 + 1] - VBOUVBuffer[(i) * 2 + 1];
                            f       = 1.0f / (deltaU1 * deltaV2 - deltaU2 * deltaV1);

                            tangent.X = f * (deltaV2 * t456.edge1.X - deltaV1 * t456.edge2.X);
                            tangent.Y = f * (deltaV2 * t456.edge1.Y - deltaV1 * t456.edge2.Y);
                            tangent.Z = f * (deltaV2 * t456.edge1.Z - deltaV1 * t456.edge2.Z);

                            bitangent.X = f * (-deltaU2 * t456.edge1.X - deltaU1 * t456.edge2.X);
                            bitangent.Y = f * (-deltaU2 * t456.edge1.Y - deltaU1 * t456.edge2.Y);
                            bitangent.Z = f * (-deltaU2 * t456.edge1.Z - deltaU1 * t456.edge2.Z);

                            normalMapping.TryGetValue(i + imageHeight + 1, out tmp);
                            tmp += normalT2;
                            normalMapping[i + imageHeight + 1] = tmp;
                            normalMappingCount[i + imageHeight + 1]++;

                            normalMapping.TryGetValue(i + 1, out tmp);
                            tmp += normalT2;
                            normalMapping[i + 1] = tmp;
                            normalMappingCount[i + 1]++;

                            normalMapping.TryGetValue(i, out tmp);
                            tmp += normalT2;
                            normalMapping[i] = tmp;
                            normalMappingCount[i]++;

                            // map tangents & bitangent here:
                            tangentMapping.TryGetValue(i + imageHeight + 1, out tmp);
                            tmp += tangent;
                            tangentMapping[i + imageHeight + 1] = tmp;
                            tangentMapping.TryGetValue(i + 1, out tmp);
                            tmp += tangent;
                            tangentMapping[i + 1] = tmp;
                            tangentMapping.TryGetValue(i, out tmp);
                            tmp += tangent;
                            tangentMapping[i] = tmp;

                            bitangentMapping.TryGetValue(i + imageHeight + 1, out tmp);
                            tmp += bitangent;
                            bitangentMapping[i + imageHeight + 1] = tmp;
                            bitangentMapping.TryGetValue(i + 1, out tmp);
                            tmp += bitangent;
                            bitangentMapping[i + 1] = tmp;
                            bitangentMapping.TryGetValue(i, out tmp);
                            tmp += bitangent;
                            bitangentMapping[i] = tmp;



                            triangles += 2;
                        }
                        Debug.WriteLine("\tGenerated triangles:\t" + triangles);
                        cFBuffer = 0;


                        for (int i = 0; i < points.Length; i++)
                        {
                            // Interpolate normals:
                            Vector3 tmp = new Vector3(normalMapping[i].X / normalMappingCount[i],
                                                      normalMapping[i].Y / normalMappingCount[i],
                                                      normalMapping[i].Z / normalMappingCount[i]);
                            tmp.Normalize();

                            Vector3 tTemp = new Vector3(tangentMapping[i].X / normalMappingCount[i],
                                                        tangentMapping[i].Y / normalMappingCount[i],
                                                        tangentMapping[i].Z / normalMappingCount[i]);
                            tTemp.Normalize();

                            Vector3 btTemp = new Vector3(bitangentMapping[i].X / normalMappingCount[i],
                                                         bitangentMapping[i].Y / normalMappingCount[i],
                                                         bitangentMapping[i].Z / normalMappingCount[i]);
                            btTemp.Normalize();

                            VBONormalsBuffer[cFBuffer + 0] = tmp.X;
                            VBONormalsBuffer[cFBuffer + 1] = tmp.Y;
                            VBONormalsBuffer[cFBuffer + 2] = tmp.Z;

                            // tangents and bitangents:
                            VBOTangentBuffer[cFBuffer + 0] = tTemp.X;
                            VBOTangentBuffer[cFBuffer + 1] = tTemp.Y;
                            VBOTangentBuffer[cFBuffer + 2] = tTemp.Z;

                            // tangents and bitangents:
                            VBOBiTangentBuffer[cFBuffer + 0] = btTemp.X;
                            VBOBiTangentBuffer[cFBuffer + 1] = btTemp.Y;
                            VBOBiTangentBuffer[cFBuffer + 2] = btTemp.Z;

                            cFBuffer += 3;
                        }

                        // Generate VBOs:
                        mmp.VBOPosition  = GL.GenBuffer();
                        mmp.VBONormal    = GL.GenBuffer();
                        mmp.VBOTexture1  = GL.GenBuffer();
                        mmp.VBOTangent   = GL.GenBuffer();
                        mmp.VBOBiTangent = GL.GenBuffer();
                        mmp.VBOIndex     = GL.GenBuffer();

                        // Vertices:
                        GL.BindBuffer(BufferTarget.ArrayBuffer, mmp.VBOPosition);
                        GL.BufferData(BufferTarget.ArrayBuffer, VBOVerticesBuffer.Length * 4, VBOVerticesBuffer, BufferUsageHint.StaticDraw);
                        GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 0, 0);
                        GL.EnableVertexAttribArray(0);
                        GL.BindBuffer(BufferTarget.ArrayBuffer, 0);

                        // Normals
                        GL.BindBuffer(BufferTarget.ArrayBuffer, mmp.VBONormal);
                        GL.BufferData(BufferTarget.ArrayBuffer, VBONormalsBuffer.Length * 4, VBONormalsBuffer, BufferUsageHint.StaticDraw);
                        GL.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, false, 0, 0);
                        GL.EnableVertexAttribArray(1);
                        GL.BindBuffer(BufferTarget.ArrayBuffer, 0);

                        // UVs
                        GL.BindBuffer(BufferTarget.ArrayBuffer, mmp.VBOTexture1);
                        GL.BufferData(BufferTarget.ArrayBuffer, VBOUVBuffer.Length * 4, VBOUVBuffer, BufferUsageHint.StaticDraw);
                        GL.VertexAttribPointer(2, 2, VertexAttribPointerType.Float, false, 0, 0);
                        GL.EnableVertexAttribArray(2);
                        GL.BindBuffer(BufferTarget.ArrayBuffer, 0);

                        // Tangents
                        GL.BindBuffer(BufferTarget.ArrayBuffer, mmp.VBOTangent);
                        GL.BufferData(BufferTarget.ArrayBuffer, VBOTangentBuffer.Length * 4, VBOTangentBuffer, BufferUsageHint.StaticDraw);
                        GL.VertexAttribPointer(4, 3, VertexAttribPointerType.Float, false, 0, 0);
                        GL.EnableVertexAttribArray(4);
                        GL.BindBuffer(BufferTarget.ArrayBuffer, 0);

                        // Bitangents
                        GL.BindBuffer(BufferTarget.ArrayBuffer, mmp.VBOBiTangent);
                        GL.BufferData(BufferTarget.ArrayBuffer, VBOBiTangentBuffer.Length * 4, VBOBiTangentBuffer, BufferUsageHint.StaticDraw);
                        GL.VertexAttribPointer(5, 3, VertexAttribPointerType.Float, false, 0, 0);
                        GL.EnableVertexAttribArray(5);
                        GL.BindBuffer(BufferTarget.ArrayBuffer, 0);

                        mmp.Indices = mIndices.ToArray();
                        // Indices:
                        GL.BindBuffer(BufferTarget.ElementArrayBuffer, mmp.VBOIndex);
                        GL.BufferData(BufferTarget.ElementArrayBuffer, mIndices.Count * 4, mmp.Indices, BufferUsageHint.StaticDraw);
                        GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0);


                        mmp.Transform = Matrix4.Identity;

                        GL.BindVertexArray(0);

                        long diff = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond - start;
                        Debug.WriteLine("\t...done (" + Math.Round(diff / 1000f, 2) + " seconds)");
                    }
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Terrain could not be created: " + ex.Message);
            }
            finally
            {
                GLWindow.StartGarbageCollection();
            }
            mmp.Primitive = PrimitiveType.Triangles;

            return(mmp);
        }
コード例 #3
0
ファイル: SceneImporter.cs プロジェクト: vardrop/KWEngine2
        private static void ProcessMaterialsForMesh(Scene scene, Mesh mesh, ref GeoModel model, ref GeoMesh geoMesh, bool isKWCube = false)
        {
            GeoMaterial geoMaterial = new GeoMaterial();
            Material    material    = null;

            if (isKWCube)
            {
                if (mesh.MaterialIndex >= 0)
                {
                    material                  = scene.Materials[mesh.MaterialIndex];
                    geoMaterial.Name          = model.Filename == "kwcube.obj" ? "KWCube" : material.Name;
                    geoMaterial.BlendMode     = material.BlendMode == BlendMode.Default ? OpenTK.Graphics.OpenGL4.BlendingFactor.OneMinusSrcAlpha : OpenTK.Graphics.OpenGL4.BlendingFactor.One; // TODO: Check if this is correct!
                    geoMaterial.ColorDiffuse  = new Vector4(1, 1, 1, 1);
                    geoMaterial.ColorEmissive = new Vector4(0, 0, 0, 1);
                }
                else
                {
                    geoMaterial.Name          = "kw-undefined.";
                    geoMaterial.BlendMode     = OpenTK.Graphics.OpenGL4.BlendingFactor.OneMinusSrcAlpha;
                    geoMaterial.ColorDiffuse  = new Vector4(1, 1, 1, 1);
                    geoMaterial.ColorEmissive = new Vector4(0, 0, 0, 1);
                }
                geoMaterial.SpecularArea  = 1024;
                geoMaterial.SpecularPower = 0;
            }
            else
            {
                if (mesh.MaterialIndex >= 0)
                {
                    material         = scene.Materials[mesh.MaterialIndex];
                    geoMaterial.Name = material.Name;

                    if (material.Name == "DefaultMaterial")
                    {
                        geoMaterial.BlendMode     = OpenTK.Graphics.OpenGL4.BlendingFactor.OneMinusSrcAlpha;
                        geoMaterial.ColorDiffuse  = new Vector4(1, 1, 1, 1);
                        geoMaterial.ColorEmissive = new Vector4(0, 0, 0, 1);
                        geoMaterial.SpecularPower = 0;
                        geoMaterial.SpecularArea  = 1024;
                        geoMaterial.TextureSpecularIsRoughness = false;
                        if (mesh.Name != null && mesh.Name.ToLower().Contains("_invisible"))
                        {
                            geoMaterial.Opacity = 0;
                        }
                    }
                    else
                    {
                        geoMaterial.BlendMode = material.BlendMode == BlendMode.Default ? OpenTK.Graphics.OpenGL4.BlendingFactor.OneMinusSrcAlpha : OpenTK.Graphics.OpenGL4.BlendingFactor.One; // TODO: Check if this is correct!
                        if (model.AssemblyMode == AssemblyMode.Internal && material.Name == "System")
                        {
                            geoMaterial.ColorDiffuse = new Vector4(1, 1, 1, 1);
                        }
                        else if (model.AssemblyMode == AssemblyMode.Internal && material.Name == "X")
                        {
                            geoMaterial.ColorDiffuse = new Vector4(1, 0, 0, 1);
                        }
                        else if (model.AssemblyMode == AssemblyMode.Internal && material.Name == "Y")
                        {
                            geoMaterial.ColorDiffuse = new Vector4(0, 1, 0, 1);
                        }
                        else if (model.AssemblyMode == AssemblyMode.Internal && material.Name == "Z")
                        {
                            geoMaterial.ColorDiffuse = new Vector4(0, 0, 1, 1);
                        }
                        else
                        {
                            geoMaterial.ColorDiffuse = material.HasColorDiffuse ? new Vector4(material.ColorDiffuse.R, material.ColorDiffuse.G, material.ColorDiffuse.B, material.ColorDiffuse.A) : new Vector4(1, 1, 1, 1);
                        }
                        geoMaterial.ColorEmissive = material.HasColorEmissive ? new Vector4(material.ColorEmissive.R, material.ColorEmissive.G, material.ColorEmissive.B, material.ColorEmissive.A) : new Vector4(0, 0, 0, 1);
                        geoMaterial.SpecularPower = material.ShininessStrength;
                        geoMaterial.SpecularArea  = material.Shininess;
                        geoMaterial.TextureSpecularIsRoughness = false;
                        geoMaterial.Opacity = material.HasOpacity ? material.Opacity : 1;
                        if (mesh.Name != null && mesh.Name.ToLower().Contains("_invisible"))
                        {
                            geoMaterial.Opacity = 0;
                        }
                    }
                }
                else
                {
                    geoMaterial.Name          = "kw-undefined.";
                    geoMaterial.BlendMode     = OpenTK.Graphics.OpenGL4.BlendingFactor.OneMinusSrcAlpha;
                    geoMaterial.ColorDiffuse  = new Vector4(1, 1, 1, 1);
                    geoMaterial.ColorEmissive = new Vector4(0, 0, 0, 1);
                    geoMaterial.SpecularArea  = 1024;
                    geoMaterial.SpecularPower = 0;
                    geoMaterial.TextureSpecularIsRoughness = false;
                    if (mesh.Name != null && mesh.Name.ToLower().Contains("_invisible"))
                    {
                        geoMaterial.Opacity = 0;
                    }
                }
            }

            // Process Textures:
            if (material != null)
            {
                bool          roughnessUsed      = false;
                TextureSlot[] texturesOfMaterial = material.GetAllMaterialTextures();
                foreach (TextureSlot slot in texturesOfMaterial)
                {
                    if (slot.TextureType == TextureType.Shininess) // this is PBR Roughness
                    {
                        GeoTexture tex = new GeoTexture();
                        tex.UVTransform = new OpenTK.Vector2(1, 1);
                        tex.Filename    = slot.FilePath;
                        tex.UVMapIndex  = slot.UVIndex;
                        if (model.Textures.ContainsKey(tex.Filename))
                        {
                            tex.OpenGLID = model.Textures[tex.Filename].OpenGLID;
                        }
                        else
                        {
                            if (model.AssemblyMode == AssemblyMode.File)
                            {
                                tex.OpenGLID = HelperTexture.LoadTextureForModelExternal(
                                    FindTextureInSubs(StripPathFromFile(tex.Filename), model.PathAbsolute), true
                                    );
                            }
                            else
                            {
                                string path = StripFileNameFromAssemblyPath(model.PathAbsolute).Substring(model.PathAbsolute.IndexOf('.') + 1) + StripPathFromFile(tex.Filename);
                                tex.OpenGLID = HelperTexture.LoadTextureForModelInternal(path, true);
                            }
                            if (tex.OpenGLID > 0)
                            {
                                tex.Type = GeoTexture.TexType.Specular;
                                model.Textures.Add(tex.Filename, tex);
                                geoMaterial.TextureSpecular            = tex;
                                geoMaterial.TextureSpecularIsRoughness = true;
                                roughnessUsed = true;
                            }
                            else
                            {
                                geoMaterial.TextureSpecular            = tex;
                                geoMaterial.TextureSpecularIsRoughness = false;
                                tex.OpenGLID = KWEngine.TextureBlack;
                            }
                        }
                        break;
                    }
                }


                // Diffuse texture
                if (material.HasTextureDiffuse)
                {
                    GeoTexture tex = new GeoTexture();
                    tex.UVTransform = new OpenTK.Vector2(1, 1);
                    tex.Filename    = material.TextureDiffuse.FilePath;
                    tex.UVMapIndex  = material.TextureDiffuse.UVIndex;
                    tex.Type        = GeoTexture.TexType.Diffuse;
                    if (model.Textures.ContainsKey(tex.Filename))
                    {
                        tex.OpenGLID = model.Textures[tex.Filename].OpenGLID;
                        geoMaterial.TextureDiffuse = tex;
                    }
                    else if (CheckIfOtherModelsShareTexture(tex.Filename, model.Path, out GeoTexture sharedTexture))
                    {
                        geoMaterial.TextureDiffuse = sharedTexture;
                    }
                    else
                    {
                        if (model.AssemblyMode == AssemblyMode.File)
                        {
                            tex.OpenGLID = HelperTexture.LoadTextureForModelExternal(
                                FindTextureInSubs(StripPathFromFile(tex.Filename), model.PathAbsolute)
                                );
                        }
                        else
                        {
                            string path = StripFileNameFromAssemblyPath(model.PathAbsolute).Substring(model.PathAbsolute.IndexOf('.') + 1) + StripPathFromFile(tex.Filename);
                            tex.OpenGLID = HelperTexture.LoadTextureForModelInternal(path, true);
                        }
                        if (tex.OpenGLID > 0)
                        {
                            geoMaterial.TextureDiffuse = tex;
                            model.Textures.Add(tex.Filename, tex);
                        }
                        else
                        {
                            tex.OpenGLID = KWEngine.TextureDefault;
                            geoMaterial.TextureDiffuse = tex;
                        }
                    }
                }

                // Normal map texture
                if (material.HasTextureNormal)
                {
                    GeoTexture tex = new GeoTexture();
                    tex.UVTransform = new OpenTK.Vector2(1, 1);
                    tex.Filename    = material.TextureNormal.FilePath;
                    tex.UVMapIndex  = material.TextureNormal.UVIndex;
                    tex.Type        = GeoTexture.TexType.Normal;
                    if (model.Textures.ContainsKey(tex.Filename))
                    {
                        tex.OpenGLID = model.Textures[tex.Filename].OpenGLID;
                        geoMaterial.TextureNormal = tex;
                    }
                    else if (CheckIfOtherModelsShareTexture(tex.Filename, model.Path, out GeoTexture sharedTexture))
                    {
                        geoMaterial.TextureNormal = sharedTexture;
                    }
                    else
                    {
                        if (model.AssemblyMode == AssemblyMode.File)
                        {
                            tex.OpenGLID = HelperTexture.LoadTextureForModelExternal(
                                FindTextureInSubs(StripPathFromFile(tex.Filename), model.PathAbsolute)
                                );
                        }
                        else
                        {
                            string path = StripFileNameFromAssemblyPath(model.PathAbsolute).Substring(model.PathAbsolute.IndexOf('.') + 1) + StripPathFromFile(tex.Filename);
                            tex.OpenGLID = HelperTexture.LoadTextureForModelInternal(path, true);
                        }
                        if (tex.OpenGLID > 0)
                        {
                            model.Textures.Add(tex.Filename, tex);
                            geoMaterial.TextureNormal = tex;
                        }
                        else
                        {
                            tex.OpenGLID = KWEngine.TextureBlack;
                            //geoMaterial.TextureNormal = tex;
                        }
                    }
                }

                // Specular map texture
                if (material.HasTextureSpecular && roughnessUsed == false)
                {
                    GeoTexture tex = new GeoTexture();
                    tex.UVTransform = new OpenTK.Vector2(1, 1);
                    tex.Filename    = material.TextureSpecular.FilePath;
                    tex.UVMapIndex  = material.TextureSpecular.UVIndex;
                    tex.Type        = GeoTexture.TexType.Specular;
                    if (model.Textures.ContainsKey(tex.Filename))
                    {
                        tex.OpenGLID = model.Textures[tex.Filename].OpenGLID;
                        geoMaterial.TextureSpecular = tex;
                    }
                    else if (CheckIfOtherModelsShareTexture(tex.Filename, model.Path, out GeoTexture sharedTexture))
                    {
                        geoMaterial.TextureSpecular = sharedTexture;
                    }
                    else
                    {
                        if (model.AssemblyMode == AssemblyMode.File)
                        {
                            tex.OpenGLID = HelperTexture.LoadTextureForModelExternal(
                                FindTextureInSubs(StripPathFromFile(tex.Filename), model.PathAbsolute)
                                );
                        }
                        else
                        {
                            string path = StripFileNameFromAssemblyPath(model.PathAbsolute).Substring(model.PathAbsolute.IndexOf('.') + 1) + StripPathFromFile(tex.Filename);
                            tex.OpenGLID = HelperTexture.LoadTextureForModelInternal(path, true);
                        }
                        if (tex.OpenGLID > 0)
                        {
                            geoMaterial.TextureSpecular = tex;

                            model.Textures.Add(tex.Filename, tex);
                        }
                        else
                        {
                            tex.OpenGLID = KWEngine.TextureBlack;
                            geoMaterial.TextureSpecular = tex;
                        }
                    }
                }
                else
                {
                    if (material.HasTextureSpecular && roughnessUsed)
                    {
                        Debug.WriteLine("Skipping specular texture for " + model.Filename + " because roughness texture was found.");
                    }
                }

                // Emissive map texture
                if (material.HasTextureEmissive)
                {
                    GeoTexture tex = new GeoTexture();
                    tex.UVTransform = new OpenTK.Vector2(1, 1);
                    tex.Filename    = material.TextureEmissive.FilePath;
                    tex.UVMapIndex  = material.TextureEmissive.UVIndex;
                    tex.Type        = GeoTexture.TexType.Emissive;
                    if (model.Textures.ContainsKey(tex.Filename))
                    {
                        tex.OpenGLID = model.Textures[tex.Filename].OpenGLID;
                        geoMaterial.TextureEmissive = tex;
                    }
                    else if (CheckIfOtherModelsShareTexture(tex.Filename, model.Path, out GeoTexture sharedTexture))
                    {
                        geoMaterial.TextureEmissive = sharedTexture;
                    }
                    else
                    {
                        if (model.AssemblyMode == AssemblyMode.File)
                        {
                            tex.OpenGLID = HelperTexture.LoadTextureForModelExternal(
                                FindTextureInSubs(StripPathFromFile(tex.Filename), model.PathAbsolute)
                                );
                        }
                        else
                        {
                            string path = StripFileNameFromAssemblyPath(model.PathAbsolute).Substring(model.PathAbsolute.IndexOf('.') + 1) + StripPathFromFile(tex.Filename);
                            tex.OpenGLID = HelperTexture.LoadTextureForModelInternal(path, true);
                        }
                        if (tex.OpenGLID > 0)
                        {
                            geoMaterial.TextureEmissive = tex;

                            model.Textures.Add(tex.Filename, tex);
                        }
                        else
                        {
                            tex.OpenGLID = KWEngine.TextureBlack;
                            geoMaterial.TextureEmissive = tex;
                        }
                    }
                }

                // Light map texture
                if (material.HasTextureLightMap)
                {
                    GeoTexture tex = new GeoTexture();
                    tex.UVTransform = new OpenTK.Vector2(1, 1);
                    tex.Filename    = material.TextureLightMap.FilePath;
                    tex.UVMapIndex  = material.TextureLightMap.UVIndex;
                    tex.Type        = GeoTexture.TexType.Light;
                    if (model.Textures.ContainsKey(tex.Filename))
                    {
                        tex.OpenGLID             = model.Textures[tex.Filename].OpenGLID;
                        geoMaterial.TextureLight = tex;
                    }
                    else if (CheckIfOtherModelsShareTexture(tex.Filename, model.Path, out GeoTexture sharedTexture))
                    {
                        geoMaterial.TextureLight = sharedTexture;
                    }
                    else
                    {
                        if (model.AssemblyMode == AssemblyMode.File)
                        {
                            tex.OpenGLID = HelperTexture.LoadTextureForModelExternal(
                                FindTextureInSubs(StripPathFromFile(tex.Filename), model.PathAbsolute)
                                );
                        }
                        else
                        {
                            string path = StripFileNameFromAssemblyPath(model.PathAbsolute).Substring(model.PathAbsolute.IndexOf('.') + 1) + StripPathFromFile(tex.Filename);
                            tex.OpenGLID = HelperTexture.LoadTextureForModelInternal(path, true);
                        }
                        if (tex.OpenGLID > 0)
                        {
                            model.Textures.Add(tex.Filename, tex);
                            geoMaterial.TextureLight = tex;
                        }
                        else
                        {
                            tex.OpenGLID = KWEngine.TextureBlack;
                            //geoMaterial.TextureLight = tex;
                        }
                    }
                }
            }

            geoMesh.Material = geoMaterial;
        }