Sign in to follow this  

[MDX] Manually created mesh - I found the problem but I can't explain

This topic is 4378 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, I am doing my first Direct3D program using VB.NET. This is for a solitaire game. The game contains 54 little T shaped tokens which must fit in a 6x6x6 cube. I made a mesh for my token but I can't understand why the colors are all funny. I think my normals are wrong. I use Mesh.ComputeNormals()... is there something I miss ? I join the whole source. Should be easy enough to compile and run.
Imports System
Imports System.Drawing
Imports System.Windows.Forms
Imports System.Diagnostics
Imports Microsoft.DirectX
Imports Microsoft.DirectX.Direct3D


Public Class Form2
   Inherits System.Windows.Forms.Form

   Private device As Device

   Private mesh As Mesh

   Private numSubSets As Integer

   ' Has the device been lost and not reset? 
   Private deviceLost As Boolean
   Dim k As Integer
   ' We'll need these to Reset successfully, so hold them here 
   Private pres As PresentParameters = New PresentParameters

   Public Shared Sub Main()
      Dim app As Form2 = New Form2
      app.Text = "Creating a Mesh"
      app.InitializeComponent()
      app.InitializeGraphics()
      app.Show()

      While app.Created
         app.Render()
         Application.DoEvents()

      End While
   End Sub

   Protected Function InitializeGraphics() As Boolean
      ' Set up our presentation parameters as usual 
      pres.Windowed = True
      pres.SwapEffect = SwapEffect.Discard
      pres.AutoDepthStencilFormat = DepthFormat.D16
      pres.EnableAutoDepthStencil = True
      device = New Device(0, DeviceType.Hardware, Me.Panel1, CreateFlags.SoftwareVertexProcessing, pres)
      ' Hook the DeviceReset event so OnDeviceReset will get called every 
      ' time we call device.Reset() 
      AddHandler device.DeviceReset, AddressOf Me.OnDeviceReset
      ' Similarly, OnDeviceLost will get called every time we call 
      ' device.Reset(). The difference is that DeviceLost gets called 
      ' earlier, giving us a chance to do the cleanup that needs to 
      ' occur before we can call Reset() successfully 
      AddHandler device.DeviceLost, AddressOf Me.OnDeviceLost
      ' Do the initial setup of our graphics objects 
      SetupDevice()
      Return True
   End Function

   Protected Sub OnDeviceReset(ByVal sender As Object, ByVal e As EventArgs)
      ' We use the same setup code to reset as we do for initial creation 
      SetupDevice()
   End Sub

   Protected Sub OnDeviceLost(ByVal sender As Object, ByVal e As EventArgs)

   End Sub

   Protected Sub SetupDevice()
      ' SetupLights()
      device.RenderState.Lighting = True
      device.RenderState.ZBufferEnable = True
      ' And create the graphical objects 
      CreateObjects(device)
   End Sub

   Protected Sub SetupLights()
      'device.RenderState.Ambient = Color.White

      'Dim dxLight As New Direct3D.Light
      'dxLight.Diffuse = Color.Yellow
      'dxLight.Type = Microsoft.DirectX.Direct3D.LightType.Point
      'dxLight.Position = New Vector3(0, 0, 1)
      'dxLight.Range = 200.0F

      Dim mtrl As Direct3D.Material = New Direct3D.Material
      mtrl.Diffuse = Color.Red
      mtrl.Ambient = Color.Red
      device.Material = mtrl
      'Set up a white, directional light, with an oscillating direction.
      'Note that many lights may be active at a time (but each one slows down

      device.Lights(0).Type = LightType.Directional
      device.Lights(0).Diffuse = System.Drawing.Color.White
      device.Lights(0).Direction = New Vector3( _
         10.0!, _
         -10.0!, _
         10.0!)
      device.Lights(0).Enabled = True
      'turn it on
      'Finally, turn on some ambient light.
      'Ambient light is light that scatters and lights all objects evenly
      device.RenderState.Ambient = Color.Gray


   End Sub

   Protected Sub SetupMaterials(ByVal color As Color)
      '    Dim mat As Material = New Material
      ' Since we haven't set up any normals for the object, 
      ' we're stuck with ambient lighting
      '      mat.Ambient = color
      '      device.Material = mat
   End Sub

   Protected Sub CreateObjects(ByVal device As device)
      ' Create new cube mesh with: 
      mesh = New Mesh(24, 16, 0, VertexFormats.Position, device)

      '                     a               b
      '                     +---------------+
      '                    /.              /|
      '                   / .             / |
      '                  /  .            /  |
      '               i +---------------+j  |
      '                 |   .           |   |
      '                 |   .           |   |
      '      g          |   .           |   | c               d
      '     +-----------| . .h          |   +---------------+
      '    /.           |  .            |  /               /|
      '   / .           | .             | /               / |
      '  /  .           |.              |/               /  |
      ' +---------------+               +---------------+   |
      ' |o  .           p              k               l|   |
      ' |   .                                           |   |
      ' |   .                                           |   |
      ' |   . . . . . . . . . . . . . . . . . . . . . . | . + e
      ' |  . f                                          |  /
      ' | .                                             | /
      ' |n                                             m|/
      ' +-----------------------------------------------+


      Dim pa As New CustomVertex.PositionOnly(1, 2, 1)
      Dim pb As New CustomVertex.PositionOnly(2, 2, 1)
      Dim pc As New CustomVertex.PositionOnly(2, 1, 1)
      Dim pd As New CustomVertex.PositionOnly(3, 1, 1)
      Dim pe As New CustomVertex.PositionOnly(3, 0, 1)
      Dim pf As New CustomVertex.PositionOnly(0, 0, 1)
      Dim pg As New CustomVertex.PositionOnly(0, 1, 1)
      Dim ph As New CustomVertex.PositionOnly(1, 1, 1)

      Dim pi As New CustomVertex.PositionOnly(1, 2, 0)
      Dim pj As New CustomVertex.PositionOnly(2, 2, 0)
      Dim pk As New CustomVertex.PositionOnly(2, 1, 0)
      Dim pl As New CustomVertex.PositionOnly(3, 1, 0)
      Dim pm As New CustomVertex.PositionOnly(3, 0, 0)
      Dim pn As New CustomVertex.PositionOnly(0, 0, 0)
      Dim po As New CustomVertex.PositionOnly(0, 1, 0)
      Dim pp As New CustomVertex.PositionOnly(1, 1, 0)


      Dim vertices() As CustomVertex.PositionOnly = New CustomVertex.PositionOnly() { _
         pa, pb, pc, pd, pe, pf, pg, ph, pi, pj, pk, pl, pm, pn, po, pp}

      For ii As Integer = 0 To 15
         vertices(ii).X -= 1.5!
         vertices(ii).Y -= 1.0!
         vertices(ii).Z -= 0.5!
      Next
      Const a As Short = 0
      Const b As Short = 1
      Const c As Short = 2
      Const d As Short = 3
      Const e As Short = 4
      Const f As Short = 5
      Const g As Short = 6
      Const h As Short = 7
      Const i As Short = 8
      Const j As Short = 9
      Const k As Short = 10
      Const l As Short = 11
      Const m As Short = 12
      Const n As Short = 13
      Const o As Short = 14
      Const p As Short = 15

      ' Set up the index information for the 12 faces
      Dim ind As New ArrayList


      ' backs
      ind.AddRange(New Short() {a, b, c})
      ind.AddRange(New Short() {a, c, h})
      ind.AddRange(New Short() {g, d, e})
      ind.AddRange(New Short() {g, e, f})
      'fronts
      ind.AddRange(New Short() {i, p, k})
      ind.AddRange(New Short() {i, k, j})
      ind.AddRange(New Short() {o, n, m})
      ind.AddRange(New Short() {o, m, l})
      'lefts
      ind.AddRange(New Short() {a, h, p})
      ind.AddRange(New Short() {a, p, i})
      ind.AddRange(New Short() {g, f, n})
      ind.AddRange(New Short() {g, n, o})
      'rights
      ind.AddRange(New Short() {j, k, c})
      ind.AddRange(New Short() {j, c, b})
      ind.AddRange(New Short() {l, m, e})
      ind.AddRange(New Short() {l, e, d})

        'tops
      ind.AddRange(New Short() {a, i, j})
      ind.AddRange(New Short() {a, j, b})
      ind.AddRange(New Short() {g, o, p})
      ind.AddRange(New Short() {g, p, h})
      ind.AddRange(New Short() {c, k, l})
      ind.AddRange(New Short() {c, l, d})
      ' bottom
      ind.AddRange(New Short() {n, f, e})
      ind.AddRange(New Short() {n, e, m})

      'Dim ind2 As New ArrayList
      'For ii As Integer = 0 To ind.Count - 1 Step 3
      '   ind2.Add(ind(ii + 0))
      '   ind2.Add(ind(ii + 1))
      '   ind2.Add(ind(ii + 2))
      'Next

      mesh.SetVertexBufferData(vertices, LockFlags.None)
      mesh.SetIndexBufferData(ind.ToArray(GetType(Short)), LockFlags.None)
      ' Dim adjacency() As Integer = New Integer(((mesh.NumberFaces * 3)) - 1) {}
      ' mesh.GenerateAdjacency(0.00999999978!, adjacency)
      'mesh.OptimizeInPlace(MeshFlags.OptimizeVertexCache, adjacency)


      Dim tempMesh As Mesh = mesh.Clone(mesh.Options.Value, (mesh.VertexFormat Or VertexFormats.Normal), device)
      tempMesh.ComputeNormals()
      mesh.Dispose()
      mesh = tempMesh

      'mesh = mesh.Sphere(device, 2, 10, 10)
      numSubSets = mesh.GetAttributeTable.Length
   End Sub

   Protected Sub SetupMatrices()
      Dim angle As Single = (Environment.TickCount / 500.0!)
      device.Transform.World = Matrix.RotationYawPitchRoll(angle, (angle / 3.0!), 0)
      device.Transform.View = Matrix.LookAtLH(New Vector3(0, 0.5!, -1000), New Vector3(0, 0.5!, 0), New Vector3(0, 1, 0))
      device.Transform.Projection = Matrix.PerspectiveFovLH((CType(Math.PI, Single) / 400.0!), 1.0!, 900.0!, 1100.0!)
   End Sub

   Protected Sub Render()
      If deviceLost Then
         ' Try to get the device back 
         AttemptRecovery()
      End If
      ' If we couldn't get the device back, don't try to render 
      If deviceLost Then
         Return
      End If
      ' Clear the back buffer 
      device.Clear((ClearFlags.Target Or ClearFlags.ZBuffer), Panel1.BackColor, 1.0!, 0)
      ' Ready Direct3D to begin drawing 
      device.BeginScene()
      ' Set the Matrices 
      SetupMatrices()
      ' Draw the cube in gray

      device.RenderState.FillMode = FillMode.Solid

      SetupLights()

      '      SetupMaterials(Color.Orange)
      For i As Integer = 0 To numSubSets
         mesh.DrawSubset(i)
      Next
      device.RenderState.DepthBias = 0.0!
      ' Indicate to Direct3D that we're done drawing 
      device.EndScene()
      Try
         ' Copy the back buffer to the display 
         device.Present()
      Catch e As DeviceLostException
         ' Indicate that the device has been lost 
         deviceLost = True
      End Try
   End Sub

   Protected Sub AttemptRecovery()
      Dim res As Integer
      device.CheckCooperativeLevel(res)
      Dim rc As ResultCode = CType(res, ResultCode)
      If (rc = ResultCode.DeviceLost) Then

      ElseIf (rc = ResultCode.DeviceNotReset) Then
         Try
            device.Reset(pres)
            deviceLost = False
         Catch e As DeviceLostException
            ' If it's still lost or lost again, just do 
            ' nothing 
         End Try
      End If
   End Sub

   Friend WithEvents Panel1 As System.Windows.Forms.Panel

   Private Sub InitializeComponent()
      Me.Panel1 = New System.Windows.Forms.Panel
      Me.SuspendLayout()
      '
      'Panel1
      '
      Me.Panel1.BackColor = System.Drawing.SystemColors.ControlDark
      Me.Panel1.Location = New System.Drawing.Point(16, 40)
      Me.Panel1.Name = "Panel1"
      Me.Panel1.Size = New System.Drawing.Size(256, 208)
      Me.Panel1.TabIndex = 1
      '
      'Form2
      '
      Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
      Me.ClientSize = New System.Drawing.Size(292, 266)
      Me.Controls.Add(Me.Panel1)
      Me.Name = "Form2"
      Me.ResumeLayout(False)

   End Sub
End Class

After tweaking the code for an hour I found out that I had to invert the Y axis
      For ii As Integer = 0 To 15
         vertices(ii).X -= 1.5!
         vertices(ii).Y = 1.0! - vertices(ii).Y ' <-- here notice I invert Y
         vertices(ii).Z -= 0.5!
      Next
Anyone knows why ? [Edited by - pagana on December 18, 2005 7:45:55 AM]

Share this post


Link to post
Share on other sites
In Windows's 2D screen coordinate, the x:0.0, y:0.0 is at upper left corner and extends x to the right and y to the bottom (this is the default mode, you can change it with Win32 API though).

In 3D (Direct3D), x axis goes from left to right (negative to positive), y axis goes from bottom to top (negative to positive), z axis goes from back to front (negative to positive).

Please get a mathematics books or look at the explanations in the Direct3D SDK and you can get it.

Share this post


Link to post
Share on other sites
To be honest, most of us don't really have time to dig through your code. If you could, can you please attach a screenshot to your post as this will give us some indication as to what might be wrong. Digging through the code poses a couple of problems. With the question you posted we can't really know what's wrong unless we actually disect your code.

So, please attach a screenshot.

I hope this helps.
Take care.

Share this post


Link to post
Share on other sites

This topic is 4378 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this