// There can be a singleton of this because GL must always render on the UI thread and can't overlap this array private static void DrawToGLUsingBsp(Mesh meshToRender, Matrix4X4 meshToViewTransform, Matrix4X4 invMeshToViewTransform) { ImageBuffer lastFaceTexture = null; var bspFaceList = FaceBspTree.GetFacesInVisibiltyOrder(meshToRender.Faces, meshToRender.FaceBspTree, meshToViewTransform, invMeshToViewTransform); foreach (var face in bspFaceList) { if (face == null) { continue; } ImageBuffer faceTexture; meshToRender.FaceTexture.TryGetValue((face, 0), out faceTexture); if (faceTexture != lastFaceTexture) { // Make sure the GLMeshPlugin has a reference to hold onto the image so it does not go away before this. if (faceTexture != null) { ImageGlPlugin glPlugin = ImageGlPlugin.GetImageGlPlugin(faceTexture, true); GL.Enable(EnableCap.Texture2D); GL.BindTexture(TextureTarget.Texture2D, glPlugin.GLTextureHandle); } else { GL.Disable(EnableCap.Texture2D); } lastFaceTexture = faceTexture; } GL.Begin(BeginMode.Triangles); GL.Normal3(face.Normal.X, face.Normal.Y, face.Normal.Z); // load up the uvs if (faceTexture != null) { foreach (var vertex in face.AsUvTriangles()) { GL.TexCoord2(vertex.v0.uv); GL.Vertex3(vertex.v0.p); GL.TexCoord2(vertex.v1.uv); GL.Vertex3(vertex.v1.p); GL.TexCoord2(vertex.v2.uv); GL.Vertex3(vertex.v2.p); } } else { foreach (var vertex in face.AsTriangles()) { GL.Vertex3(vertex.p0); GL.Vertex3(vertex.p1); GL.Vertex3(vertex.p2); } } GL.End(); } }
public override void Render(IImageByte source, double x, double y, double angleRadians, double scaleX, double scaleY) { #if true Affine transform = GetTransform(); if (!transform.is_identity()) { if (scaleX != 1 || scaleY != 1) // || angleDegrees != 0) { throw new NotImplementedException(); } // TODO: <BUG> make this do rotation and scaling transform.transform(ref x, ref y); scaleX *= transform.sx; scaleY *= transform.sy; } #endif #if true // TODO: <BUG> make this do rotation and scaling RectangleInt sourceBounds = source.GetBounds(); sourceBounds.Offset((int)x, (int)y); RectangleInt destBounds = new RectangleInt((int)cachedClipRect.Left, (int)cachedClipRect.Bottom, (int)cachedClipRect.Right, (int)cachedClipRect.Top); if (!RectangleInt.DoIntersect(sourceBounds, destBounds)) { if (scaleX != 1 || scaleY != 1) // || angleDegrees != 0) { //throw new NotImplementedException(); } //return; } #endif ImageBuffer sourceAsImageBuffer = (ImageBuffer)source; ImageGlPlugin glPlugin = ImageGlPlugin.GetImageGlPlugin(sourceAsImageBuffer, false); // Prepare openGL for rendering PushOrthoProjection(); GL.Disable(EnableCap.Lighting); GL.Enable(EnableCap.Texture2D); GL.Disable(EnableCap.DepthTest); GL.Enable(EnableCap.Blend); GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha); GL.Translate(x, y, 0); GL.Rotate(MathHelper.RadiansToDegrees(angleRadians), 0, 0, 1); GL.Scale(scaleX, scaleY, 1); RGBA_Bytes color = RGBA_Bytes.White; GL.Color4((byte)color.Red0To255, (byte)color.Green0To255, (byte)color.Blue0To255, (byte)color.Alpha0To255); glPlugin.DrawToGL(); //Restore openGL state PopOrthoProjection(); }
// There can be a singleton of this because GL must always render on the UI thread and can't overlap this array private static void DrawToGLZSorted(Mesh mesh, Matrix4X4 meshToViewTransform, Matrix4X4 invMeshToViewTransform) { ImageBuffer lastFaceTexture = null; // var zSortedFaceList2 = mesh.GetFacesInVisibiltyOrder(meshToViewTransform); var zSortedFaceList = FaceBspTree.GetFacesInVisibiltyOrder(mesh, mesh.FaceBspTree, meshToViewTransform, invMeshToViewTransform); foreach (var face in zSortedFaceList) { if (face == -1) { continue; } FaceTextureData faceTexture; mesh.FaceTextures.TryGetValue(face, out faceTexture); if (faceTexture != null && faceTexture.image != lastFaceTexture) { // Make sure the GLMeshPlugin has a reference to hold onto the image so it does not go away before this. if (faceTexture != null) { var glPlugin = ImageGlPlugin.GetImageGlPlugin(faceTexture.image, true); GL.Enable(EnableCap.Texture2D); GL.BindTexture(TextureTarget.Texture2D, glPlugin.GLTextureHandle); } else { GL.Disable(EnableCap.Texture2D); } lastFaceTexture = faceTexture.image; } GL.Begin(BeginMode.Triangles); var normal = mesh.Faces[face].normal; GL.Normal3(normal.X, normal.Y, normal.Z); // load up the uvs if (faceTexture != null) { GL.TexCoord2(faceTexture.uv0); GL.Vertex3(mesh.Vertices[mesh.Faces[face].v0]); GL.TexCoord2(faceTexture.uv1); GL.Vertex3(mesh.Vertices[mesh.Faces[face].v1]); GL.TexCoord2(faceTexture.uv2); GL.Vertex3(mesh.Vertices[mesh.Faces[face].v2]); } else { GL.Vertex3(mesh.Vertices[mesh.Faces[face].v0]); GL.Vertex3(mesh.Vertices[mesh.Faces[face].v1]); GL.Vertex3(mesh.Vertices[mesh.Faces[face].v2]); } GL.End(); } }
public static ImageGlPlugin GetImageGlPlugin(ImageBuffer imageToGetDisplayListFor, bool createAndUseMipMaps, bool textureMagFilterLinear = true, bool clamp = true) { imagesWithCacheData.TryGetValue(imageToGetDisplayListFor.GetBuffer(), out ImageGlPlugin plugin); lock (glDataNeedingToBeDeleted) { // We run this in here to ensure that we are on the correct thread and have the correct // glcontext realized. for (int i = glDataNeedingToBeDeleted.Count - 1; i >= 0; i--) { int textureToDelete = glDataNeedingToBeDeleted[i].glTextureHandle; if (textureToDelete != -1 && glDataNeedingToBeDeleted[i].glContextId == contextId && glDataNeedingToBeDeleted[i].refreshCountCreatedOn == currentGlobalRefreshCount) // this is to leak on purpose on android for some gl that kills textures { GL.DeleteTextures(1, ref textureToDelete); if (removeGlDataCallBackHolder != null) { removeGlDataCallBackHolder.releaseAllGlData -= glDataNeedingToBeDeleted[i].DeleteTextureData; } } glDataNeedingToBeDeleted.RemoveAt(i); } } if (plugin != null && (imageToGetDisplayListFor.ChangedCount != plugin.imageUpdateCount || plugin.glData.refreshCountCreatedOn != currentGlobalRefreshCount || plugin.glData.glTextureHandle == -1)) { int textureToDelete = plugin.GLTextureHandle; if (plugin.glData.refreshCountCreatedOn == currentGlobalRefreshCount) { GL.DeleteTextures(1, ref textureToDelete); } plugin.glData.glTextureHandle = -1; imagesWithCacheData.Remove(imageToGetDisplayListFor.GetBuffer()); // use the original settings createAndUseMipMaps = plugin.createdWithMipMaps; clamp = plugin.clamp; plugin = null; } if (plugin == null) { var newPlugin = new ImageGlPlugin(); imagesWithCacheData.Add(imageToGetDisplayListFor.GetBuffer(), newPlugin); newPlugin.createdWithMipMaps = createAndUseMipMaps; newPlugin.clamp = clamp; newPlugin.glData.glContextId = contextId; newPlugin.CreateGlDataForImage(imageToGetDisplayListFor, textureMagFilterLinear); newPlugin.imageUpdateCount = imageToGetDisplayListFor.ChangedCount; newPlugin.glData.refreshCountCreatedOn = currentGlobalRefreshCount; if (removeGlDataCallBackHolder != null) { removeGlDataCallBackHolder.releaseAllGlData += newPlugin.glData.DeleteTextureData; } return(newPlugin); } return(plugin); }
static public ImageGlPlugin GetImageGlPlugin(ImageBuffer imageToGetDisplayListFor, bool createAndUseMipMaps, bool TextureMagFilterLinear = true) { ImageGlPlugin plugin; imagesWithCacheData.TryGetValue(imageToGetDisplayListFor.GetBuffer(), out plugin); using (TimedLock.Lock(glDataNeedingToBeDeleted, "GetImageGlPlugin")) { // We run this in here to ensure that we are on the correct thread and have the correct // glcontext realized. for (int i = glDataNeedingToBeDeleted.Count - 1; i >= 0; i--) { int textureToDelete = glDataNeedingToBeDeleted[i].glTextureHandle; if (glDataNeedingToBeDeleted[i].refreshCountCreatedOn == currentGlobalRefreshCount) { GL.DeleteTextures(1, ref textureToDelete); } glDataNeedingToBeDeleted.RemoveAt(i); } } #if ON_IMAGE_CHANGED_ALWAYS_CREATE_IMAGE if (plugin != null && (imageToGetDisplayListFor.ChangedCount != plugin.imageUpdateCount || plugin.glData.refreshCountCreatedOn != currentGlobalRefreshCount)) { int textureToDelete = plugin.GLTextureHandle; if (plugin.glData.refreshCountCreatedOn == currentGlobalRefreshCount) { GL.DeleteTextures(1, ref textureToDelete); } plugin.glData.glTextureHandle = 0; imagesWithCacheData.Remove(imageToGetDisplayListFor.GetBuffer()); plugin = null; } if (plugin == null) { ImageGlPlugin newPlugin = new ImageGlPlugin(); imagesWithCacheData.Add(imageToGetDisplayListFor.GetBuffer(), newPlugin); newPlugin.createdWithMipMaps = createAndUseMipMaps; newPlugin.CreateGlDataForImage(imageToGetDisplayListFor, TextureMagFilterLinear); newPlugin.imageUpdateCount = imageToGetDisplayListFor.ChangedCount; newPlugin.glData.refreshCountCreatedOn = currentGlobalRefreshCount; return newPlugin; } #else if (plugin == null) { ImageGlPlugin newPlugin = new ImageGlPlugin(); imagesWithCacheData.Add(imageToGetDisplayListFor.GetBuffer(), newPlugin); newPlugin.createdWithMipMaps = createAndUseMipMaps; newPlugin.CreateGlDataForImage(imageToGetDisplayListFor, TextureMagFilterLinear); newPlugin.imageUpdateCount = imageToGetDisplayListFor.ChangedCount; newPlugin.refreshCountCreatedOn = currentGlobalRefreshCount; return newPlugin; } if(imageToGetDisplayListFor.ChangedCount != plugin.imageUpdateCount || plugin.refreshCountCreatedOn != currentGlobalRefreshCount) { plugin.imageUpdateCount = imageToGetDisplayListFor.ChangedCount; plugin.refreshCountCreatedOn = currentGlobalRefreshCount; GL.BindTexture(TextureTarget.Texture2D, plugin.GLTextureHandle); // Create the texture switch (imageToGetDisplayListFor.BitDepth) { case 8: GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, imageToGetDisplayListFor.Width, imageToGetDisplayListFor.Height, PixelFormat.Luminance, PixelType.UnsignedByte, imageToGetDisplayListFor.GetBuffer()); break; case 24: // our bitmaps are not padded and GL is having a problem with them so don't use 24 bit unless you fix this. GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, imageToGetDisplayListFor.Width, imageToGetDisplayListFor.Height, PixelFormat.Bgr, PixelType.UnsignedByte, imageToGetDisplayListFor.GetBuffer()); break; case 32: GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, imageToGetDisplayListFor.Width, imageToGetDisplayListFor.Height, PixelFormat.Bgra, PixelType.UnsignedByte, imageToGetDisplayListFor.GetBuffer()); break; default: throw new NotImplementedException(); } if (plugin.createdWithMipMaps) { if (GLMajorVersion < 3) { switch (imageToGetDisplayListFor.BitDepth) { case 32: { ImageBuffer sourceImage = new ImageBuffer(imageToGetDisplayListFor); ImageBuffer tempImage = new ImageBuffer(sourceImage.Width / 2, sourceImage.Height / 2, 32, new BlenderBGRA()); tempImage.NewGraphics2D().Render(sourceImage, 0, 0, 0, .5, .5); int mipLevel = 1; while (sourceImage.Width > 1 && sourceImage.Height > 1) { GL.TexSubImage2D(TextureTarget.Texture2D, mipLevel++, 0, 0, tempImage.Width, tempImage.Height, PixelFormat.Bgra, PixelType.UnsignedByte, tempImage.GetBuffer()); sourceImage = new ImageBuffer(tempImage); tempImage = new ImageBuffer(Math.Max(1, sourceImage.Width / 2), Math.Max(1, sourceImage.Height / 2), 32, new BlenderBGRA()); tempImage.NewGraphics2D().Render(sourceImage, 0, 0, 0, (double)tempImage.Width / (double)sourceImage.Width, (double)tempImage.Height / (double)sourceImage.Height); } } break; default: throw new NotImplementedException(); } } else { GL.GenerateMipmap(GenerateMipmapTarget.Texture2D); } } } #endif return plugin; }
private static void DrawToGL(Mesh meshToRender, bool isTransparent, Matrix4X4?meshToViewTransform, bool blendTexture = true, bool allowBspRendering = true) { if (!blendTexture) { // Turn off default GL_MODULATE mode GL.TexEnv(TextureEnvironmentTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, GL_REPLACE); } if (meshToViewTransform != null && isTransparent && meshToRender.FaceBspTree != null && meshToRender.Faces.Count > 0 && allowBspRendering) { var invMeshToViewTransform = meshToViewTransform.Value; invMeshToViewTransform.Invert(); DrawToGLZSorted(meshToRender, meshToViewTransform.Value, invMeshToViewTransform); if (!blendTexture) { // Restore default GL_MODULATE mode GL.TexEnv(TextureEnvironmentTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, GL_MODULATE); } return; } var glMeshPlugin = GLMeshTrianglePlugin.Get(meshToRender); for (int i = 0; i < glMeshPlugin.subMeshs.Count; i++) { SubTriangleMesh subMesh = glMeshPlugin.subMeshs[i]; // Make sure the GLMeshPlugin has a reference to hold onto the image so it does not go away before this. if (subMesh.texture != null) { if (subMesh.texture.HasTransparency) { GL.Enable(EnableCap.Blend); } var glPlugin = ImageGlPlugin.GetImageGlPlugin(subMesh.texture, true); GL.Enable(EnableCap.Texture2D); GL.BindTexture(TextureTarget.Texture2D, glPlugin.GLTextureHandle); GL.EnableClientState(ArrayCap.TextureCoordArray); } else { GL.Disable(EnableCap.Texture2D); GL.DisableClientState(ArrayCap.TextureCoordArray); } if (subMesh.UseVertexColors) { GL.EnableClientState(ArrayCap.ColorArray); } GL.EnableClientState(ArrayCap.NormalArray); GL.EnableClientState(ArrayCap.VertexArray); unsafe { fixed(VertexTextureData *pTextureData = subMesh.textureData.Array) { fixed(VertexColorData *pColorData = subMesh.colorData.Array) { fixed(VertexNormalData *pNormalData = subMesh.normalData.Array) { fixed(VertexPositionData *pPosition = subMesh.positionData.Array) { GL.VertexPointer(3, VertexPointerType.Float, 0, new IntPtr(pPosition)); GL.NormalPointer(NormalPointerType.Float, 0, new IntPtr(pNormalData)); GL.TexCoordPointer(2, TexCordPointerType.Float, 0, new IntPtr(pTextureData)); if (pColorData != null) { GL.ColorPointer(3, ColorPointerType.UnsignedByte, 0, new IntPtr(pColorData)); } GL.DrawArrays(BeginMode.Triangles, 0, subMesh.positionData.Count); } } } } } GL.DisableClientState(ArrayCap.NormalArray); GL.DisableClientState(ArrayCap.VertexArray); GL.DisableClientState(ArrayCap.TextureCoordArray); GL.DisableClientState(ArrayCap.ColorArray); GL.TexCoordPointer(2, TexCordPointerType.Float, 0, new IntPtr(0)); GL.ColorPointer(3, ColorPointerType.UnsignedByte, 0, new IntPtr(0)); GL.NormalPointer(NormalPointerType.Float, 0, new IntPtr(0)); GL.VertexPointer(3, VertexPointerType.Float, 0, new IntPtr(0)); if (subMesh.texture != null) { GL.DisableClientState(ArrayCap.TextureCoordArray); } } if (!blendTexture) { // Restore default GL_MODULATE mode GL.TexEnv(TextureEnvironmentTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, GL_MODULATE); } }
private static void DrawToGL(Mesh meshToRender) { GLMeshTrianglePlugin glMeshPlugin = GLMeshTrianglePlugin.Get(meshToRender); for (int i = 0; i < glMeshPlugin.subMeshs.Count; i++) { SubTriangleMesh subMesh = glMeshPlugin.subMeshs[i]; // Make sure the GLMeshPlugin has a reference to hold onto the image so it does not go away before this. if (subMesh.texture != null) { ImageGlPlugin glPlugin = ImageGlPlugin.GetImageGlPlugin(subMesh.texture, true); GL.Enable(EnableCap.Texture2D); GL.BindTexture(TextureTarget.Texture2D, glPlugin.GLTextureHandle); GL.EnableClientState(ArrayCap.TextureCoordArray); } else { GL.Disable(EnableCap.Texture2D); GL.DisableClientState(ArrayCap.TextureCoordArray); } #if true GL.EnableClientState(ArrayCap.NormalArray); GL.EnableClientState(ArrayCap.VertexArray); unsafe { fixed(VertexTextureData *pTextureData = subMesh.textrueData.Array) { fixed(VertexNormalData *pNormalData = subMesh.normalData.Array) { fixed(VertexPositionData *pPosition = subMesh.positionData.Array) { GL.TexCoordPointer(2, TexCordPointerType.Float, 0, new IntPtr(pTextureData)); GL.NormalPointer(NormalPointerType.Float, 0, new IntPtr(pNormalData)); GL.VertexPointer(3, VertexPointerType.Float, 0, new IntPtr(pPosition)); GL.DrawArrays(BeginMode.Triangles, 0, subMesh.positionData.Count); } } } } #else GL.InterleavedArrays(InterleavedArrayFormat.T2fN3fV3f, 0, subMesh.vertexDatas.Array); if (subMesh.texture != null) { //GL.TexCoordPointer(2, TexCoordPointerType.Float, VertexData.Stride, subMesh.vertexDatas.Array); //GL.EnableClientState(ArrayCap.TextureCoordArray); } else { GL.DisableClientState(ArrayCap.TextureCoordArray); } #endif GL.DisableClientState(ArrayCap.NormalArray); GL.DisableClientState(ArrayCap.VertexArray); GL.DisableClientState(ArrayCap.TextureCoordArray); GL.TexCoordPointer(2, TexCordPointerType.Float, 0, new IntPtr(0)); GL.NormalPointer(NormalPointerType.Float, 0, new IntPtr(0)); GL.VertexPointer(3, VertexPointerType.Float, 0, new IntPtr(0)); if (subMesh.texture != null) { GL.DisableClientState(ArrayCap.TextureCoordArray); } } }
private void CreateRenderData(Mesh meshToBuildListFor, Func <Vector3Float, Color> getColorFunc) { subMeshs = new List <SubTriangleMesh>(); SubTriangleMesh currentSubMesh = null; VectorPOD <VertexTextureData> textureData = null; VectorPOD <VertexColorData> colorData = null; VectorPOD <VertexNormalData> normalData = null; VectorPOD <VertexPositionData> positionData = null; // first make sure all the textures are created for (int faceIndex = 0; faceIndex < meshToBuildListFor.Faces.Count; faceIndex++) { FaceTextureData faceTexture; meshToBuildListFor.FaceTextures.TryGetValue(faceIndex, out faceTexture); if (faceTexture != null) { ImageGlPlugin.GetImageGlPlugin(faceTexture.image, true); } // don't compare the data of the texture but rather if they are just the same object if (subMeshs.Count == 0 || (faceTexture != null && (object)subMeshs[subMeshs.Count - 1].texture != (object)faceTexture.image)) { SubTriangleMesh newSubMesh = new SubTriangleMesh(); newSubMesh.texture = faceTexture == null ? null : faceTexture.image; subMeshs.Add(newSubMesh); if (getColorFunc != null) { newSubMesh.UseVertexColors = true; } currentSubMesh = subMeshs[subMeshs.Count - 1]; textureData = currentSubMesh.textureData; colorData = currentSubMesh.colorData; normalData = currentSubMesh.normalData; positionData = currentSubMesh.positionData; } VertexColorData color = new VertexColorData(); if (getColorFunc != null) { var faceColor = getColorFunc(meshToBuildListFor.Faces[faceIndex].normal); color = new VertexColorData { red = faceColor.red, green = faceColor.green, blue = faceColor.blue }; } VertexTextureData tempTexture; VertexNormalData tempNormal; VertexPositionData tempPosition; tempTexture.textureU = faceTexture == null ? 0 : (float)faceTexture.uv0.X; tempTexture.textureV = faceTexture == null ? 0 : (float)faceTexture.uv0.Y; var normal = meshToBuildListFor.Faces[faceIndex].normal; tempNormal.normalX = normal.X; tempNormal.normalY = normal.Y; tempNormal.normalZ = normal.Z; int vertexIndex = meshToBuildListFor.Faces[faceIndex].v0; tempPosition.positionX = (float)meshToBuildListFor.Vertices[vertexIndex].X; tempPosition.positionY = (float)meshToBuildListFor.Vertices[vertexIndex].Y; tempPosition.positionZ = (float)meshToBuildListFor.Vertices[vertexIndex].Z; textureData.Add(tempTexture); normalData.Add(tempNormal); positionData.Add(tempPosition); colorData.add(color); tempTexture.textureU = faceTexture == null ? 0 : (float)faceTexture.uv1.X; tempTexture.textureV = faceTexture == null ? 0 : (float)faceTexture.uv1.Y; vertexIndex = meshToBuildListFor.Faces[faceIndex].v1; tempPosition.positionX = (float)meshToBuildListFor.Vertices[vertexIndex].X; tempPosition.positionY = (float)meshToBuildListFor.Vertices[vertexIndex].Y; tempPosition.positionZ = (float)meshToBuildListFor.Vertices[vertexIndex].Z; textureData.Add(tempTexture); normalData.Add(tempNormal); positionData.Add(tempPosition); colorData.add(color); tempTexture.textureU = faceTexture == null ? 0 : (float)faceTexture.uv2.X; tempTexture.textureV = faceTexture == null ? 0 : (float)faceTexture.uv2.Y; vertexIndex = meshToBuildListFor.Faces[faceIndex].v2; tempPosition.positionX = (float)meshToBuildListFor.Vertices[vertexIndex].X; tempPosition.positionY = (float)meshToBuildListFor.Vertices[vertexIndex].Y; tempPosition.positionZ = (float)meshToBuildListFor.Vertices[vertexIndex].Z; textureData.Add(tempTexture); normalData.Add(tempNormal); positionData.Add(tempPosition); colorData.add(color); } }
private void CreateRenderData(Mesh meshToBuildListFor) { subMeshs = new List <SubTriangleMesh>(); SubTriangleMesh currentSubMesh = null; VectorPOD <VertexTextureData> textureData = new VectorPOD <VertexTextureData>(); VectorPOD <VertexNormalData> normalData = new VectorPOD <VertexNormalData>(); VectorPOD <VertexPositionData> positionData = new VectorPOD <VertexPositionData>(); // first make sure all the textures are created foreach (Face face in meshToBuildListFor.Faces) { ImageBuffer faceTexture = face.GetTexture(0); if (faceTexture != null) { ImageGlPlugin.GetImageGlPlugin(faceTexture, true); } // don't compare the data of the texture but rather if they are just the same object if (subMeshs.Count == 0 || (object)subMeshs[subMeshs.Count - 1].texture != (object)faceTexture) { SubTriangleMesh newSubMesh = new SubTriangleMesh(); newSubMesh.texture = faceTexture; subMeshs.Add(newSubMesh); currentSubMesh = subMeshs[subMeshs.Count - 1]; textureData = currentSubMesh.textrueData; normalData = currentSubMesh.normalData; positionData = currentSubMesh.positionData; } Vector2[] textureUV = new Vector2[2]; Vector3[] position = new Vector3[2]; int vertexIndex = 0; foreach (FaceEdge faceEdge in face.FaceEdges()) { if (vertexIndex < 2) { textureUV[vertexIndex] = faceEdge.GetUVs(0); position[vertexIndex] = faceEdge.firstVertex.Position; } else { VertexTextureData tempTexture; VertexNormalData tempNormal; VertexPositionData tempPosition; tempTexture.textureU = (float)textureUV[0].x; tempTexture.textureV = (float)textureUV[0].y; tempNormal.normalX = (float)face.normal.x; tempNormal.normalY = (float)face.normal.y; tempNormal.normalZ = (float)face.normal.z; tempPosition.positionX = (float)position[0].x; tempPosition.positionY = (float)position[0].y; tempPosition.positionZ = (float)position[0].z; textureData.Add(tempTexture); normalData.Add(tempNormal); positionData.Add(tempPosition); tempTexture.textureU = (float)textureUV[1].x; tempTexture.textureV = (float)textureUV[1].y; tempNormal.normalX = (float)face.normal.x; tempNormal.normalY = (float)face.normal.y; tempNormal.normalZ = (float)face.normal.z; tempPosition.positionX = (float)position[1].x; tempPosition.positionY = (float)position[1].y; tempPosition.positionZ = (float)position[1].z; textureData.Add(tempTexture); normalData.Add(tempNormal); positionData.Add(tempPosition); Vector2 textureUV2 = faceEdge.GetUVs(0); Vector3 position2 = faceEdge.firstVertex.Position; tempTexture.textureU = (float)textureUV2.x; tempTexture.textureV = (float)textureUV2.y; tempNormal.normalX = (float)face.normal.x; tempNormal.normalY = (float)face.normal.y; tempNormal.normalZ = (float)face.normal.z; tempPosition.positionX = (float)position2.x; tempPosition.positionY = (float)position2.y; tempPosition.positionZ = (float)position2.z; textureData.Add(tempTexture); normalData.Add(tempNormal); positionData.Add(tempPosition); textureUV[1] = faceEdge.GetUVs(0); position[1] = faceEdge.firstVertex.Position; } vertexIndex++; } } }
static public ImageGlPlugin GetImageGlPlugin(ImageBuffer imageToGetDisplayListFor, bool createAndUseMipMaps, bool TextureMagFilterLinear = true) { ImageGlPlugin plugin; imagesWithCacheData.TryGetValue(imageToGetDisplayListFor.GetBuffer(), out plugin); using (TimedLock.Lock(glDataNeedingToBeDeleted, "GetImageGlPlugin")) { // We run this in here to ensure that we are on the correct thread and have the correct // glcontext realized. for (int i = glDataNeedingToBeDeleted.Count - 1; i >= 0; i--) { int textureToDelete = glDataNeedingToBeDeleted[i].glTextureHandle; if (glDataNeedingToBeDeleted[i].refreshCountCreatedOn == currentGlobalRefreshCount) { GL.DeleteTextures(1, ref textureToDelete); } glDataNeedingToBeDeleted.RemoveAt(i); } } #if ON_IMAGE_CHANGED_ALWAYS_CREATE_IMAGE if (plugin != null && (imageToGetDisplayListFor.ChangedCount != plugin.imageUpdateCount || plugin.glData.refreshCountCreatedOn != currentGlobalRefreshCount)) { int textureToDelete = plugin.GLTextureHandle; if (plugin.glData.refreshCountCreatedOn == currentGlobalRefreshCount) { GL.DeleteTextures(1, ref textureToDelete); } plugin.glData.glTextureHandle = 0; imagesWithCacheData.Remove(imageToGetDisplayListFor.GetBuffer()); plugin = null; } if (plugin == null) { ImageGlPlugin newPlugin = new ImageGlPlugin(); imagesWithCacheData.Add(imageToGetDisplayListFor.GetBuffer(), newPlugin); newPlugin.createdWithMipMaps = createAndUseMipMaps; newPlugin.CreateGlDataForImage(imageToGetDisplayListFor, TextureMagFilterLinear); newPlugin.imageUpdateCount = imageToGetDisplayListFor.ChangedCount; newPlugin.glData.refreshCountCreatedOn = currentGlobalRefreshCount; return(newPlugin); } #else if (plugin == null) { ImageGlPlugin newPlugin = new ImageGlPlugin(); imagesWithCacheData.Add(imageToGetDisplayListFor.GetBuffer(), newPlugin); newPlugin.createdWithMipMaps = createAndUseMipMaps; newPlugin.CreateGlDataForImage(imageToGetDisplayListFor, TextureMagFilterLinear); newPlugin.imageUpdateCount = imageToGetDisplayListFor.ChangedCount; newPlugin.refreshCountCreatedOn = currentGlobalRefreshCount; return(newPlugin); } if (imageToGetDisplayListFor.ChangedCount != plugin.imageUpdateCount || plugin.refreshCountCreatedOn != currentGlobalRefreshCount) { plugin.imageUpdateCount = imageToGetDisplayListFor.ChangedCount; plugin.refreshCountCreatedOn = currentGlobalRefreshCount; GL.BindTexture(TextureTarget.Texture2D, plugin.GLTextureHandle); // Create the texture switch (imageToGetDisplayListFor.BitDepth) { case 8: GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, imageToGetDisplayListFor.Width, imageToGetDisplayListFor.Height, PixelFormat.Luminance, PixelType.UnsignedByte, imageToGetDisplayListFor.GetBuffer()); break; case 24: // our bitmaps are not padded and GL is having a problem with them so don't use 24 bit unless you fix this. GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, imageToGetDisplayListFor.Width, imageToGetDisplayListFor.Height, PixelFormat.Bgr, PixelType.UnsignedByte, imageToGetDisplayListFor.GetBuffer()); break; case 32: GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, imageToGetDisplayListFor.Width, imageToGetDisplayListFor.Height, PixelFormat.Bgra, PixelType.UnsignedByte, imageToGetDisplayListFor.GetBuffer()); break; default: throw new NotImplementedException(); } if (plugin.createdWithMipMaps) { if (GLMajorVersion < 3) { switch (imageToGetDisplayListFor.BitDepth) { case 32: { ImageBuffer sourceImage = new ImageBuffer(imageToGetDisplayListFor); ImageBuffer tempImage = new ImageBuffer(sourceImage.Width / 2, sourceImage.Height / 2, 32, new BlenderBGRA()); tempImage.NewGraphics2D().Render(sourceImage, 0, 0, 0, .5, .5); int mipLevel = 1; while (sourceImage.Width > 1 && sourceImage.Height > 1) { GL.TexSubImage2D(TextureTarget.Texture2D, mipLevel++, 0, 0, tempImage.Width, tempImage.Height, PixelFormat.Bgra, PixelType.UnsignedByte, tempImage.GetBuffer()); sourceImage = new ImageBuffer(tempImage); tempImage = new ImageBuffer(Math.Max(1, sourceImage.Width / 2), Math.Max(1, sourceImage.Height / 2), 32, new BlenderBGRA()); tempImage.NewGraphics2D().Render(sourceImage, 0, 0, 0, (double)tempImage.Width / (double)sourceImage.Width, (double)tempImage.Height / (double)sourceImage.Height); } } break; default: throw new NotImplementedException(); } } else { GL.GenerateMipmap(GenerateMipmapTarget.Texture2D); } } } #endif return(plugin); }
private void CreateRenderData(Mesh meshToBuildListFor, Func <Vector3, Color> getColorFunc) { subMeshs = new List <SubTriangleMesh>(); SubTriangleMesh currentSubMesh = null; VectorPOD <VertexTextureData> textureData = null; VectorPOD <VertexColorData> colorData = null; VectorPOD <VertexNormalData> normalData = null; VectorPOD <VertexPositionData> positionData = null; // first make sure all the textures are created foreach (Face face in meshToBuildListFor.Faces) { ImageBuffer faceTexture = face.GetTexture(0); if (faceTexture != null) { ImageGlPlugin.GetImageGlPlugin(faceTexture, true); } // don't compare the data of the texture but rather if they are just the same object if (subMeshs.Count == 0 || (object)subMeshs[subMeshs.Count - 1].texture != (object)faceTexture) { SubTriangleMesh newSubMesh = new SubTriangleMesh(); newSubMesh.texture = faceTexture; subMeshs.Add(newSubMesh); if (getColorFunc != null) { newSubMesh.UseVertexColors = true; } currentSubMesh = subMeshs[subMeshs.Count - 1]; textureData = currentSubMesh.textureData; colorData = currentSubMesh.colorData; normalData = currentSubMesh.normalData; positionData = currentSubMesh.positionData; } Vector2[] textureUV = new Vector2[2]; Vector3[] position = new Vector3[2]; VertexColorData color = new VertexColorData(); if (getColorFunc != null) { var faceColor = getColorFunc(face.Normal); color = new VertexColorData { red = faceColor.red, green = faceColor.green, blue = faceColor.blue }; } int vertexIndex = 0; foreach (FaceEdge faceEdge in face.FaceEdges()) { if (vertexIndex < 2) { textureUV[vertexIndex] = faceEdge.GetUv(0); position[vertexIndex] = faceEdge.FirstVertex.Position; } else { VertexTextureData tempTexture; VertexNormalData tempNormal; VertexPositionData tempPosition; tempTexture.textureU = (float)textureUV[0].X; tempTexture.textureV = (float)textureUV[0].Y; tempNormal.normalX = (float)face.Normal.X; tempNormal.normalY = (float)face.Normal.Y; tempNormal.normalZ = (float)face.Normal.Z; tempPosition.positionX = (float)position[0].X; tempPosition.positionY = (float)position[0].Y; tempPosition.positionZ = (float)position[0].Z; textureData.Add(tempTexture); normalData.Add(tempNormal); positionData.Add(tempPosition); colorData.add(color); tempTexture.textureU = (float)textureUV[1].X; tempTexture.textureV = (float)textureUV[1].Y; tempNormal.normalX = (float)face.Normal.X; tempNormal.normalY = (float)face.Normal.Y; tempNormal.normalZ = (float)face.Normal.Z; tempPosition.positionX = (float)position[1].X; tempPosition.positionY = (float)position[1].Y; tempPosition.positionZ = (float)position[1].Z; textureData.Add(tempTexture); normalData.Add(tempNormal); positionData.Add(tempPosition); colorData.add(color); Vector2 textureUV2 = faceEdge.GetUv(0); Vector3 position2 = faceEdge.FirstVertex.Position; tempTexture.textureU = (float)textureUV2.X; tempTexture.textureV = (float)textureUV2.Y; tempNormal.normalX = (float)face.Normal.X; tempNormal.normalY = (float)face.Normal.Y; tempNormal.normalZ = (float)face.Normal.Z; tempPosition.positionX = (float)position2.X; tempPosition.positionY = (float)position2.Y; tempPosition.positionZ = (float)position2.Z; textureData.Add(tempTexture); normalData.Add(tempNormal); positionData.Add(tempPosition); colorData.add(color); textureUV[1] = faceEdge.GetUv(0); position[1] = faceEdge.FirstVertex.Position; } vertexIndex++; } } }