public void RemoveModel(Model model) { models.Remove(model); Armature armature = model.Armature; int i = 0; while (i < activeBones.Count) { Armature.Bone bone = activeBones[i]; if (bone.armature == armature) { activeBones.RemoveAt(i); if (model.IsVisible) { int j = visibleBones.IndexOf(bone); visibleBones.RemoveAt(j); visibleBonesProjections.RemoveAt(j); } } else { i++; } } armature.ArmatureEvent -= HandleArmatureEvent; selectedBoneIndex = -1; }
private void RecalculateBonePositions() { Viewport viewport = graphicsDevice.Viewport; Matrix projectionMatrix = camera.ProjectionMatrix; Matrix viewMatrix = camera.ViewMatrix; float cameraNear = camera.NearPlane; renderedBonesCount = 0; for (int i = 0; i < visibleBones.Count; i++) { Armature.Bone bone = visibleBones[i]; Matrix worldMatrix = bone.armature.WorldMatrix; Vector3 absPos = bone.absTransform.Translation; Vector3 projected = viewport.Project(absPos, projectionMatrix, viewMatrix, worldMatrix); projected.Y = viewport.Height - 1 - projected.Y; if (projected.Z > 0 && projected.Z < 1) { projected.Z = 0; renderedBonesCount++; } else { projected.Z = -1; } visibleBonesProjections[i] = projected; } }
private void LoadPoseNew(List <string> lines) { Armature armature = selectedItem.Model.Armature; Dictionary <string, BoneTransform> boneTransforms = new Dictionary <string, BoneTransform>(); foreach (string line in lines) { string[] tokens1 = line.Split(':'); if (tokens1.Length == 2) { string boneName = tokens1[0].Trim(); Armature.Bone bone = armature.GetBone(boneName); if (bone != null) { string[] tokens2 = tokens1[1].Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (tokens2.Length == 3 || tokens2.Length == 6) { BoneTransform boneTransform = new BoneTransform(); boneTransform.rotX = float.Parse(tokens2[0]); boneTransform.rotY = float.Parse(tokens2[1]); boneTransform.rotZ = float.Parse(tokens2[2]); if (tokens2.Length == 6) { boneTransform.moveX = float.Parse(tokens2[3]); boneTransform.moveY = float.Parse(tokens2[4]); boneTransform.moveZ = float.Parse(tokens2[5]); } else { boneTransform.moveX = 0; boneTransform.moveY = 0; boneTransform.moveZ = 0; } boneTransforms[boneName] = boneTransform; } } } } ICollection <string> boneNames = boneTransforms.Keys; PoseFilterDialog dialog = new PoseFilterDialog(game, "Load pose", "Select bones to load:", boneNames, true); if (dialog.ShowDialog(this) != DialogResult.OK) { return; } DataSet dataSet = dataSetDict[selectedItem]; foreach (string boneName in boneNames) { if (dialog.IsBoneSelected(boneName)) { Armature.Bone bone = armature.GetBone(boneName); BoneTransform boneTransform = boneTransforms[boneName]; dataSet.boneTransforms[bone.id] = boneTransform; ApplyTransformToBone(bone, boneTransform); } } }
private Armature LoadArmature(BinaryReader file, Model model) { int boneCount = file.ReadInt32(); if (boneCount == 0) { return(null); } Armature armature = new Armature(model); Armature.Bone[] bones = new Armature.Bone[boneCount]; int[] parentIDs = new int[boneCount]; for (int boneID = 0; boneID < boneCount; boneID++) { Armature.Bone bone = new Armature.Bone(); bone.armature = armature; bone.id = boneID; bone.name = file.ReadString(); parentIDs[boneID] = file.ReadInt16(); float absPosX = file.ReadSingle(); float absPosY = file.ReadSingle(); float absPosZ = file.ReadSingle(); bone.absPosition = new Vector3(absPosX, absPosY, absPosZ); bones[boneID] = bone; } for (int boneID = 0; boneID < boneCount; boneID++) { Armature.Bone bone = bones[boneID]; int parentID = parentIDs[boneID]; if (parentID >= 0) { Armature.Bone parent = bones[parentID]; bone.parent = parent; parent.children.Add(bone); } } armature.Bones = bones; return(armature); }
public static Vector3 GetTransformedBone(Armature.Bone bone, Matrix worldMatrix) { Matrix m = bone.absTransform * worldMatrix; return(Vector3.Transform(Vector3.Zero, m)); }
private void MirrorPose() { if (selectedItem == null) { return; } Armature armature = selectedItem.Model.Armature; List <string> labels = new List <string>(); foreach (Armature.Bone bone in armature.Bones) { int origSide; string mirroredName = GetMirroredBoneName(bone.name, out origSide); if (mirroredName != null && origSide < 0 && armature.GetBone(mirroredName) != null) { labels.Add("L: " + bone.name); } } foreach (Armature.Bone bone in armature.Bones) { int origSide; string mirroredName = GetMirroredBoneName(bone.name, out origSide); if (mirroredName != null && origSide > 0 && armature.GetBone(mirroredName) != null) { labels.Add("R: " + bone.name); } } PoseFilterDialog dialog = new PoseFilterDialog(game, "Mirror (copy) pose left/right", "Select bones to mirror pose from:", labels, false); if (dialog.ShowDialog(this) != DialogResult.OK) { return; } DataSet dataSet = dataSetDict[selectedItem]; foreach (string label in labels) { if (!dialog.IsBoneSelected(label)) { continue; } string boneNameFrom = label.Substring(3); Armature.Bone boneFrom = armature.GetBone(boneNameFrom); BoneTransform boneTransformFrom = dataSet.boneTransforms[boneFrom.id]; string boneNameTo = GetMirroredBoneName(boneNameFrom); Armature.Bone boneTo = armature.GetBone(boneNameTo); BoneTransform boneTransformTo = dataSet.boneTransforms[boneTo.id]; boneTransformTo.moveX = -boneTransformFrom.moveX; boneTransformTo.moveY = +boneTransformFrom.moveY; boneTransformTo.moveZ = +boneTransformFrom.moveZ; boneTransformTo.rotX = +boneTransformFrom.rotX; boneTransformTo.rotY = -boneTransformFrom.rotY; boneTransformTo.rotZ = -boneTransformFrom.rotZ; ApplyTransformToBone(boneTo, boneTransformTo); } }
private void FlipPose() { if (selectedItem == null) { return; } Armature armature = selectedItem.Model.Armature; List <string> labels = new List <string>(); Dictionary <string, string> labelsToBoneNames = new Dictionary <string, string>(); foreach (Armature.Bone bone in armature.Bones) { int origSide; string flippedName = GetFlippedBoneName(bone.name, out origSide); if (flippedName != null && origSide < 0 && armature.GetBone(flippedName) != null) { string combinedName = GetCombinedBoneName(bone.name); labels.Add(combinedName); labelsToBoneNames[combinedName] = bone.name; } } PoseFilterDialog dialog = new PoseFilterDialog(game, "Flip (swap) pose left/right", "Select bone pairs whose pose to flip:", labels, false); if (dialog.ShowDialog(this) != DialogResult.OK) { return; } DataSet dataSet = dataSetDict[selectedItem]; foreach (string label in labels) { if (!dialog.IsBoneSelected(label)) { continue; } string boneName1 = labelsToBoneNames[label]; Armature.Bone bone1 = armature.GetBone(boneName1); BoneTransform boneTransform1 = dataSet.boneTransforms[bone1.id]; string boneName2 = GetFlippedBoneName(boneName1); Armature.Bone bone2 = armature.GetBone(boneName2); BoneTransform boneTransform2 = dataSet.boneTransforms[bone2.id]; float moveX1 = boneTransform1.moveX; float moveY1 = boneTransform1.moveY; float moveZ1 = boneTransform1.moveZ; float rotX1 = boneTransform1.rotX; float rotY1 = boneTransform1.rotY; float rotZ1 = boneTransform1.rotZ; float moveX2 = boneTransform2.moveX; float moveY2 = boneTransform2.moveY; float moveZ2 = boneTransform2.moveZ; float rotX2 = boneTransform2.rotX; float rotY2 = boneTransform2.rotY; float rotZ2 = boneTransform2.rotZ; boneTransform2.moveX = -moveX1; boneTransform2.moveY = +moveY1; boneTransform2.moveZ = +moveZ1; boneTransform2.rotX = +rotX1; boneTransform2.rotY = -rotY1; boneTransform2.rotZ = -rotZ1; boneTransform1.moveX = -moveX2; boneTransform1.moveY = +moveY2; boneTransform1.moveZ = +moveZ2; boneTransform1.rotX = +rotX2; boneTransform1.rotY = -rotY2; boneTransform1.rotZ = -rotZ2; ApplyTransformToBone(bone1, boneTransform1); ApplyTransformToBone(bone2, boneTransform2); } }
private Model LoadModel(string filenameObj, Dictionary <string, Material> materials) { StreamReader file = null; try { file = new StreamReader(filenameObj); } catch (Exception) { MessageBox.Show("Could not open OBJ file.", "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error); return(null); } try { Model model = new Model(game); List <Vector3> vertexCoords = new List <Vector3>(); List <Vector3> vertexNormals = new List <Vector3>(); List <Vector2> vertexTexCoords = new List <Vector2>(); List <Vector4> vertexColors = new List <Vector4>(); List <Vertex> vertexList = new List <Vertex>(); Dictionary <Vertex, int> vertexDict = new Dictionary <Vertex, int>(); List <Face> faces = new List <Face>(); int meshID = 0; Material material = null; lineCounter = 0; while (true) { lineCounter++; string line = file.ReadLine(); if (line != null) { line = line.TrimStart(); } if (line == null || line.StartsWith("usemtl ")) { if (faces.Count > 0) { if (material == null) { throw new Exception(string.Format("No material assigned (line {0}).", lineCounter)); } if (material.textureDiffuse == null) { throw new Exception(string.Format("No diffuse texture defined for material \"{0}\".", material.name)); } meshID++; string meshName = string.Format("Mesh{0}", meshID); MeshDesc meshDesc = BuildMeshDesc(meshName, material, vertexList, faces); model.AddMeshDesc(meshDesc); vertexList.Clear(); vertexDict.Clear(); faces.Clear(); } if (line == null) { break; } string materialName = line.Substring(7).Trim(); material = materials[materialName]; } if (line.StartsWith("v ")) { Vector3 coord = ParseVertexCoord(line.Substring(2)); vertexCoords.Add(coord); continue; } if (line.StartsWith("vn ")) { Vector3 normal = ParseVertexNormal(line.Substring(3)); normal.Normalize(); vertexNormals.Add(normal); continue; } if (line.StartsWith("vt ")) { Vector2 texCoord = ParseVertexTexCoord(line.Substring(3)); vertexTexCoords.Add(texCoord); continue; } if (line.StartsWith("vc ")) { Vector4 color = ParseVertexColor(line.Substring(3)); vertexColors.Add(color); continue; } if (line.StartsWith("f ")) { Face face = ParseFace(line.Substring(2)); try { for (int i = 0; i < face.vertexIndices.Length; i++) { Vertex vertex = new Vertex(); int index; index = face.coordIndices[i]; vertex.coord = index > 0 ? vertexCoords[index - 1] : vertexCoords[vertexCoords.Count + index]; index = face.normalIndices[i]; vertex.normal = index > 0 ? vertexNormals[index - 1] : vertexNormals[vertexNormals.Count + index]; index = face.texCoordIndices[i]; vertex.texCoord = index > 0 ? vertexTexCoords[index - 1] : vertexTexCoords[vertexTexCoords.Count + index]; if (face.colorIndices != null) { index = face.colorIndices[i]; vertex.color = index > 0 ? vertexColors[index - 1] : vertexColors[vertexColors.Count + index]; } else { vertex.color = new Vector4(1, 1, 1, 1); } if (!vertexDict.TryGetValue(vertex, out index)) { index = vertexList.Count; vertexList.Add(vertex); vertexDict[vertex] = index; } face.vertexIndices[i] = index; } } catch (Exception) { throw new Exception(string.Format("Invalid face: invalid vertex index (line {0}).", lineCounter)); } if (face.vertexIndices.Length == 3) { FlipTriangularFace(face); faces.Add(face); } else { Face[] triFaces = Triangulate(face); FlipTriangularFace(triFaces[0]); FlipTriangularFace(triFaces[1]); faces.Add(triFaces[0]); faces.Add(triFaces[1]); } continue; } } Armature armature = new Armature(model); Armature.Bone bone = new Armature.Bone(); bone.armature = armature; bone.id = 0; bone.name = "root"; bone.absPosition = Vector3.Zero; bone.parent = null; armature.Bones = new Armature.Bone[] { bone }; model.Armature = armature; file.Close(); return(model); } catch (Exception ex) { MessageBox.Show("Could not load OBJ file.\n" + ex.Message, "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error); return(null); } }
public void Render() { if (selectedBoneIndex < 0 || renderedBonesCount == 0) { return; } Color DefaultBoneColor = new Color(Color.White, 0.35f); Armature.Bone selectedBone = null; Vector3 selectedBoneProj = Vector3.Zero; VertexPositionColor[] points = new VertexPositionColor[renderedBonesCount]; int j = 0; for (int i = 0; i < visibleBones.Count; i++) { Vector3 boneProj = visibleBonesProjections[i]; if (boneProj.Z < 0) { continue; } Color color; if (i == selectedBoneIndex) { color = Color.Red; selectedBone = visibleBones[i]; selectedBoneProj = boneProj; } else { color = DefaultBoneColor; } points[j] = new VertexPositionColor(boneProj, color); j++; } graphicsDevice.RenderState.PointSize = 5; graphicsDevice.VertexDeclaration = vertexDeclaration; graphicsDevice.RenderState.AlphaBlendEnable = true; graphicsDevice.RenderState.SourceBlend = Blend.SourceAlpha; graphicsDevice.RenderState.DestinationBlend = Blend.InverseSourceAlpha; basicEffect.VertexColorEnabled = true; basicEffect.World = Matrix.Identity; basicEffect.View = viewMatrix; basicEffect.Projection = projectionMatrix; basicEffect.Begin(); foreach (EffectPass pass in basicEffect.CurrentTechnique.Passes) { pass.Begin(); graphicsDevice.DrawUserPrimitives <VertexPositionColor>(PrimitiveType.PointList, points, 0, points.Length); pass.End(); } basicEffect.End(); graphicsDevice.RenderState.AlphaBlendEnable = false; if (game.DisplayBoneNames && selectedBone != null) { spriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Deferred, SaveStateMode.SaveState); int x = (int)Math.Round(selectedBoneProj.X); int y = (int)Math.Round(screenHeight - 1 - selectedBoneProj.Y - font.LineSpacing - 3); string label = selectedBone.name; spriteBatch.DrawString(font, label, new Vector2(x + 1, y + 1), Color.Black); spriteBatch.DrawString(font, label, new Vector2(x, y), Color.Yellow); spriteBatch.End(); } }
private void ProcessKeyboard(float deltaMilliseconds) { KeyboardState keyboardState = Keyboard.GetState(); KeyboardEventHandler.ProcessKeyboardState(keyboardState); if (KeyboardEventHandler.HasKeyBeenPressed(Keys.NumPad0)) { Armature.Bone selectedBone = controlGUI.SelectedBone; if (selectedBone != null) { controlGUI.HandleBoneRotationXChanged(selectedBone, 0); controlGUI.HandleBoneRotationYChanged(selectedBone, 0); controlGUI.HandleBoneRotationZChanged(selectedBone, 0); } } bool ctrlKeyPressed = keyboardState.IsKeyDown(Keys.LeftControl) || keyboardState.IsKeyDown(Keys.RightControl); bool shiftKeyPressed = keyboardState.IsKeyDown(Keys.LeftShift) || keyboardState.IsKeyDown(Keys.RightShift); bool altKeyPressed = keyboardState.IsKeyDown(Keys.LeftAlt) || keyboardState.IsKeyDown(Keys.RightAlt); if (keyboardState.IsKeyDown(Keys.Up) || keyboardState.IsKeyDown(Keys.Down) || keyboardState.IsKeyDown(Keys.Left) || keyboardState.IsKeyDown(Keys.Right)) { Item selectedItem = controlGUI.SelectedItem; if (selectedItem != null) { Armature armature = selectedItem.Model.Armature; float speed = shiftKeyPressed ? 3e-3f : 1e-3f; if (!altKeyPressed) { Vector3 dir = Vector3.Zero; if (keyboardState.IsKeyDown(Keys.Up)) { dir += DetermineMovementVector(Keys.Up); } if (keyboardState.IsKeyDown(Keys.Down)) { dir += DetermineMovementVector(Keys.Down); } if (keyboardState.IsKeyDown(Keys.Left)) { dir += DetermineMovementVector(Keys.Left); } if (keyboardState.IsKeyDown(Keys.Right)) { dir += DetermineMovementVector(Keys.Right); } armature.WorldTranslation += dir * speed; controlGUI.HandlePositionChanged(armature.WorldTranslation); } else { float dir = 0; if (keyboardState.IsKeyDown(Keys.Up)) { dir += 1; } if (keyboardState.IsKeyDown(Keys.Down)) { dir -= 1; } float height = armature.WorldTranslation.Y; height += dir * speed; controlGUI.HandleHeightChanged(height); } } } if (KeyboardEventHandler.HasKeyBeenPressed(Keys.F2)) { cameraSavedState = camera.CameraState; hud.Message = "camera state saved"; } if (KeyboardEventHandler.HasKeyBeenPressed(Keys.F3)) { if (cameraSavedState != null) { camera.CameraState = cameraSavedState; hud.Message = "camera state loaded"; } } if (KeyboardEventHandler.HasKeyBeenPressed(Keys.F5)) { controlGUI.QuickSaveImage(); } if (KeyboardEventHandler.HasKeyBeenPressed(Keys.F8)) { controlGUI.ReloadTextures(); } if (KeyboardEventHandler.HasKeyBeenPressed(Keys.F12)) { if (controlGUI.IsDisposed) { controlGUI = new ControlGUI(this); } controlGUI.Show(); } if (!controlGUI.IsCameraLocked) { if (KeyboardEventHandler.HasKeyBeenPressed(Keys.D1)) { controlGUI.SetCameraPivot(0); } if (KeyboardEventHandler.HasKeyBeenPressed(Keys.D2)) { controlGUI.SetCameraPivot(1); } if (KeyboardEventHandler.HasKeyBeenPressed(Keys.D3)) { controlGUI.SetCameraPivot(2); } if (KeyboardEventHandler.HasKeyBeenPressed(Keys.D4)) { controlGUI.SetCameraPivot(3); } if (KeyboardEventHandler.HasKeyBeenPressed(Keys.D5)) { controlGUI.SetCameraPivot(4); } if (KeyboardEventHandler.HasKeyBeenPressed(Keys.D6)) { controlGUI.SetCameraPivot(5); } if (KeyboardEventHandler.HasKeyBeenPressed(Keys.D7)) { controlGUI.SetCameraPivot(6); } if (KeyboardEventHandler.HasKeyBeenPressed(Keys.D8)) { controlGUI.SetCameraPivot(7); } if (KeyboardEventHandler.HasKeyBeenPressed(Keys.D9)) { controlGUI.SetCameraPivot(8); } if (KeyboardEventHandler.HasKeyBeenPressed(Keys.D0)) { controlGUI.SetCameraPivot(9); } } if (ctrlKeyPressed && KeyboardEventHandler.HasKeyBeenPressed(Keys.Z) || KeyboardEventHandler.HasKeyBeenPressed(Keys.NumPad5)) { controlGUI.Undo(); } }
private void ProcessMouse(float deltaMilliseconds) { MouseState mouseState = Mouse.GetState(); KeyboardState keyboardState = Keyboard.GetState(); bool axisKeyPressed = keyboardState.IsKeyDown(Keys.NumPad1) || keyboardState.IsKeyDown(Keys.NumPad2) || keyboardState.IsKeyDown(Keys.NumPad3) || keyboardState.IsKeyDown(Keys.Q) || keyboardState.IsKeyDown(Keys.W) || keyboardState.IsKeyDown(Keys.E); bool ctrlKeyPressed = keyboardState.IsKeyDown(Keys.LeftControl) || keyboardState.IsKeyDown(Keys.RightControl); bool shiftKeyPressed = keyboardState.IsKeyDown(Keys.LeftShift) || keyboardState.IsKeyDown(Keys.RightShift); bool altKeyPressed = keyboardState.IsKeyDown(Keys.LeftAlt) || keyboardState.IsKeyDown(Keys.RightAlt); if (axisKeyPressed || ctrlKeyPressed || shiftKeyPressed || altKeyPressed) { disableBoneSelection = true; } else { if (!mouseLeftDragging) { disableBoneSelection = false; } } if (mouseState.LeftButton == ButtonState.Pressed) { if (displayBones && !disableBoneSelection) { Armature.Bone selectedBone = boneSelector.SelectedBone; if (selectedBone != null) { controlGUI.HandleBoneSelectedIn3D(selectedBone); } } if (!mouseLeftDragging) { mouseLeftDragging = true; mouseAnchor = new Point(mouseState.X, mouseState.Y); } } else { mouseLeftDragging = false; disableBoneSelection = false; if (boneTransformActive) { boneTransformActive = false; controlGUI.UndoSaveInterrupt(); } } if (mouseState.RightButton == ButtonState.Pressed) { if (!mouseRightDragging) { mouseRightDragging = true; mouseAnchor = new Point(mouseState.X, mouseState.Y); } } else { mouseRightDragging = false; } if (mouseLeftDragging && mouseRightDragging) { int dx = mouseState.X - mouseAnchor.X; int dy = mouseState.Y - mouseAnchor.Y; mouseAnchor = new Point(mouseState.X, mouseState.Y); if (!controlGUI.IsCameraLocked) { camera.Target -= (camera.Left * dx - camera.Up * dy) * 0.005f; } return; } if (mouseLeftDragging) { int dx = mouseState.X - mouseAnchor.X; int dy = mouseState.Y - mouseAnchor.Y; mouseAnchor = new Point(mouseState.X, mouseState.Y); if (axisKeyPressed) { Armature.Bone selectedBone = controlGUI.SelectedBone; if (selectedBone != null) { boneTransformActive = true; if (keyboardState.IsKeyDown(Keys.NumPad1) || keyboardState.IsKeyDown(Keys.Q)) { float angle = controlGUI.GetBoneRotationX(selectedBone); controlGUI.HandleBoneRotationXChanged(selectedBone, angle + (dx + dy) * 0.5f); } if (keyboardState.IsKeyDown(Keys.NumPad2) || keyboardState.IsKeyDown(Keys.W)) { float angle = controlGUI.GetBoneRotationY(selectedBone); controlGUI.HandleBoneRotationYChanged(selectedBone, angle + (dx + dy) * 0.5f); } if (keyboardState.IsKeyDown(Keys.NumPad3) || keyboardState.IsKeyDown(Keys.E)) { float angle = controlGUI.GetBoneRotationZ(selectedBone); controlGUI.HandleBoneRotationZChanged(selectedBone, angle + (dx + dy) * 0.5f); } } return; } if (ctrlKeyPressed) { Item selectedItem = controlGUI.SelectedItem; if (selectedItem != null) { Vector3 point; if (ProjectMouseToGround(mouseState.X, mouseState.Y, out point)) { Armature armature = selectedItem.Model.Armature; float height = armature.WorldTranslation.Y; armature.WorldTranslation = new Vector3(point.X, height, point.Z); controlGUI.HandlePositionChanged(armature.WorldTranslation); } } return; } if (!controlGUI.IsCameraLocked) { if (shiftKeyPressed) { camera.Target -= (camera.Left * dx - camera.Up * dy) * 0.005f; return; } float rotationHorizontal = camera.RotationHorizontal - dx * 0.01f; float rotationVertical = camera.RotationVertical + dy * 0.01f; camera.SetRotation(rotationHorizontal, rotationVertical); } } if (mouseRightDragging) { if (!controlGUI.IsCameraLocked) { int dy = mouseState.Y - mouseAnchor.Y; mouseAnchor = new Point(mouseState.X, mouseState.Y); if (!shiftKeyPressed) { camera.Distance += dy * 0.01f; } else { camera.Target -= camera.Forward * dy * 0.005f; } } } if (!mouseLeftDragging && !mouseRightDragging) { boneSelector.HandleMouseMoved(mouseState.X, mouseState.Y); } if (mouseWheel != mouseState.ScrollWheelValue) { if (!controlGUI.IsCameraLocked) { int delta = mouseWheel - mouseState.ScrollWheelValue; camera.Distance += delta * 0.002f; } mouseWheel = mouseState.ScrollWheelValue; } }