Hi all!
My doubt may be idiot, but I spent many hours trying to do this thing works, but I didn't.
In my WinForm C# application, there is a user control which I load an aircraft. I would like to add some movement to this aircraft. I also would like to change the perspective which I can view the object doing its movements.
In order to get this behaviour, I code something as you can see bellow.
The code of the main control class.
| /// <summary> |
| /// Loads a new 3D model file into the ModelViewerControl. |
| /// </summary> |
| void LoadModel(String fileName) { |
| Cursor = Cursors.WaitCursor; |
| |
| // Unload any existing model. |
| modelViewerControl.Model = null; |
| contentManager.Unload(); |
| |
| // Tell the ContentBuilder what to build. |
| contentBuilder.Clear(); |
| contentBuilder.Add(fileName, "Model", null, "ModelProcessor"); |
| |
| // Build this new model data. |
| string buildError = contentBuilder.Build(); |
| |
| if (string.IsNullOrEmpty(buildError)) { |
| // If the build succeeded, use the ContentManager to |
| // load the temporary .xnb file that we just created. |
| modelViewerControl.Model = contentManager.Load<Model>("Model"); |
| } |
| else { |
| // If the build failed, display an error message. |
| MessageBox.Show(buildError, "Error"); |
| } |
| |
| Cursor = Cursors.Arrow; |
| } |
Model view control class
|
/// <summary>
|
| /// Gets or sets the current model. |
| /// </summary> |
| public Model Model { |
| get { return model; } |
| set { |
| model = value; |
| if (model != null){ |
| MeasureModel(); |
| } |
| } |
| } |
| |
| /// <summary> |
| /// Whenever a new model is selected, we examine it to see how big |
| /// it is and where it is centered. This lets us automatically zoom |
| /// the display, so we can correctly handle models of any scale. |
| /// </summary> |
| void MeasureModel() { |
| // Look up the absolute bone transforms for this model. |
| boneTransforms = new Matrix[model.Bones.Count]; |
| |
| model.CopyAbsoluteBoneTransformsTo(boneTransforms); |
| |
| // Compute an (approximate) model center position by |
| // averaging the center of each mesh bounding sphere. |
| modelCenter = Vector3.Zero; |
| |
| foreach (ModelMesh mesh in model.Meshes) { |
| BoundingSphere meshBounds = mesh.BoundingSphere; |
| Matrix transform = boneTransforms[mesh.ParentBone.Index]; |
| Vector3 meshCenter = Vector3.Transform(meshBounds.Center, transform); |
| |
| modelCenter += meshCenter; |
| } |
| |
| modelCenter /= model.Meshes.Count; |
| |
| // Now we know the center point, we can compute the model radius |
| // by examining the radius of each mesh bounding sphere. |
| modelRadius = 0; |
| |
| foreach (ModelMesh mesh in model.Meshes) { |
| BoundingSphere meshBounds = mesh.BoundingSphere; |
| Matrix transform = boneTransforms[mesh.ParentBone.Index]; |
| Vector3 meshCenter = Vector3.Transform(meshBounds.Center, transform); |
| |
| float transformScale = transform.Forward.Length(); |
| |
| float meshRadius = (meshCenter - modelCenter).Length() + |
| (meshBounds.Radius * transformScale); |
| |
| modelRadius = Math.Max(modelRadius, meshRadius); |
| } |
| } |
The functions above works successfully. Now, I try to start the objects movements.
There is a function, in my main control class, which receives all parameters which are necessary in order to start the movements.
| public override void ControlEx_UpdateData(ParameterVo param, double paramvalue, double timestamp, TimeSpan timespan) { |
| |
| if ( param.getParameterId() == this.roll.getParameterId() ) { |
| this.behaviour.X = MathHelper.ToRadians((float)paramvalue); |
| this.checkX = true; |
| } |
| else if ( param.getParameterId() == this.pitch.getParameterId() ) { |
| this.behaviour.Y = MathHelper.ToRadians((float)paramvalue); |
| this.checkY = true; |
| } |
| else if ( param.getParameterId() == this.yaw.getParameterId() ) { |
| this.behaviour.Z = MathHelper.ToRadians((float)paramvalue); |
| this.checkZ = true; |
| } |
| |
| if (this.checkX && this.checkY && this.checkZ) { |
| this.checkX = false; |
| this.checkY = false; |
| this.checkZ = false; |
| this.modelViewerControl.updateYawPitchRoll(this.behaviour); |
| } |
| |
| return; |
| } |
In modelViewerControl class, the job is done like this:
I would like to add that I think here is the problem, but I donno how to fix it.
| public void updateYawPitchRoll (Vector3 angles) { |
| this.eulerAngles.X = angles.X; |
| this.eulerAngles.Y = angles.Y; |
| this.eulerAngles.Z = angles.Z; |
| } |
| |
| /// <summary> |
| /// Draws the control. |
| /// </summary> |
| protected override void Draw() { |
| |
| Color backColor = new Color(210, 242, 255); |
| GraphicsDevice.Clear(backColor); |
| |
| if (model != null) { |
| if (this.eyePosition == Vector3.Zero) { |
| |
| this.eyePosition = new Vector3(); |
| this.eyePosition = modelCenter; |
| |
| this.eyePosition.Z += modelRadius * -1.5f; |
| this.eyePosition.Y += modelRadius * 1; |
| this.eyePosition.X += modelRadius * 1.5f; |
| } |
| this.UpdateDraw(); |
| } |
| } |
| |
| private void UpdateDraw() { |
| |
| float aspectRatio = GraphicsDevice.Viewport.AspectRatio; |
| |
| float nearClip = modelRadius / 100; |
| float farClip = modelRadius * 100; |
| |
| Matrix world = Matrix.CreateFromYawPitchRoll(this.eulerAngles.Z, this.eulerAngles.Y, this.eulerAngles.X); |
| Matrix view = Matrix.CreateLookAt(this.eyePosition, modelCenter, this.cameraRotation); |
| Matrix projection = Matrix.CreatePerspectiveFieldOfView(1, aspectRatio, |
| nearClip, farClip); |
| |
| // Draw the model. |
| foreach (ModelMesh mesh in model.Meshes) { |
| foreach (BasicEffect effect in mesh.Effects) { |
| effect.World = boneTransforms[mesh.ParentBone.Index] * world; |
| effect.View = view; |
| effect.Projection = projection; |
| |
| effect.EnableDefaultLighting(); |
| effect.PreferPerPixelLighting = true; |
| effect.SpecularPower = 16; |
| } |
| |
| mesh.Draw(); |
| } |
| } |
I would like to thank you very much for your help!
Gustavo