/// <summary> /// Creates a graphics mesh with the triangle mesh data of the given shape and the given /// diffuse and specular material properties. /// </summary> /// <param name="contentManager">The contentManager manager.</param> /// <param name="graphicsService">The graphics service.</param> /// <param name="shape">The shape.</param> /// <param name="diffuse">The diffuse material color.</param> /// <param name="specular">The specular material color.</param> /// <param name="specularPower">The specular power of the material.</param> /// <returns>The graphics mesh.</returns> public static Mesh CreateMesh(ContentManager contentManager, IGraphicsService graphicsService, Shape shape, Vector3 diffuse, Vector3 specular, float specularPower) { // Create a DigitalRune.Geometry.Meshes.TriangleMesh from the shape and // convert this to a DigitalRune.Graphics.Mesh. TriangleMesh triangleMesh = shape.GetMesh(0.01f, 4); Submesh submesh = CreateSubmeshWithTexCoords( graphicsService.GraphicsDevice, triangleMesh, MathHelper.ToRadians(70)); var mesh = CreateMesh(contentManager, graphicsService, submesh, diffuse, specular, specularPower); // Set bounding shape to a box that is equal to the AABB of the shape. var aabb = shape.GetAabb(Pose.Identity); var boxShape = new BoxShape(aabb.Extent); var center = aabb.Center; if (center.IsNumericallyZero) { mesh.BoundingShape = boxShape; } else { mesh.BoundingShape = new TransformedShape(new GeometricObject(boxShape, new Pose(center))); } return(mesh); }
public void Write(string Location) { using (BinaryWriter bw = new BinaryWriter(File.OpenWrite(Location))) { bw.Write(0x00112233); bw.Write((UInt16)2); bw.Write((UInt16)1); bw.Write((UInt32)this.Submeshes.Count); UInt32 IndexCount = 0; UInt32 VertexCount = 0; foreach (SKNSubmesh Submesh in this.Submeshes) { Submesh.Write(bw); IndexCount += Submesh.IndexCount; VertexCount += Submesh.VertexCount; } bw.Write(IndexCount); bw.Write(VertexCount); foreach (UInt16 Index in this.Indices) { bw.Write(Index); } foreach (SKNVertex Vertex in this.Vertices) { Vertex.Write(bw); } bw.Write(new byte[12]); } }
//QFont font; //float arrow_length; internal Coordinate() { submesh = new Submesh[3]; model = new TopoModel[3]; //arrow_length = Convert.ToSingle(Math.Abs(model.boundingBox.zMax - model.boundingBox.zMin)); // override mesh color for (int i = 0; i < 3; i++) { // import mesh from STL. model[i] = new TopoModel(); model[i].importSTL(Application.StartupPath + Path.DirectorySeparatorChar + names[i], 1); submesh[i] = new Submesh(); model[i].FillMeshTrianglesOnly(submesh[i], 0); submesh[i].Compress(true, coordinate_colors[i]); submesh[i].vertices.Clear(); } model = null; // release memory // config font /*font = new QFont("data/HappySans.ttf", * label_font_size, new QFontBuilderConfiguration(true)); * font.Options.DropShadowActive = false;*/ }
//QFont font; //float arrow_length; internal Coordinate(ThreeDControl ctrl) { submesh = new Submesh[3]; model = new TopoModel[3]; this.ctrl = ctrl; //arrow_length = Convert.ToSingle(Math.Abs(model.boundingBox.zMax - model.boundingBox.zMin)); // override mesh color for (int i = 0; i < 3; i++) { // import mesh from STL. model[i] = new TopoModel(); string file = System.AppDomain.CurrentDomain.BaseDirectory + Path.DirectorySeparatorChar + names[i]; model[i].importSTL(File.ReadAllBytes(file), file, 1); submesh[i] = new Submesh(); model[i].FillMeshTrianglesOnly(submesh[i], 0); submesh[i].Compress(true, coordinate_colors[i]); submesh[i].vertices.Clear(); } model = null; // release memory // config font /*font = new QFont("data/HappySans.ttf", * label_font_size, new QFontBuilderConfiguration(true)); * font.Options.DropShadowActive = false;*/ }
public ScatteringSkyRenderer(IGraphicsService graphicsService) { if (graphicsService == null) { throw new ArgumentNullException("graphicsService"); } if (graphicsService.GraphicsDevice.GraphicsProfile == GraphicsProfile.Reach) { throw new NotSupportedException("The ScatteringSkyRenderer does not support the Reach profile."); } _effect = graphicsService.Content.Load <Effect>("DigitalRune/Sky/ScatteringSky"); _parameterView = _effect.Parameters["View"]; _parameterProjection = _effect.Parameters["Projection"]; _parameterSunDirection = _effect.Parameters["SunDirection"]; _parameterRadii = _effect.Parameters["Radii"]; _parameterNumberOfSamples = _effect.Parameters["NumberOfSamples"]; _parameterBetaRayleigh = _effect.Parameters["BetaRayleigh"]; _parameterBetaMie = _effect.Parameters["BetaMie"]; _parameterGMie = _effect.Parameters["GMie"]; _parameterSunIntensity = _effect.Parameters["SunIntensity"]; _parameterTransmittance = _effect.Parameters["Transmittance"]; _parameterBaseHorizonColor = _effect.Parameters["BaseHorizonColor"]; _parameterBaseZenithColor = _effect.Parameters["BaseZenithColor"]; _passLinear = _effect.Techniques[0].Passes["Linear"]; _passGamma = _effect.Techniques[0].Passes["Gamma"]; _passLinearWithBaseColor = _effect.Techniques[0].Passes["LinearWithBaseColor"]; _passGammaWithBaseColor = _effect.Techniques[0].Passes["GammaWithBaseColor"]; _submesh = MeshHelper.GetBox(graphicsService); }
private void CollectMeshParts(List <Submesh> collector, Mesh mesh, MeshRenderer renderer, float maxSize) { Matrix4x4 localToWorldMatrix = renderer.localToWorldMatrix; Material[] sharedMaterials = renderer.sharedMaterials; int index = 0; Vector3[] vertices = mesh.vertices; for (int i = 0; i < mesh.subMeshCount; i++) { if (index >= sharedMaterials.Length) { index = sharedMaterials.Length - 1; } Bounds bounds = CalculatePartBounds(vertices, mesh.GetTriangles(i), localToWorldMatrix); if ((2f * bounds.extents.magnitude) <= maxSize) { Submesh item = new Submesh { renderer = renderer, material = sharedMaterials[index], mesh = mesh, submesh = i, bounds = bounds }; collector.Add(item); } index++; } }
/// <summary> /// Initializes a new instance of the <see cref="FogSphereRenderer"/> class. /// </summary> /// <param name="graphicsService">The graphics service.</param> /// <exception cref="ArgumentNullException"> /// <paramref name="graphicsService"/> is <see langword="null"/>. /// </exception> public FogSphereRenderer(IGraphicsService graphicsService) { if (graphicsService == null) { throw new ArgumentNullException("graphicsService"); } // Load effect. _effect = graphicsService.Content.Load <Effect>("FogSphere"); _parameterViewportSize = _effect.Parameters["ViewportSize"]; _parameterWorld = _effect.Parameters["World"]; _parameterWorldInverse = _effect.Parameters["WorldInverse"]; _parameterView = _effect.Parameters["View"]; _parameterProjection = _effect.Parameters["Projection"]; _parameterCameraPosition = _effect.Parameters["CameraPosition"]; _parameterCameraFar = _effect.Parameters["CameraFar"]; _parameterGBuffer0 = _effect.Parameters["GBuffer0"]; _parameterColor = _effect.Parameters["Color"]; _parameterBlendMode = _effect.Parameters["BlendMode"]; _parameterDensity = _effect.Parameters["Density"]; _parameterFalloff = _effect.Parameters["Falloff"]; _parameterIntersectionSoftness = _effect.Parameters["IntersectionSoftness"]; // Get a sphere mesh. _submesh = MeshHelper.CreateIcosphere(graphicsService.GraphicsDevice, 2); }
private void RenderCylinder(IGraphicsService graphicsService, PrimitiveJob job) { float radius = job.Size.Radius; float height = job.Size.Height; Effect.World = Matrix.CreateScale(radius, height / 2, radius) * job.Pose; Effect.CurrentTechnique.Passes[0].Apply(); if (DrawWireFrame) { if (_cylinderLinePrimitive == null) { _cylinderLinePrimitive = MeshHelper.GetCylinderLines(graphicsService); } _cylinderLinePrimitive.Draw(); } else { if (_cylinderPrimitive == null) { _cylinderPrimitive = MeshHelper.GetCylinder(graphicsService); } _cylinderPrimitive.Draw(); } }
private Submesh[] ReadSubmeshes(uint nSubmeshes, uint ofsSubmeshes, BinaryReader bin) { bin.BaseStream.Position = ofsSubmeshes; var submeshes = new Submesh[nSubmeshes]; for (int i = 0; i < nSubmeshes; i++) { submeshes[i].submeshID = bin.ReadUInt16(); submeshes[i].unk1 = bin.ReadUInt16(); submeshes[i].startVertex = bin.ReadUInt16(); submeshes[i].nVertices = bin.ReadUInt16(); if (submeshes[i].unk1 == 1) { submeshes[i].startTriangle = bin.ReadUInt32(); } else { submeshes[i].startTriangle = (uint)bin.ReadUInt16(); } submeshes[i].nTriangles = bin.ReadUInt16(); submeshes[i].nBones = bin.ReadUInt16(); submeshes[i].startBones = bin.ReadUInt16(); submeshes[i].unk2 = bin.ReadUInt16(); submeshes[i].rootBone = bin.ReadUInt16(); submeshes[i].centerMas = bin.Read <Vector3>(); submeshes[i].centerBoundingBox = bin.Read <Vector3>(); submeshes[i].radius = bin.ReadSingle(); } return(submeshes); }
public SubmeshSample(Microsoft.Xna.Framework.Game game) : base(game) { _delegateGraphicsScreen = new DelegateGraphicsScreen(GraphicsService) { RenderCallback = Render, }; GraphicsService.Screens.Insert(0, _delegateGraphicsScreen); // Add a custom game object which controls the camera. _cameraObject = new CameraObject(Services); GameObjectService.Objects.Add(_cameraObject); var graphicsDevice = GraphicsService.GraphicsDevice; // The MeshHelper class can create submeshes for several basic shapes: _sphere = MeshHelper.CreateUVSphere(graphicsDevice, 20); _torus = MeshHelper.CreateTorus(graphicsDevice, 0.5f, 0.667f, 16); _teapot = MeshHelper.CreateTeapot(graphicsDevice, 1, 8); // MeshHelper.CreateBox() returns a new submesh for a box. Instead we can call // MeshHelper.GetBox(), which returns a shared submesh. - GetBox() will always // return the same instance. _box = MeshHelper.GetBox(GraphicsService); // We can also create a submesh that uses line primitives. _cone = MeshHelper.GetConeLines(GraphicsService); // We use a normal XNA BasicEffect to render the submeshes. _effect = new BasicEffect(graphicsDevice) { PreferPerPixelLighting = true }; _effect.EnableDefaultLighting(); }
public GradientTextureSkyRenderer(IGraphicsService graphicsService) { if (graphicsService == null) throw new ArgumentNullException("graphicsService"); if (graphicsService.GraphicsDevice.GraphicsProfile == GraphicsProfile.Reach) throw new NotSupportedException("The GradientTextureSkyRenderer does not support the Reach profile."); _effect = graphicsService.Content.Load<Effect>("DigitalRune/Sky/GradientTextureSky"); _parameterView = _effect.Parameters["View"]; _parameterProjection = _effect.Parameters["Projection"]; _parameterSunDirection = _effect.Parameters["SunDirection"]; _parameterTime = _effect.Parameters["Time"]; _parameterColor = _effect.Parameters["Color"]; _parameterFrontTexture = _effect.Parameters["FrontTexture"]; _parameterBackTexture = _effect.Parameters["BackTexture"]; _parameterAbcd = _effect.Parameters["Abcd"]; _parameterEAndStrength = _effect.Parameters["EAndStrength"]; _passLinear = _effect.Techniques[0].Passes["Linear"]; _passGamma = _effect.Techniques[0].Passes["Gamma"]; _passCieLinear = _effect.Techniques[0].Passes["CieLinear"]; _passCieGamma = _effect.Techniques[0].Passes["CieGamma"]; _submesh = MeshHelper.GetBox(graphicsService); }
private void SortForBetterGrouping(List <Submesh> parts, float maxSize) { int num = 0; while (num < parts.Count) { Submesh submesh = parts[num]; int num2 = num + 1; while (true) { if (num2 >= parts.Count) { num++; break; } Submesh submesh2 = parts[num2]; Vector3 extents = submesh.bounds.extents; float magnitude = extents.magnitude; Vector3 vector2 = submesh2.bounds.extents; Vector3 vector3 = submesh.bounds.center - submesh2.bounds.center; float num4 = (vector2.magnitude + vector3.magnitude) + magnitude; if (num4 <= maxSize) { float num5 = ((num4 - magnitude) - magnitude) / magnitude; submesh.nearValue = (num5 > 0.1) ? ((num5 > 0.2) ? ((num5 > 0.3) ? (submesh.nearValue + 1) : (submesh.nearValue + 3)) : (submesh.nearValue + 5)) : (submesh.nearValue + 10); } num2++; } } parts.Sort(this.orderComparer); }
public GradientSkyRenderer(IGraphicsService graphicsService) { if (graphicsService == null) { throw new ArgumentNullException("graphicsService"); } if (graphicsService.GraphicsDevice.GraphicsProfile == GraphicsProfile.Reach) { throw new NotSupportedException("The GradientSkyRenderer does not support the Reach profile."); } _effect = graphicsService.Content.Load <Effect>("DigitalRune/Sky/GradientSky"); _parameterView = _effect.Parameters["View"]; _parameterProjection = _effect.Parameters["Projection"]; _parameterSunDirection = _effect.Parameters["SunDirection"]; _parameterFrontColor = _effect.Parameters["FrontColor"]; _parameterZenithColor = _effect.Parameters["ZenithColor"]; _parameterBackColor = _effect.Parameters["BackColor"]; _parameterGroundColor = _effect.Parameters["GroundColor"]; _parameterShift = _effect.Parameters["Shift"]; _parameterAbcd = _effect.Parameters["Abcd"]; _parameterEAndStrength = _effect.Parameters["EAndStrength"]; _passLinear = _effect.Techniques[0].Passes["Linear"]; _passGamma = _effect.Techniques[0].Passes["Gamma"]; _passCieLinear = _effect.Techniques[0].Passes["CieLinear"]; _passCieGamma = _effect.Techniques[0].Passes["CieGamma"]; _submesh = MeshHelper.GetBox(graphicsService); }
private List <Zone> CombineZones(List <Submesh> parts, float maxSize) { this.SortForBetterGrouping(parts, maxSize); List <Zone> list = new List <Zone>(); for (int i = 0; i < parts.Count; i++) { Submesh item = parts[i]; if (!item.merged && (item.nearValue != 0)) { Vector3 vector = new Vector3(); int num2 = i + 1; while (true) { if (num2 >= parts.Count) { if (this.candidates.Count > 0) { Zone zone = new Zone { bounds = item.bounds, contents = new List <Submesh>() }; zone.contents.Add(item); item.merged = true; this.candidatesComparer.center = vector / ((float)this.candidates.Count); this.candidates.Sort(this.candidatesComparer); int num3 = 0; while (true) { if (num3 >= this.candidates.Count) { list.Add(zone); this.candidates.Clear(); break; } Submesh submesh3 = this.candidates[num3]; if ((num3 == 0) || CanGroup(zone.bounds, submesh3.bounds, maxSize)) { zone.bounds.Encapsulate(submesh3.bounds); zone.contents.Add(submesh3); submesh3.merged = true; } num3++; } } break; } Submesh submesh2 = parts[num2]; if (!submesh2.merged && ((submesh2.material == item.material) && ((submesh2.lightmapIndex == item.lightmapIndex) && CanGroup(item.bounds, submesh2.bounds, maxSize)))) { vector += submesh2.bounds.center; this.candidates.Add(submesh2); } num2++; } } } return(list); }
internal void Dispose() { if (_submesh != null) { _submesh.Dispose(); _submesh = null; } }
protected override Mesh Read(ContentReader input, Mesh existingInstance) { if (existingInstance == null) existingInstance = new Mesh(); existingInstance.BoundingShape = input.ReadObject<Shape>(); int numberOfSubmeshes = input.ReadInt32(); for (int i = 0; i < numberOfSubmeshes; i++) { // Add submesh to Mesh.Submeshes before loading it. This is necessary // because the submesh tries to store its material in Mesh.Materials. Submesh submesh = new Submesh(); existingInstance.Submeshes.Add(submesh); input.ReadObject(submesh); } existingInstance.Name = input.ReadString(); bool hasOccluder = input.ReadBoolean(); if (hasOccluder) { using (var helper = AssetLoadHelper.Get(input.AssetName)) { input.ReadSharedResource(helper.Fixup<Occluder>(o => existingInstance.Occluder = o)); } } bool hasSkeleton = input.ReadBoolean(); if (hasSkeleton) { using (var helper = AssetLoadHelper.Get(input.AssetName)) { input.ReadSharedResource(helper.Fixup<Skeleton>(s => existingInstance.Skeleton = s)); } #else throw new ContentLoadException("Mesh contains a skeleton, but this build of DigitalRune Graphics does not support animations."); } var hasAnimations = input.ReadBoolean(); if (hasAnimations) { using (var helper = AssetLoadHelper.Get(input.AssetName)) { input.ReadSharedResource(helper.Fixup<Dictionary<string, SkeletonKeyFrameAnimation>>(a => existingInstance.Animations = a)); } #else throw new ContentLoadException("Mesh contains animations, but this build of DigitalRune Graphics does not support animations."); } input.ReadSharedResource<object>(userData => existingInstance.UserData = userData); return existingInstance; }
public SubmeshRenderer(Submesh submesh, Material material) { this.Submesh = submesh; this.Material = material; var indices = from face in Submesh.Faces from index in face.Indices select index; indexBuffer = new StaticBuffer <ushort>(sizeof(ushort), indices.ToArray(), BufferTarget.ElementArrayBuffer); }
private void RenderCapsule(IGraphicsService graphicsService, PrimitiveJob job) { float radius = job.Size.Radius; float height = job.Size.Height; if (DrawWireFrame) { if (_hemisphereLinePrimitive == null) { _hemisphereLinePrimitive = MeshHelper.GetHemisphereLines(graphicsService); } Effect.World = Matrix.CreateScale(radius) * Matrix.CreateTranslation(0, height / 2 - radius, 0) * job.Pose; Effect.CurrentTechnique.Passes[0].Apply(); _hemisphereLinePrimitive.Draw(); Effect.World = Matrix.CreateScale(-radius, -radius, radius) * Matrix.CreateTranslation(0, -height / 2 + radius, 0) * job.Pose; Effect.CurrentTechnique.Passes[0].Apply(); _hemisphereLinePrimitive.Draw(); // 4 lines Vector3F dx = radius * job.Pose.ToWorldDirection(new Vector3F(1, 0, 0)); Vector3F dy = (height / 2 - radius) * job.Pose.ToWorldDirection(new Vector3F(0, 1, 0)); Vector3F dz = radius * job.Pose.ToWorldDirection(new Vector3F(0, 0, 1)); Vector3F center = job.Pose.Position; _lineBatch.Add(center + dy + dx, center - dy + dx, job.Color); _lineBatch.Add(center + dy - dx, center - dy - dx, job.Color); _lineBatch.Add(center + dy + dz, center - dy + dz, job.Color); _lineBatch.Add(center + dy - dz, center - dy - dz, job.Color); } else { if (_hemispherePrimitive == null) { _hemispherePrimitive = MeshHelper.GetHemisphere(graphicsService); } Effect.World = Matrix.CreateScale(radius) * Matrix.CreateTranslation(0, height / 2 - radius, 0) * job.Pose; Effect.CurrentTechnique.Passes[0].Apply(); _hemispherePrimitive.Draw(); Effect.World = Matrix.CreateScale(-radius, -radius, radius) * Matrix.CreateTranslation(0, -height / 2 + radius, 0) * job.Pose; Effect.CurrentTechnique.Passes[0].Apply(); _hemispherePrimitive.Draw(); if (_uncappedCylinderPrimitive == null) { _uncappedCylinderPrimitive = MeshHelper.GetUncappedCylinder(graphicsService); } Effect.World = Matrix.CreateScale(radius, height / 2 - radius, radius) * job.Pose; Effect.CurrentTechnique.Passes[0].Apply(); _uncappedCylinderPrimitive.Draw(); } }
private void InitializeHiDef(IGraphicsService graphicsService) { _submesh = MeshHelper.GetBox(graphicsService); _effect = graphicsService.Content.Load <Effect>("DigitalRune/Sky/Skybox"); _parameterWorldViewProjection = _effect.Parameters["WorldViewProjection"]; _parameterExposure = _effect.Parameters["Color"]; _textureParameter = _effect.Parameters["Texture"]; _passLinear = _effect.CurrentTechnique.Passes["SRgbToRgb"]; _passGamma = _effect.CurrentTechnique.Passes["SRgbToSRgb"]; }
/// <summary> /// Sets the new submesh. /// </summary> /// <param name="context">The render context.</param> /// <param name="submesh">The submesh.</param> /// <param name="effectPassBinding">The effect pass binding.</param> /// <param name="effectPassParameterBindings"> /// The effect parameter bindings containing per-pass parameter bindings. /// (Can also contain other parameter binding, e.g. per-instance, which are ignored. /// </param> /// <remarks> /// The current batch is automatically flushed when the submesh is changed. /// </remarks> public void SetSubmesh(RenderContext context, Submesh submesh, EffectPassBinding effectPassBinding, EffectParameterBindingCollection effectPassParameterBindings) { Flush(); _renderContext = context; _submesh = submesh; _effectPassBinding = effectPassBinding; _effectPassParameterBindings = effectPassParameterBindings; }
public void AddElements(IEnumerable <Vector3> vertices, IEnumerable <Vector2> uvs, IEnumerable <int> indices, Material material) { var vertexList = new List <Vector3>(vertices); int vertexCount = vertexList.Count; MeshBucket bucket = null; // Check whether the last available bucket is valid for use given the maximum vertex count if (Meshes.Count > 0) { var last = Meshes[Meshes.Count - 1]; if (last.Vertices.Count + vertexCount < MaxVertexCount) { bucket = last; } } // No bucket were found, instantiate a new one if (bucket == null) { bucket = new MeshBucket(); Meshes.Add(bucket); } int offset = bucket.Vertices.Count; bucket.Vertices.AddRange(vertexList); bucket.UVs.AddRange(uvs); // Find a submesh with this material, or create a new one. Submesh submesh = null; foreach (var s in bucket.Submeshes) { if (s.Material == material) { submesh = s; break; } } if (submesh == null) { submesh = new Submesh { Indices = new List <int>(), Material = material }; bucket.Submeshes.Add(submesh); } foreach (var index in indices) { submesh.Indices.Add(index + offset); } }
private Mesh Construct() { Mesh mesh = new Mesh(new Vertex[vertices.Count], new Face[0]) { Name = name, Comments = comments }; // add vertex position & color for (int i = 0; i < vertices.Count; i++) { var vertex = vertices[i]; var position = vertex.Position; var color = new Color4(vertex.Color.X, vertex.Color.Y, vertex.Color.Z, 1); mesh.Vertices[i] = new Vertex(position, color); } // facegroup (obj) = submesh (BE) foreach (var faceGroup in faceGroups) { var submesh = new Submesh(new Face[faceGroup.Faces.Count]) { Name = faceGroup.Name, Comments = faceGroup.Comments }; for (int i = 0; i < faceGroup.Faces.Count; i++) { // convert faces var objFace = faceGroup.Faces[i]; submesh.Faces[i] = new Face(3); for (int v = 0; v < 3; v++) { ObjFaceVertex faceVertex = objFace.Vertices[v]; ushort vertexId = faceVertex.VertexIndex; submesh.Faces[i].Indices[v] = vertexId; // add missing (indexed / referenced) data to vertex if (normals.Count > 0) { mesh.Vertices[vertexId].Normal = normals[faceVertex.NormalIndex]; } if (uvs.Count > 0) { mesh.Vertices[vertexId].UV = uvs[faceVertex.UVIndex]; } } } mesh.Submeshes.Add(submesh); } return(mesh); }
private IndexedVertexAttributeArrays GetIndexedVertexAttributeArrays(Submesh submesh, int index) { if (ThreadUtility.isMainThread) { return(_cachedIndexedVertexAttributeArrays.MoveTo(submesh, index)); } else { return(new IndexedVertexAttributeArrays(submesh, index)); } }
/// <summary> /// Adds a model for rendering. /// </summary> /// <param name="submesh">The submesh.</param> /// <param name="pose">The pose.</param> /// <param name="scale">The scale.</param> /// <param name="color">The color.</param> public void AddSubmesh(Submesh submesh, Pose pose, Vector3 scale, Color color) { var job = PrimitiveJobPool.Obtain(); job.Type = PrimitiveJobType.Submesh; job.Submesh = submesh; job.Pose = pose; job.Color = color; job.Size.Scale = scale; _primitives.Add(job); _usesTransparency = _usesTransparency || (color.A < 255); }
private static bool ContainsSubmeshWithIndex(List <Submesh> list, int index) { for (int i = 0; i < list.Count; i++) { Submesh submesh = list[i]; if (index == submesh.submesh) { return(true); } } return(false); }
private static OutlineItem CreateOutlineItem(Submesh submesh) { var item = new OutlineItem { Text = "Submesh", Icon = MultiColorGlyphs.Mesh, ToolTip = ToolTipSceneNode, UserData = submesh, }; return(item); }
private void RemoveOriginalSubmeshes(List <Zone> zones) { Dictionary <MeshRenderer, List <Submesh> > dictionary = new Dictionary <MeshRenderer, List <Submesh> >(); int num = 0; while (num < zones.Count) { Zone zone = zones[num]; int num2 = 0; while (true) { if (num2 >= zone.contents.Count) { num++; break; } Submesh item = zone.contents[num2]; MeshRenderer key = item.renderer; List <Submesh> list = null; if (dictionary.ContainsKey(key)) { list = dictionary[key]; } else { list = new List <Submesh>(); dictionary.Add(key, list); } list.Add(item); num2++; } } foreach (KeyValuePair <MeshRenderer, List <Submesh> > pair in dictionary) { MeshRenderer key = pair.Key; List <Submesh> list = pair.Value; MeshFilter component = key.GetComponent <MeshFilter>(); Mesh sharedMesh = component.sharedMesh; if (sharedMesh.subMeshCount != list.Count) { this.RemoveSubmeshesFromMesh(component, key, list); continue; } Destroy(component); Destroy(key); GameObject gameObject = key.gameObject; if ((gameObject.transform.childCount == 0) && !HasImportantComponents(gameObject)) { key.gameObject.SetActive(false); } } }
public Model(Mesh mesh) { this.mesh = mesh; submeshes = new Submesh[mesh.subMeshCount]; for (int i = 0; i < submeshes.Length; i++) { submeshes[i] = new Submesh { mesh = mesh, index = i, }; } }
/** Adds a material. Adds submesh indexes if existing indexes aren't sufficient. */ private void addSubmesh(Material material, int endQuadCount, int submeshQuadCount, bool lastSubmesh) { int submeshIndex = submeshMaterials.Count; submeshMaterials.Add(material); int indexCount = submeshQuadCount * 6; int vertexIndex = (endQuadCount - submeshQuadCount) * 4; if (submeshes.Count <= submeshIndex) { submeshes.Add(new Submesh()); } Submesh submesh = submeshes[submeshIndex]; // Allocate indexes if not the right size, allowing last submesh to have more than required. int[] indexes = submesh.indexes; if (lastSubmesh ? (indexes.Length < indexCount) : (indexes.Length != indexCount)) { submesh.indexes = indexes = new int[indexCount]; submesh.indexCount = 0; } // Set indexes if not already set. if (submesh.firstVertex != vertexIndex || submesh.indexCount < indexCount) { submesh.indexCount = indexCount; submesh.firstVertex = vertexIndex; for (int i = 0; i < indexCount; i += 6, vertexIndex += 4) { indexes[i] = vertexIndex; indexes[i + 1] = vertexIndex + 2; indexes[i + 2] = vertexIndex + 1; indexes[i + 3] = vertexIndex + 2; indexes[i + 4] = vertexIndex + 3; indexes[i + 5] = vertexIndex + 1; } } // Last submesh may have more indices than required, so zero indexes to the end. if (lastSubmesh && submesh.indexCount != indexCount) { submesh.indexCount = indexCount; for (int i = indexCount, n = indexes.Length; i < n; i++) { indexes[i] = 0; } } }
/// <summary> /// Releases all resources used by an instance of the <see cref="RenderBatch{TVertex,TIndex}"/> class. /// </summary> public void Dispose() { if (IsDisposed) { return; } _renderContext = null; _submesh = null; _effectPassBinding = new EffectPassBinding(); _effectPassParameterBindings = null; _instanceVertexBuffer.Dispose(); IsDisposed = true; }
private static Submesh CreateSubmesh(GraphicsDevice graphicsDevice, TerrainVertex[] vertices, Array indices) { var submesh = new Submesh(); submesh.VertexBuffer = new VertexBuffer( graphicsDevice, TerrainVertex.VertexDeclaration, vertices.Length, BufferUsage.None); submesh.VertexBuffer.SetData(vertices); submesh.VertexCount = submesh.VertexBuffer.VertexCount; // Build array of indices. if (vertices.Length <= ushort.MaxValue) { var indicesUInt16 = indices as ushort[]; if (indicesUInt16 == null) { var indicesInt32 = (int[])indices; indicesUInt16 = new ushort[indices.Length]; for (int i = 0; i < indicesUInt16.Length; i++) { indicesUInt16[i] = (ushort)indicesInt32[i]; } } submesh.IndexBuffer = new IndexBuffer( graphicsDevice, IndexElementSize.SixteenBits, indicesUInt16.Length, BufferUsage.None); submesh.IndexBuffer.SetData(indicesUInt16); } else { var indicesInt32 = (int[])indices; submesh.IndexBuffer = new IndexBuffer( graphicsDevice, IndexElementSize.ThirtyTwoBits, indicesInt32.Length, BufferUsage.None); submesh.IndexBuffer.SetData(indicesInt32); } submesh.PrimitiveType = PrimitiveType.TriangleList; submesh.PrimitiveCount = indices.Length / 3; return(submesh); }
// Used in the Load method. private TerrainRendererMesh(int numberOfLevels, int cellsPerLevel, Submesh submesh) { NumberOfLevels = numberOfLevels; CellsPerLevel = cellsPerLevel; Submesh = submesh; }
public void Dispose() { LastNormalUpdateFrame = -1; Submesh = null; }
private static Submesh CreateSubmesh(GraphicsDevice graphicsDevice, TerrainVertex[] vertices, Array indices) { var submesh = new Submesh(); submesh.VertexBuffer = new VertexBuffer( graphicsDevice, TerrainVertex.VertexDeclaration, vertices.Length, BufferUsage.None); submesh.VertexBuffer.SetData(vertices); submesh.VertexCount = submesh.VertexBuffer.VertexCount; // Build array of indices. if (vertices.Length <= ushort.MaxValue) { var indicesUInt16 = indices as ushort[]; if (indicesUInt16 == null) { var indicesInt32 = (int[])indices; indicesUInt16 = new ushort[indices.Length]; for (int i = 0; i < indicesUInt16.Length; i++) indicesUInt16[i] = (ushort)indicesInt32[i]; } submesh.IndexBuffer = new IndexBuffer( graphicsDevice, IndexElementSize.SixteenBits, indicesUInt16.Length, BufferUsage.None); submesh.IndexBuffer.SetData(indicesUInt16); } else { var indicesInt32 = (int[])indices; submesh.IndexBuffer = new IndexBuffer( graphicsDevice, IndexElementSize.ThirtyTwoBits, indicesInt32.Length, BufferUsage.None); submesh.IndexBuffer.SetData(indicesInt32); } submesh.PrimitiveType = PrimitiveType.TriangleList; submesh.PrimitiveCount = indices.Length / 3; return submesh; }
//-------------------------------------------------------------- internal void Dispose() { if (_submesh != null) { _submesh.Dispose(); _submesh = null; } }
public override void AbcSampleUpdated(AbcAPI.aiSample sample, bool topologyChanged) { AlembicMaterial abcMaterials = m_trans.GetComponent<AlembicMaterial>(); if (abcMaterials != null) { if (abcMaterials.HasFacesetsChanged()) { AbcVerboseLog("AlembicMesh.AbcSampleUpdated: Facesets updated, force topology update"); topologyChanged = true; } hasFacesets = (abcMaterials.GetFacesetsCount() > 0); } else if (hasFacesets) { AbcVerboseLog("AlembicMesh.AbcSampleUpdated: Facesets cleared, force topology update"); topologyChanged = true; hasFacesets = false; } if (m_freshSetup) { topologyChanged = true; m_freshSetup = false; } AbcAPI.aiPolyMeshGetSampleSummary(sample, ref m_sampleSummary, topologyChanged); AbcAPI.aiMeshSampleData vertexData = default(AbcAPI.aiMeshSampleData); UpdateSplits(m_sampleSummary.splitCount); for (int s=0; s<m_sampleSummary.splitCount; ++s) { Split split = m_splits[s]; split.clear = topologyChanged; split.active = true; int vertexCount = AbcAPI.aiPolyMeshGetVertexBufferLength(sample, s); Array.Resize(ref split.positionCache, vertexCount); vertexData.positions = GetArrayPtr(split.positionCache); if (m_sampleSummary.hasNormals) { Array.Resize(ref split.normalCache, vertexCount); vertexData.normals = GetArrayPtr(split.normalCache); } else { Array.Resize(ref split.normalCache, 0); vertexData.normals = IntPtr.Zero; } if (m_sampleSummary.hasUVs) { Array.Resize(ref split.uvCache, vertexCount); vertexData.uvs = GetArrayPtr(split.uvCache); } else { Array.Resize(ref split.uvCache, 0); vertexData.uvs = IntPtr.Zero; } if (m_sampleSummary.hasTangents) { Array.Resize(ref split.tangentCache, vertexCount); vertexData.tangents = GetArrayPtr(split.tangentCache); } else { Array.Resize(ref split.tangentCache, 0); vertexData.tangents = IntPtr.Zero; } AbcAPI.aiPolyMeshFillVertexBuffer(sample, s, ref vertexData); split.center = vertexData.center; split.size = vertexData.size; } if (topologyChanged) { AbcAPI.aiFacesets facesets = default(AbcAPI.aiFacesets); AbcAPI.aiSubmeshSummary submeshSummary = default(AbcAPI.aiSubmeshSummary); AbcAPI.aiSubmeshData submeshData = default(AbcAPI.aiSubmeshData); if (abcMaterials != null) { abcMaterials.GetFacesets(ref facesets); } int numSubmeshes = AbcAPI.aiPolyMeshPrepareSubmeshes(sample, ref facesets); if (m_submeshes.Count > numSubmeshes) { m_submeshes.RemoveRange(numSubmeshes, m_submeshes.Count - numSubmeshes); } for (int s=0; s<m_sampleSummary.splitCount; ++s) { m_splits[s].submeshCount = AbcAPI.aiPolyMeshGetSplitSubmeshCount(sample, s); } while (AbcAPI.aiPolyMeshGetNextSubmesh(sample, ref submeshSummary)) { if (submeshSummary.splitIndex >= m_splits.Count) { Debug.Log("Invalid split index"); continue; } Submesh submesh = null; if (submeshSummary.index < m_submeshes.Count) { submesh = m_submeshes[submeshSummary.index]; } else { submesh = new Submesh { indexCache = new int[0], facesetIndex = -1, splitIndex = -1, index = -1, update = true }; m_submeshes.Add(submesh); } submesh.facesetIndex = submeshSummary.facesetIndex; submesh.splitIndex = submeshSummary.splitIndex; submesh.index = submeshSummary.splitSubmeshIndex; submesh.update = true; Array.Resize(ref submesh.indexCache, 3 * submeshSummary.triangleCount); submeshData.indices = GetArrayPtr(submesh.indexCache); AbcAPI.aiPolyMeshFillSubmeshIndices(sample, ref submeshSummary, ref submeshData); } if (abcMaterials != null) { abcMaterials.AknowledgeFacesetsChanges(); } } else { for (int i=0; i<m_submeshes.Count; ++i) { m_submeshes[i].update = false; } } AbcDirty(); }
/// <inheritdoc/> protected override void Dispose(bool disposing) { if (!IsDisposed) { if (disposing) { _noiseMap.Dispose(); if (_quadSubmesh != null) { _quadSubmesh.Dispose(); _quadSubmesh = null; } ProjectedGridParameters.Dispose(); } } base.Dispose(disposing); }
public CloudLayerRenderer(IGraphicsService graphicsService) { if (graphicsService == null) throw new ArgumentNullException("graphicsService"); if (graphicsService.GraphicsDevice.GraphicsProfile == GraphicsProfile.Reach) throw new NotSupportedException("The CloudLayerRenderer does not support the Reach profile."); _effect = graphicsService.Content.Load<Effect>("DigitalRune/Sky/CloudLayer"); _parameterView = _effect.Parameters["View"]; _parameterProjection = _effect.Parameters["Projection"]; _parameterSunDirection = _effect.Parameters["SunDirection"]; _parameterSkyCurvature = _effect.Parameters["SkyCurvature"]; _parameterTextureMatrix = _effect.Parameters["Matrix0"]; _parameterNumberOfSamples = _effect.Parameters["NumberOfSamples"]; _parameterSampleDistance = _effect.Parameters["SampleDistance"]; _parameterScatterParameters = _effect.Parameters["ScatterParameters"]; _parameterHorizonFade = _effect.Parameters["HorizonFade"]; _parameterSunLight = _effect.Parameters["SunLight"]; _parameterAmbientLight = _effect.Parameters["AmbientLight"]; _parameterTexture = _effect.Parameters["NoiseTexture0"]; _passCloudRgbLinear = _effect.Techniques[0].Passes["CloudRgbLinear"]; _passCloudAlphaLinear = _effect.Techniques[0].Passes["CloudAlphaLinear"]; _passCloudRgbGamma = _effect.Techniques[0].Passes["CloudRgbGamma"]; _passCloudAlphaGamma = _effect.Techniques[0].Passes["CloudAlphaGamma"]; _passOcclusionRgb = _effect.Techniques[0].Passes["OcclusionRgb"]; _passOcclusionAlpha = _effect.Techniques[0].Passes["OcclusionAlpha"]; // We render a spherical patch into the sky. But any mesh which covers the top // hemisphere works too. //_submesh = MeshHelper.CreateSpherePatch(graphicsService.GraphicsDevice, 1, 1.1f, 10); _submesh = MeshHelper.CreateBox(graphicsService.GraphicsDevice); _queryGeometry = new Vector3F[4]; }
public ScatteringSkyRenderer(IGraphicsService graphicsService) { if (graphicsService == null) throw new ArgumentNullException("graphicsService"); if (graphicsService.GraphicsDevice.GraphicsProfile == GraphicsProfile.Reach) throw new NotSupportedException("The ScatteringSkyRenderer does not support the Reach profile."); _effect = graphicsService.Content.Load<Effect>("DigitalRune/Sky/ScatteringSky"); _parameterView = _effect.Parameters["View"]; _parameterProjection = _effect.Parameters["Projection"]; _parameterSunDirection = _effect.Parameters["SunDirection"]; _parameterRadii = _effect.Parameters["Radii"]; _parameterNumberOfSamples = _effect.Parameters["NumberOfSamples"]; _parameterBetaRayleigh = _effect.Parameters["BetaRayleigh"]; _parameterBetaMie = _effect.Parameters["BetaMie"]; _parameterGMie = _effect.Parameters["GMie"]; _parameterSunIntensity = _effect.Parameters["SunIntensity"]; _parameterTransmittance = _effect.Parameters["Transmittance"]; _parameterBaseHorizonColor = _effect.Parameters["BaseHorizonColor"]; _parameterBaseZenithColor = _effect.Parameters["BaseZenithColor"]; _passLinear = _effect.Techniques[0].Passes["Linear"]; _passGamma = _effect.Techniques[0].Passes["Gamma"]; _passLinearWithBaseColor = _effect.Techniques[0].Passes["LinearWithBaseColor"]; _passGammaWithBaseColor = _effect.Techniques[0].Passes["GammaWithBaseColor"]; _submesh = MeshHelper.GetBox(graphicsService); }
public void Dispose() { ClipSubmesh = null; }
private static Submesh GetStarfieldMesh(StarfieldNode node, RenderContext context) { // The mesh is cached in the scene node. var mesh = node.RenderData as Submesh; if (mesh == null) { mesh = new Submesh { PrimitiveType = PrimitiveType.TriangleList }; node.RenderData = mesh; } if (mesh.VertexBuffer == null || mesh.VertexBuffer.IsDisposed) { int numberOfStars = node.Stars.Count; // The total number of stars is limited by the graphics device max primitives per call limit. var graphicsDevice = context.GraphicsService.GraphicsDevice; int maxNumberOfStars = graphicsDevice.GetMaxPrimitivesPerCall() / 2; if (numberOfStars > maxNumberOfStars) throw new GraphicsException("The number of stars must be less than " + maxNumberOfStars); // Create a vertex buffer with a quad for each star. // 1--2 // | /| // |/ | // 0--3 mesh.VertexCount = numberOfStars * 4; var vertices = new StarVertex[numberOfStars * 4]; for (int i = 0; i < numberOfStars; i++) { var star = node.Stars[i]; var positionAndSize = new HalfVector4(star.Position.X, star.Position.Y, star.Position.Z, star.Size); var color = new HalfVector4(star.Color.X, star.Color.Y, star.Color.Z, 1); vertices[i * 4 + 0].PositionAndSize = positionAndSize; vertices[i * 4 + 0].Color = color; vertices[i * 4 + 0].Texture = new Vector2(0, 1); vertices[i * 4 + 1].PositionAndSize = positionAndSize; vertices[i * 4 + 1].Color = color; vertices[i * 4 + 1].Texture = new Vector2(0, 0); vertices[i * 4 + 2].PositionAndSize = positionAndSize; vertices[i * 4 + 2].Color = color; vertices[i * 4 + 2].Texture = new Vector2(1, 0); vertices[i * 4 + 3].PositionAndSize = positionAndSize; vertices[i * 4 + 3].Color = color; vertices[i * 4 + 3].Texture = new Vector2(1, 1); } mesh.VertexBuffer = new VertexBuffer(graphicsDevice, typeof(StarVertex), vertices.Length, BufferUsage.None); mesh.VertexBuffer.SetData(vertices); // Create index buffer for quad (= two triangles, clockwise). var indices = new ushort[numberOfStars * 6]; for (int i = 0; i < numberOfStars; i++) { indices[i * 6 + 0] = (ushort)(i * 4 + 0); indices[i * 6 + 1] = (ushort)(i * 4 + 1); indices[i * 6 + 2] = (ushort)(i * 4 + 2); indices[i * 6 + 3] = (ushort)(i * 4 + 0); indices[i * 6 + 4] = (ushort)(i * 4 + 2); indices[i * 6 + 5] = (ushort)(i * 4 + 3); } mesh.IndexBuffer = new IndexBuffer(graphicsDevice, IndexElementSize.SixteenBits, indices.Length, BufferUsage.None); mesh.IndexBuffer.SetData(indices); mesh.PrimitiveCount = numberOfStars * 2; } return mesh; }
private void RenderSurface(WaterNode node, CameraNode cameraNode, bool isCameraUnderwater) { var graphicsDevice = _graphicsService.GraphicsDevice; var projection = cameraNode.Camera.Projection; graphicsDevice.RasterizerState = RasterizerState.CullNone; //graphicsDevice.RasterizerState = isCameraUnderwater ? RasterizerState.CullClockwise : RasterizerState.CullCounterClockwise; //graphicsDevice.RasterizerState = GraphicsHelper.RasterizerStateWireFrame; graphicsDevice.DepthStencilState = node.DepthBufferWriteEnable ? DepthStencilState.Default : DepthStencilState.DepthRead; // TODO: Support gamma corrected LDR rendering. //if (context.IsHdrEnabled()) _passGamma... if (node.Volume != null) { // ----- Render with user-defined water volume. var data = ((WaterRenderData)node.RenderData); _parameterWorld.SetValue((Matrix)( node.PoseWorld * Matrix44F.CreateScale(node.ScaleWorld) * data.SubmeshMatrix)); ApplySurfacePass(node, false); data.Submesh.Draw(); } else if (node.Waves == null || node.Waves.DisplacementMap == null) { // ----- Infinite ocean without displacement map. // Draw using simple, gigantic quad. if (_quadSubmesh == null) { // This is the really lazy way to get a quad submesh. :-P var quadShape = new TransformedShape(new GeometricObject( new RectangleShape(1, 1), new Pose(Matrix33F.CreateRotationX(-ConstantsF.PiOver2)))).GetMesh(0.001f, 4); _quadSubmesh = MeshHelper.CreateSubmesh(graphicsDevice, quadShape, -1); } // Position the quad under the camera and choose a size large enough to cover everything. Vector3F position = cameraNode.PoseWorld.Position; position.Y = node.PoseWorld.Position.Y; // Add a bit to make sure that the surface is rendered above the underwater geometry. // Without the epsilon if the camera cuts the surface, there might be a horizontal ~1 pixel // line when the surface quad ends before the underwater shape. position.Y += Numeric.EpsilonF * 10; float farPlaneRadius = new Vector3F(Math.Max(Math.Abs(projection.Right), Math.Abs(projection.Left)), Math.Max(Math.Abs(projection.Top), Math.Abs(projection.Bottom)), projection.Far ).Length; float size = 2 * farPlaneRadius; Matrix44F world = Matrix44F.CreateTranslation(position) * Matrix44F.CreateScale(size, 1, size); _parameterWorld.SetValue((Matrix)world); ApplySurfacePass(node, false); _quadSubmesh.Draw(); } else { // ----- Use Projected Grid. if (SetProjectedGridParameters(node, cameraNode, isCameraUnderwater)) { ApplySurfacePass(node, true); ProjectedGridParameters.Submesh.Draw(); } } }
private void RenderUnderwaterGeometry(WaterNode node, CameraNode cameraNode) { var graphicsDevice = _graphicsService.GraphicsDevice; graphicsDevice.RasterizerState = RasterizerState.CullNone; //graphicsDevice.RasterizerState = GraphicsHelper.RasterizerStateWireFrame; graphicsDevice.DepthStencilState = DepthStencilState.None; var data = ((WaterRenderData)node.RenderData); var submesh = data.Submesh; if (submesh != null) { // User-defined volume _parameterWorld.SetValue((Matrix)( node.PoseWorld * Matrix44F.CreateScale(node.ScaleWorld) * data.SubmeshMatrix)); } else { // Underwater rendering of infinite ocean. // --> Use a shared box around the camera. if (_boxSubmesh == null) _boxSubmesh = MeshHelper.GetBox(_graphicsService); // The box must not be clipped at near or far plane: // Make the box extent (size, size / 2, size) with size / 2 = (near + far) / 2. var projection = cameraNode.Camera.Projection; float size = projection.Near + projection.Far; // The box is centered on the camera. (Ignore camera orientation in case // the camera has a roll.) Vector3F position = cameraNode.PoseWorld.Position; // Top of box must go through water node origin, except when waves are // rendered. (Waves are bent up or down at the near plane.) if (node.Waves == null || node.Waves.DisplacementMap == null) position.Y = node.PoseWorld.Position.Y - size / 4.0f; var world = Matrix44F.CreateTranslation(position) * Matrix44F.CreateScale(size, size / 2.0f, size); _parameterWorld.SetValue((Matrix)world); submesh = _boxSubmesh; } if (node.Water.CausticsSampleOffset <= 0 || node.Water.CausticsIntensity <= Numeric.EpsilonF) _passUnderwater.Apply(); else _passUnderwaterCaustics.Apply(); submesh.Draw(); }
private void InitializeHiDef(IGraphicsService graphicsService) { _submesh = MeshHelper.GetBox(graphicsService); _effect = graphicsService.Content.Load<Effect>("DigitalRune/Sky/Skybox"); _parameterWorldViewProjection = _effect.Parameters["WorldViewProjection"]; _parameterColor = _effect.Parameters["Color"]; _parameterRgbmMaxValue = _effect.Parameters["RgbmMax"]; _parameterTextureSize = _effect.Parameters["TextureSize"]; _textureParameter = _effect.Parameters["Texture"]; _passRgbToRgb = _effect.CurrentTechnique.Passes["RgbToRgb"]; _passSRgbToRgb = _effect.CurrentTechnique.Passes["SRgbToRgb"]; _passRgbmToRgb = _effect.CurrentTechnique.Passes["RgbmToRgb"]; _passRgbToSRgb = _effect.CurrentTechnique.Passes["RgbToSRgb"]; _passSRgbToSRgb = _effect.CurrentTechnique.Passes["SRgbToSRgb"]; _passRgbmToSRgb = _effect.CurrentTechnique.Passes["RgbmToSRgb"]; }
public void DrawMesh(Submesh submesh, Pose pose, Vector3F scale, Color color, bool drawWireFrame, bool drawOverScene) { if (!Enabled || submesh == null) return; if (!drawWireFrame && drawOverScene) throw new NotSupportedException("Drawing solid objects with disabled depth test is not yet supported."); PrimitiveBatch batch; if (drawOverScene) batch = OverSceneWireFramePrimitiveBatch; else if (drawWireFrame) batch = InSceneWireFramePrimitiveBatch; else if (color.A == 255) batch = OpaquePrimitiveBatch; else batch = TransparentPrimitiveBatch; batch.AddSubmesh(submesh, pose, scale, color); }