private static void ExecuteDrawCall(DrawCall call) { return; //Handles.color = call.color; //switch (call.type) { // case DrawType.WireCube: // Handles.DrawWireCube((Vector3) call.parameters[0], (Vector3) call.parameters[1]); // break; // case DrawType.Cube: // // TODO implement // //Handles.DrawCube((Vector3) call.parameters[0], (Vector3) call.parameters[1]); // break; // case DrawType.WireSphere: // Handles.DrawWireDisc((Vector3) call.parameters[0], Vector3.up, (float) call.parameters[1]); // Handles.DrawWireDisc((Vector3) call.parameters[0], Vector3.right, (float) call.parameters[1]); // Handles.DrawWireDisc((Vector3) call.parameters[0], new Vector3(1, 0, 1).normalized, (float) call.parameters[1]); // Handles.DrawWireDisc((Vector3) call.parameters[0], Vector3.forward, (float) call.parameters[1]); // Handles.DrawWireDisc((Vector3) call.parameters[0], new Vector3(-1, 0, 1).normalized, (float) call.parameters[1]); // break; // case DrawType.Sphere: // // TODO implement // //Handles.DrawSphere((Vector3) call.parameters[0], (float) call.parameters[1]); // break; // case DrawType.WireMesh: // Graphics.DrawMeshNow((Mesh) call.parameters[0], (Vector3) call.parameters[1], (Quaternion) call.parameters[2]); // break; //} }
public void NameColor() { MDL0Node model = ((MDL0Node)_resource); MDL0GroupNode g = model._colorGroup; if (g != null) { foreach (MDL0ColorNode v in g.Children) { string name = model.Name + "_"; if (v._objects.Count > 0) { MDL0ObjectNode o = v._objects[0]; name += o.Name; if (o._drawCalls.Count > 0) { DrawCall c = o._drawCalls[0]; if (c.MaterialNode != null && c.VisibilityBoneNode != null) { name += "_" + c.Material + "_" + c.VisibilityBone; } } } else { name += "ColorArray"; } v.Name = g.FindName(name); } } }
private void SendActiveEvent(MouseInput input) { InputData newInput = CreateInputData(input); switch (input.State) { case InputState.Start: StartDraw?.Invoke(newInput); _previousInput = newInput; break; case InputState.Draw: if (newInput.Position != _previousInput.Position) { DrawCall?.Invoke(newInput); _previousInput = newInput; } break; case InputState.End: EndDraw?.Invoke(newInput); _previousInput = default; break; default: throw new Exception("Try send active event to disactive input"); } }
void Start() { DrawCall drawCall = new DrawCall(new Sphere("球形"), new OpenGL()); drawCall.StartDraw(); drawCall.StopDraw(); }
/// <summary> /// Get the vertex shader output for the /// respective primitive ID and instance. /// </summary> /// <param name="primitiveID"></param> /// <param name="instanceID"></param> private void GetVertexShaderOutput(int primitiveID, int instanceID) { if (DrawCall?.cmd?.Count == 0) { return; } var vertexShader = VertexShader; // set shader input gl_PrimitiveIDIn = primitiveID; // load patch data from vertex shader var patch = DrawCall.GetPatch(primitiveID); DebugGetError(new StackTrace(true)); gl_in = __InOut.Create(patch.Length); for (int i = 0; i < patch.Length; i++) { // compute vertex shader output var vertexID = Convert.ToInt32(patch.GetValue(i)); vertexShader.Execute(vertexID, instanceID); // set geometry shader built in input varyings gl_in[i].gl_Position = vertexShader.GetOutputVarying <vec4>("gl_Position"); gl_in[i].gl_PointSize = vertexShader.GetOutputVarying <float>("gl_PointSize"); var clipDistance = vertexShader.GetOutputVarying <float[]>("gl_ClipDistance"); for (int j = 0; j < clipDistance.Length; j++) { gl_in[i].gl_ClipDistance[j] = clipDistance[j]; } // set geometry shader user input varyings ProcessFields(this, ProcessInField, new[] { typeof(__in) }, i); } }
/// <summary> /// Uses the spriteBatch to draw a given Drawcall onto the active rendertarget. Must be within spriteBatch.begin/end /// </summary> /// <param name="spriteBatch">Spritebatch to use</param> /// <param name="drawCall">The drawcall to draw</param> protected void ApplyDrawCallToScene(SpriteBatch spriteBatch, DrawCall drawCall) { if (drawCall.texture == null) { //Text spriteBatch.DrawString(drawCall.font, drawCall.text, drawCall.position, drawCall.color, drawCall.rotation, drawCall.origin, drawCall.scale, drawCall.spriteEffects, drawCall.depth); } else { if (drawCall.useVectorPos) { if (drawCall.useSourceRectangle) { spriteBatch.Draw(drawCall.texture, drawCall.position, drawCall.SourceRectangle, drawCall.color, drawCall.rotation, drawCall.origin, drawCall.scale, drawCall.spriteEffects, 0f); } else { spriteBatch.Draw(drawCall.texture, drawCall.position, null, drawCall.color, drawCall.rotation, drawCall.origin, drawCall.scale, drawCall.spriteEffects, 0f); } } else { if (drawCall.useSourceRectangle) { spriteBatch.Draw(drawCall.texture, drawCall.Rectangle, drawCall.SourceRectangle, drawCall.color, drawCall.rotation, drawCall.origin, drawCall.spriteEffects, 0f); } else { spriteBatch.Draw(drawCall.texture, drawCall.Rectangle, null, drawCall.color, drawCall.rotation, drawCall.origin, drawCall.spriteEffects, 0f); } } } }
/// <summary> /// Get the output from the vertex shader. /// </summary> /// <param name="primitiveID"></param> /// <param name="instanceID"></param> private void GetVertexShaderOutput(int primitiveID, int instanceID) { if (DrawCall?.cmd?.Count == 0) { return; } // load patch data from vertex shader var patch = DrawCall.GetPatch(primitiveID); DebugGetError(new StackTrace(true)); gl_PatchVerticesIn = patch.Length; gl_PrimitiveID = primitiveID; for (int i = 0; i < gl_PatchVerticesIn; i++) { // compute vertex shader data VertShader.Execute(Convert.ToInt32(patch.GetValue(i)), instanceID); // set input data for the vertex gl_in[i].gl_Position = VertShader.GetOutputVarying <vec4>("gl_Position"); gl_in[i].gl_PointSize = VertShader.GetOutputVarying <float>("gl_PointSize"); var clipDistance = VertShader.GetOutputVarying <float[]>("gl_ClipDistance"); for (int j = 0; j < clipDistance.Length; j++) { gl_in[i].gl_ClipDistance[j] = clipDistance[j]; } } }
public void Draw(DrawCall.Tag tag, Texture2D texture, Rectangle rectangle, Rectangle sourceRectangle, Color color, float depth) { DrawCall toAdd = new DrawCall(tag, texture, rectangle, sourceRectangle, 0f, Vector2.Zero, color, depth, SpriteEffects.None); if (toAdd.Rectangle.Intersects(Game1.camera.Rectangle)) { drawCalls.Add(depth, toAdd); } }
public void Draw(DrawCall.Tag tag, Texture2D texture, Rectangle rectangle, float rotation, Vector2 origin, Color color, float depth) { DrawCall toAdd = new DrawCall(tag, texture, rectangle, rotation, origin, color, depth, SpriteEffects.None); if (toAdd.Rectangle.Intersects(Game1.camera.Rectangle)) { drawCalls.Add(depth, toAdd); } }
/// <summary> /// /// </summary> /// <param name="tag"></param> /// <param name="texture"></param> /// <param name="rectangle"></param> /// <param name="sourceRectangle"></param> /// <param name="rotation"></param> /// <param name="origin"></param> /// <param name="color"></param> /// <param name="depth"></param> /// <param name="spriteEffects"></param> /// <param name="affectedByLight">0 - always dark, 1 - dynamic, 2 - always bright</param> /// <param name="lightBleedThrough">The amount of light able to pass through the object</param> public void Draw(DrawCall.Tag tag, Texture2D texture, Rectangle rectangle, Rectangle sourceRectangle, float rotation, Vector2 origin, Color color, float depth, SpriteEffects spriteEffects, short affectedByLight, float lightBleedThrough) { DrawCall toAdd = new DrawCall(tag, texture, rectangle, sourceRectangle, rotation, origin, color, depth, spriteEffects, affectedByLight, lightBleedThrough); if (toAdd.Rectangle.Intersects(Game1.camera.Rectangle)) { drawCalls.Add(depth, toAdd); } }
public void Draw(DrawCall.Tag tag, Texture2D texture, Vector2 position, Rectangle sourceRectangle, Vector2 scale, float rotation, Vector2 origin, Color color, float depth, SpriteEffects spriteEffects) { DrawCall toAdd = new DrawCall(tag, texture, position, sourceRectangle, scale, rotation, origin, color, depth, spriteEffects, 0, 0); if (toAdd.Rectangle.Intersects(Game1.camera.Rectangle)) { drawCalls.Add(depth, toAdd); } }
private static void WritePolygon(StreamWriter writer, DrawCall c) { MDL0ObjectNode poly = c._parentObject; if (poly._manager._vertices != null) { int count = poly._manager._vertices.Count; Vector3[] Vertices = new Vector3[count]; //Weight vertices poly.Model.WeightMeshes(); //Set weighted positions for (int i = 0; i < count; i++) { Vertices[i] = poly._manager._vertices[i].WeightedPosition; } WriteVertexGroup(writer, Vertices); } if (poly._manager._faceData[1] != null) { WriteNormalGroup(writer, poly._manager, true); } for (int i = 0; i < 1; i++) //Obj only supports 1 uv coord set... { if (poly._manager._faceData[i + 4] != null) { WriteUVGroup(writer, poly._manager._faceData[i + 4]); } } writer.WriteLine(); writer.WriteLine(string.Format("g {0}", poly.Name)); if (c._material != null) { WriteMaterial(writer, c._material); } if (poly._manager != null) { if (poly._manager._triangles != null) { WriteTriList(writer, poly._manager); } //if (poly._manager._lines != null) //{ //} //if (poly._manager._points != null) //{ //} } }
private void btnNew_Click(object sender, EventArgs e) { if (_targetObject != null) { DrawCall d = new DrawCall(_targetObject); _targetObject._drawCalls.Add(d); _targetObject.OnDrawCallsChanged(); _targetObject.Model.RegenerateVIS0Indices(); _targetObject.SignalPropertyChange(); } }
//#endif private static void RegisterDrawCall(DrawType type, Color color, params object[] parameters) { #if UNITY_EDITOR Initialize(); DrawCall call = new DrawCall() { type = type, color = color, parameters = parameters }; drawCalls.Enqueue(call); //drawCalls.Add(call); #else Debug.LogWarning("Trying to register a debug draw on a non editor build!"); #endif }
private void numDrawOrder_ValueChanged(object sender, EventArgs e) { if (_updating) { return; } DrawCall drawCall = lstDrawCalls.SelectedItem as DrawCall; if (drawCall != null) { drawCall.DrawPriority = (byte)numDrawOrder.Value; } }
private void cboDrawPass_SelectedIndexChanged(object sender, EventArgs e) { if (_updating) { return; } DrawCall drawCall = lstDrawCalls.SelectedItem as DrawCall; if (drawCall != null) { drawCall.DrawPass = (DrawCall.DrawPassType)cboDrawPass.SelectedIndex; } }
/// <summary> /// Uses the spriteBatch to draw a given Drawcall onto the active rendertarget. Must be within spriteBatch.begin/end /// Draws the depth of the object as the amount of red color and the rest 0 /// </summary> /// <param name="spriteBatch">Spritebatch to use</param> /// <param name="drawCall">The drawcall to draw</param> protected void ApplyDrawCallDepthToMask(SpriteBatch spriteBatch, DrawCall drawCall) { float depth = drawCall.depth; float lightBleedThrough = drawCall.lightBleedThrough; if (drawCall.affectedByLight == 0) { depth = 1; lightBleedThrough = 1; } else if (drawCall.affectedByLight == 2) { depth = 0; lightBleedThrough = 0; } if (drawCall.texture == null) { //Text spriteBatch.DrawString(drawCall.font, drawCall.text, drawCall.position, drawCall.color, drawCall.rotation, drawCall.origin, drawCall.scale, drawCall.spriteEffects, drawCall.depth); } else { if (drawCall.useVectorPos) { if (drawCall.useSourceRectangle) { spriteBatch.Draw(drawCall.texture, drawCall.position, drawCall.SourceRectangle, new Color(depth, 1 - lightBleedThrough, 0, 1), drawCall.rotation, drawCall.origin, drawCall.scale, drawCall.spriteEffects, 0f); } else { spriteBatch.Draw(drawCall.texture, drawCall.position, null, new Color(depth, 1 - lightBleedThrough, 0, 1), drawCall.rotation, drawCall.origin, drawCall.scale, drawCall.spriteEffects, 0f); } } else { if (drawCall.useSourceRectangle) { spriteBatch.Draw(drawCall.texture, drawCall.Rectangle, drawCall.SourceRectangle, new Color(depth, 1 - lightBleedThrough, 0, 1), drawCall.rotation, drawCall.origin, drawCall.spriteEffects, 0f); } else { spriteBatch.Draw(drawCall.texture, drawCall.Rectangle, null, new Color(depth, 1 - lightBleedThrough, 0, 1), drawCall.rotation, drawCall.origin, drawCall.spriteEffects, 0f); } } } }
private void cboVisBone_SelectedIndexChanged(object sender, EventArgs e) { if (_updating) { return; } DrawCall drawCall = lstDrawCalls.SelectedItem as DrawCall; if (drawCall != null) { drawCall.VisibilityBoneNode = cboVisBone.SelectedItem as MDL0BoneNode; drawCall._parentObject.Model.RegenerateVIS0Indices(); drawCall._parentObject.SignalPropertyChange(); } }
//Called every frame, after update has completed. It is wrapped in code that //managed the render state, so don't call DrawCall.Perform() outside of here. static void Render() { //First we setup our draw call var draw = new DrawCall(null, material, mesh, BlendMode.Premultiplied); material.SetMatrix4x4("Matrix", Matrix4x4.CreateOrthographic(Screen.Width, Screen.Height, -1f, 1f)); //Then we'll draw the logo { //The material is how we interact with shaders material.SetTexture("Texture", logo); //A mesh defines the geometry of what we're drawing mesh.Clear(); var rect = Rectangle.Box(new Vector2(Screen.Width / 2, Screen.Height / 2 - 32), logo.Width, logo.Height); mesh.AddRect(rect, Vector2.Zero, Vector2.One); mesh.Update(); //To render, we setup a draw call and then perform it draw.Perform(PrimitiveType.Triangles); } //After we call Perform(), we can change stuff and then call Perform() again //The the rendering system will internally optimize the draw state { material.SetTexture("Texture", star); mesh.Clear(); for (int i = 0; i < positions.Length; ++i) { float a = i / (positions.Length - 1f); mesh.AddRect(positions[i], Vector2.Zero, Vector2.One); } mesh.Update(); draw.Perform(PrimitiveType.Triangles); } //This might seem tedious, but in reality this will be wrapped in components //or some kind of rendering class! For example, the Atlas automatically allows //us to pack textures/fonts into atlases, and the DrawBatch2D allows us to //use simple draw functions between a Begin() and End() //We just want to provide a low-level API so you have lots of options }
public IDrawCall[] Process(IScene scene) { IDrawCall[] drawCalls = new DrawCall[scene.meshes.Length]; for (int i = drawCalls.Length - 1; i >= 0; i--) { IMesh mesh = scene.meshes[i]; IDrawCall drawCall = new DrawCall(); drawCall.vertices = Array.ConvertAll <Vector3, Vector4>(mesh.vertices, (Vector3 each) => new Vector4(each.x, each.y, each.z, 1)); drawCall.normals = new Vector3[mesh.normals.Length]; mesh.normals.CopyTo(drawCall.normals, 0); drawCall.indices = new int[mesh.indices.Length]; mesh.indices.CopyTo(drawCall.indices, 0); drawCall.M = mesh.M; drawCalls[i] = drawCall; } return(drawCalls); }
private void btnDelete_Click(object sender, EventArgs e) { if (lstDrawCalls.SelectedIndices != null) { for (int x = lstDrawCalls.SelectedIndices.Count - 1; x >= 0; x--) { DrawCall drawCall = lstDrawCalls.Items[lstDrawCalls.SelectedIndices[x]] as DrawCall; if (drawCall != null) { MDL0ObjectNode o = drawCall._parentObject; o._drawCalls.Remove(drawCall); o.OnDrawCallsChanged(); o.Model.RegenerateVIS0Indices(); o.SignalPropertyChange(); } } } }
private void lstDrawCalls_DoubleClick(object sender, EventArgs e) { if (_updating) { return; } DrawCall drawCall = lstDrawCalls.SelectedItem as DrawCall; if (drawCall != null) { drawCall._render = !drawCall._render; lstDrawCalls.SetItemChecked(lstDrawCalls.SelectedIndex, drawCall._render); if (_targetObject?.Model != null) { TKContext.InvalidateModelPanels(_targetObject.Model); } } }
public void Draw(object sender, GraphicsEventArgs args) { for (int i = 0; i < this.calls.Count; i++) { DrawCall call = calls[i]; if (Environment.TickCount <= call.ValidUntil) { Vector2 position = this.Scale(call.RenderX, call.RenderY); Vector2 size = this.Scale(call.Width, call.Height); Vector2 rotationCenter = new Vector2(position.X + (size.X * call.RotationCenterX), position.Y + (size.Y * call.RotationCenterY)); args.Graphics.DrawTexture(this.textures[call.TextureId], position, size, 0.0f, 0.0f, 1.0f, 1.0f, call.Rotation, rotationCenter); } else { calls.Remove(call); i--; } } }
private void cboMaterial_SelectedIndexChanged(object sender, EventArgs e) { if (_updating) { return; } DrawCall drawCall = lstDrawCalls.SelectedItem as DrawCall; if (drawCall != null) { drawCall.MaterialNode = cboMaterial.SelectedItem as MDL0MaterialNode; drawCall._parentObject.SignalPropertyChange(); //lstDrawCalls.BeginUpdate(); //int i = lstDrawCalls.SelectedIndex; //lstDrawCalls.DataSource = _targetObject._drawCalls; //lstDrawCalls.SelectedIndex = i; //lstDrawCalls.EndUpdate(); } }
private void lstDrawCalls_SelectedIndexChanged(object sender, EventArgs e) { DrawCall drawCall = lstDrawCalls.SelectedItem as DrawCall; if (drawCall != null) { _updating = true; cboMaterial.SelectedIndex = drawCall.MaterialNode != null ? drawCall.MaterialNode.Index : -1; cboVisBone.SelectedIndex = drawCall.VisibilityBoneNode != null ? drawCall.VisibilityBoneNode.BoneIndex : -1; _prevDrawOrder = numDrawOrder.Value = drawCall.DrawPriority; numDrawOrder.Enabled = !(chkDoesntMatter.Checked = drawCall.DrawPriority == 0); cboDrawPass.SelectedIndex = (int)drawCall.DrawPass; lstDrawCalls.SetItemChecked(lstDrawCalls.SelectedIndex, drawCall._render); _updating = false; //drawCall._render = true; } }
public IGraphicsService PushDrawCall(string DrawStackID, DrawCall DC) { _drawStacks[DrawStackID].PushDrawCall(DC); return(this); }
public void SetLastUser(DrawCall lastUser) => LastUser = lastUser;
private Mesh CreateGltfMesh(string meshName, VMesh vmesh, ModelRoot model, bool includeJoints) { ProgressDialog.SetProgress($"Creating mesh: {meshName}"); var data = vmesh.GetData(); var vbib = vmesh.VBIB; var mesh = model.CreateMesh(meshName); mesh.Name = meshName; foreach (var sceneObject in data.GetArray("m_sceneObjects")) { foreach (var drawCall in sceneObject.GetArray("m_drawCalls")) { var vertexBufferInfo = drawCall.GetArray("m_vertexBuffers")[0]; // In what situation can we have more than 1 vertex buffer per draw call? var vertexBufferIndex = (int)vertexBufferInfo.GetIntegerProperty("m_hBuffer"); var vertexBuffer = vbib.VertexBuffers[vertexBufferIndex]; var indexBufferInfo = drawCall.GetSubCollection("m_indexBuffer"); var indexBufferIndex = (int)indexBufferInfo.GetIntegerProperty("m_hBuffer"); var indexBuffer = vbib.IndexBuffers[indexBufferIndex]; // Create one primitive per draw call var primitive = mesh.CreatePrimitive(); // Avoid duplicate attribute names var attributeCounters = new Dictionary <string, int>(); // Set vertex attributes foreach (var attribute in vertexBuffer.Attributes) { attributeCounters.TryGetValue(attribute.Name, out var attributeCounter); attributeCounters[attribute.Name] = attributeCounter + 1; var accessorName = GetAccessorName(attribute.Name, attributeCounter); var buffer = ReadAttributeBuffer(vertexBuffer, attribute); var numComponents = buffer.Length / vertexBuffer.Count; if (attribute.Name == "BLENDINDICES") { if (!includeJoints) { continue; } var byteBuffer = buffer.Select(f => (byte)f).ToArray(); var rawBufferData = new byte[buffer.Length]; System.Buffer.BlockCopy(byteBuffer, 0, rawBufferData, 0, rawBufferData.Length); var bufferView = mesh.LogicalParent.UseBufferView(rawBufferData); var accessor = mesh.LogicalParent.CreateAccessor(); accessor.SetVertexData(bufferView, 0, buffer.Length / 4, DimensionType.VEC4, EncodingType.UNSIGNED_BYTE); primitive.SetVertexAccessor(accessorName, accessor); continue; } if (attribute.Name == "NORMAL" && DrawCall.IsCompressedNormalTangent(drawCall)) { var vectors = ToVector4Array(buffer); var(normals, tangents) = DecompressNormalTangents(vectors); primitive.WithVertexAccessor("NORMAL", normals); primitive.WithVertexAccessor("TANGENT", tangents); continue; } if (attribute.Name == "BLENDINDICES") { var byteBuffer = buffer.Select(f => (byte)f).ToArray(); var bufferView = mesh.LogicalParent.UseBufferView(byteBuffer); var accessor = mesh.LogicalParent.CreateAccessor(); accessor.SetVertexData(bufferView, 0, buffer.Length / 4, DimensionType.VEC4, EncodingType.UNSIGNED_BYTE); primitive.SetVertexAccessor(accessorName, accessor); continue; } if (attribute.Name == "TEXCOORD" && numComponents != 2) { // We are ignoring some data, but non-2-component UVs cause failures in gltf consumers continue; } switch (numComponents) { case 4: { var vectors = ToVector4Array(buffer); primitive.WithVertexAccessor(accessorName, vectors); break; } case 3: { var vectors = ToVector3Array(buffer); primitive.WithVertexAccessor(accessorName, vectors); break; } case 2: { var vectors = ToVector2Array(buffer); primitive.WithVertexAccessor(accessorName, vectors); break; } case 1: { primitive.WithVertexAccessor(accessorName, buffer); break; } default: throw new NotImplementedException($"Attribute \"{attribute.Name}\" has {numComponents} components"); } } // For some reason soruce models can have joints but no weights, check if that is the case var jointAccessor = primitive.GetVertexAccessor("JOINTS_0"); if (jointAccessor != null && primitive.GetVertexAccessor("WEIGHTS_0") == null) { // If this occurs, give default weights var defaultWeights = Enumerable.Repeat(Vector4.UnitX, jointAccessor.Count).ToList(); primitive.WithVertexAccessor("WEIGHTS_0", defaultWeights); } // Set index buffer var startIndex = (int)drawCall.GetIntegerProperty("m_nStartIndex"); var indexCount = (int)drawCall.GetIntegerProperty("m_nIndexCount"); var indices = ReadIndices(indexBuffer, startIndex, indexCount); primitive.WithIndicesAccessor(PrimitiveType.TRIANGLES, indices); // Add material var materialPath = drawCall.GetProperty <string>("m_material"); ProgressDialog.SetProgress($"Loading material: {materialPath}"); var materialResource = GuiContext.LoadFileByAnyMeansNecessary(materialPath + "_c"); if (materialResource == null) { continue; } var renderMaterial = (VMaterial)materialResource.DataBlock; var materialNameTrimmed = Path.GetFileNameWithoutExtension(materialPath); var bestMaterial = GenerateGLTFMaterialFromRenderMaterial(renderMaterial, model, materialNameTrimmed); primitive.WithMaterial(bestMaterial); } } return(mesh); }
private Mesh CreateGltfMesh(string meshName, VMesh vmesh, ModelRoot model) { ProgressDialog.SetProgress($"Creating mesh: {meshName}"); var data = vmesh.GetData(); var vbib = vmesh.VBIB; var mesh = model.CreateMesh(meshName); mesh.Name = meshName; foreach (var sceneObject in data.GetArray("m_sceneObjects")) { foreach (var drawCall in sceneObject.GetArray("m_drawCalls")) { var vertexBufferInfo = drawCall.GetArray("m_vertexBuffers")[0]; // In what situation can we have more than 1 vertex buffer per draw call? var vertexBufferIndex = (int)vertexBufferInfo.GetIntegerProperty("m_hBuffer"); var vertexBuffer = vbib.VertexBuffers[vertexBufferIndex]; var indexBufferInfo = drawCall.GetSubCollection("m_indexBuffer"); var indexBufferIndex = (int)indexBufferInfo.GetIntegerProperty("m_hBuffer"); var indexBuffer = vbib.IndexBuffers[indexBufferIndex]; // Create one primitive per draw call var primitive = mesh.CreatePrimitive(); // Avoid duplicate attribute names var uniqueAttributes = vertexBuffer.Attributes.GroupBy(a => a.Name).Select(g => g.First()); // Set vertex attributes foreach (var attribute in uniqueAttributes) { if (AccessorInfo.TryGetValue(attribute.Name, out var accessorInfo)) { var buffer = ReadAttributeBuffer(vbib, vertexBuffer, attribute); if (accessorInfo.NumComponents == 4) { var vectors = ToVector4Array(buffer); primitive.WithVertexAccessor(accessorInfo.GltfAccessorName, vectors); } else if (attribute.Name == "NORMAL" && DrawCall.IsCompressedNormalTangent(drawCall)) { var vectors = ToVector4Array(buffer); var(normals, tangents) = DecompressNormalTangents(vectors); primitive.WithVertexAccessor("NORMAL", normals); primitive.WithVertexAccessor("TANGENT", tangents); } else if (accessorInfo.NumComponents == 3) { var vectors = ToVector3Array(buffer, true, accessorInfo.Resize); primitive.WithVertexAccessor(accessorInfo.GltfAccessorName, vectors); } else if (accessorInfo.NumComponents == 2) { var vectors = ToVector2Array(buffer); primitive.WithVertexAccessor(accessorInfo.GltfAccessorName, vectors); } } } // Set index buffer var indices = ReadIndices(indexBuffer); // For triangle primitives, the front face has to be in counter-clockwise (CCW) winding order. for (var i = 0; i < indices.Length; i += 3) { var b = indices[i + 2]; indices[i + 2] = indices[i + 1]; indices[i + 1] = b; } primitive.WithIndicesAccessor(PrimitiveType.TRIANGLES, indices); // Add material var materialPath = drawCall.GetProperty <string>("m_material"); ProgressDialog.SetProgress($"Loading material: {materialPath}"); var materialResource = GuiContext.LoadFileByAnyMeansNecessary(materialPath + "_c"); if (materialResource == null) { continue; } var renderMaterial = (VMaterial)materialResource.DataBlock; var materialNameTrimmed = Path.GetFileNameWithoutExtension(materialPath); var bestMaterial = GenerateGLTFMaterialFromRenderMaterial(renderMaterial, model, materialNameTrimmed); primitive.WithMaterial(bestMaterial); } } return(mesh); }
public void UpdateVis0(int objectIndex, int drawCallIndex, bool value) { BRESEntryNode n; if ((n = TargetAnimation as BRESEntryNode) == null || _animFrame == 0 || TargetModel == null) { return; } Start: if (_vis0 != null) { if (objectIndex < 0 || objectIndex >= TargetModel.Objects.Length) { return; } MDL0ObjectNode obj = (MDL0ObjectNode)TargetModel.Objects[objectIndex]; if (drawCallIndex < 0 || drawCallIndex >= obj._drawCalls.Count) { return; } DrawCall c = obj._drawCalls[drawCallIndex]; MDL0BoneNode bone = c._visBoneNode; if (bone == null) { return; } VIS0EntryNode node = null; if ((node = (VIS0EntryNode)_vis0.FindChild(bone.Name, true)) == null && bone.BoneIndex != 0 && bone.Name != "EyeYellowM") { node = _vis0.CreateEntry(); node.Name = bone.Name; node.MakeConstant(true); } bool ANIMval = value; bool nowAnimated = false, alreadyConstant = false; Top: if (node != null) { if (node._entryCount != 0) //Node is animated { bool VIS0val = node.GetEntry((int)_animFrame - 1); if (VIS0val != ANIMval) { node.SetEntry((int)_animFrame - 1, ANIMval); } } else //Node is constant { alreadyConstant = true; bool VIS0val = node._flags.HasFlag(VIS0Flags.Enabled); if (VIS0val != ANIMval) { node.MakeAnimated(); nowAnimated = true; goto Top; } } } //Check if the entry can be made constant. //No point if the entry has just been made animated or if the node is already constant. if (node != null && !alreadyConstant && !nowAnimated) { bool constant = true; for (int i = 0; i < node._entryCount; i++) { if (i == 0) { continue; } if (node.GetEntry(i - 1) != node.GetEntry(i)) { constant = false; break; } } if (constant) { node.MakeConstant(node.GetEntry(0)); } } var t = (VIS0EntryNode)KeyframePanel.visEditor.TargetNode; if (node != null && t != null && t.Name == node.Name) { VIS0Editor.UpdateEntry(); } } else { CreateVIS0(); if (_vis0 != null) { goto Start; } } }