Sign in to follow this  
jor1980

[Solved]My model is rendered one half from the front and the other half from the back

Recommended Posts

Hi i made a human face and when i render it i saw one half of the face from the front and the other half from the back, here is a capture changing from z to -z the eye vector: http://img696.imageshack.us/g/57765909.png/ [Edited by - jor1980 on December 28, 2009 5:09:32 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by Deranged
Are the normals on half the head reversed? Possibly during mirroring?


In my FVF i didn´t use normals, here i leave you the code to you to see if there are something wrong.





Imports Microsoft.DirectX.Direct3D
Imports Microsoft.DirectX


Public Class Form1
Private device As Device
Dim verticest As CustomVertex.PositionTextured() = New CustomVertex.PositionTextured(1398) {}
Dim indices As Short() = New Short(7991) {}




Public Sub Initialize()
Dim Present As PresentParameters = New PresentParameters
Present.Windowed = True
Present.SwapEffect = SwapEffect.Discard
device = New Device(0, DeviceType.Hardware, Me.Handle, CreateFlags.SoftwareVertexProcessing, Present)
device.RenderState.Lighting = False

End Sub


Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Me.Text = "DirectX Tutorial using Visual Basic"
Me.Setstyle(Controlstyles.AllPaintingInWmPaint Or Controlstyles.Opaque, True)
Initialize()


Dim nºarchivo As Integer = FreeFile()

FileOpen(nºarchivo, My.Computer.FileSystem.SpecialDirectories.Desktop & "\cara.3d", OpenMode.Input)



For i = 0 To 1398
Dim dato As String
dato = LineInput(nºarchivo)
Dim Datoparts As String()
Datoparts = Split(dato, " ")

verticest(i).SetPosition(New Vector3(NumerosDecimales(Datoparts(0)), NumerosDecimales(Datoparts(1)), NumerosDecimales(Datoparts(2))))

verticest(i).Tu = (NumerosDecimales(Datoparts(3)))
verticest(i).Tv = 1 - (NumerosDecimales(Datoparts(4)))


Next

For i = 0 To 2663
Dim dato As String
dato = LineInput(nºarchivo)
Dim Datoparts As String()
Datoparts = Split(dato, " ")
indices(3 * i) = Datoparts(0)
indices((3 * i) + 1) = Datoparts(1)
indices((3 * i) + 2) = Datoparts(2)
Next

End Sub

Private Sub Form1_OnPaint(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Me.Paint
device.RenderState.CullMode = Cull.None
device.RenderState.FillMode = FillMode.Solid

device.Clear(ClearFlags.Target, Color.Black, 1, 0)


Dim imagen As New Bitmap("C:\Users\Jorge\Desktop\fernando.png")

Dim textura As New Texture(device, imagen, Usage.Dynamic, Pool.Default)
device.MultiplyTransform(TransformType.Projection, Matrix.PerspectiveFovLH(Math.PI / 4, _
Me.Width / Me.Height, 1, 100))





device.MultiplyTransform(TransformType.World, Matrix.LookAtLH(New Vector3(0, 0, -8), New Vector3(0, 2, 0), New Vector3(0, 1, 0)))




device.BeginScene()

device.SetTexture(0, textura)
device.VertexFormat = CustomVertex.PositionTextured.Format
device.DrawIndexedUserPrimitives(PrimitiveType.TriangleList, 0, 1399, 2664, indices, True, verticest)

device.EndScene()
device.Present()

End Sub

Share this post


Link to post
Share on other sites
Even if you don't use per-vertex normals (as in lighting), the hardware still calculates face normals for your triangles for the purpose of backface culling.

When you have mirrored your geometry, the winding order (counterwise or counterclockwise vertices) of the triangles has mirrored accordingly and thus their geometric normal points in the opposite direction from what you'd expect.

As a quick fix, try disabling backface culling. The long-term fix is to fix your model so that the winding order of your triangles is consistent.

Most modeling programs automatically correct the winding order for you when you use a "mirror modifier" (exact name varies). Either your program doesn't, or you used some kind of negative scaling modeling technique that didn't capture the intent of the modification (for example, mirroring only vertex positions).

Share this post


Link to post
Share on other sites
As a separate note, it is a very bad practice to hard-code stuff like the number of indices and vertices. Instead, determine such values from the model file. This way, when the file changes, your code will not break. There are other problems with your code structure as well, but I don't iterate them here unless you want me to.

Also, Managed DX is effectively dead. I recommend using SlimDX to replace it, seeing as you use VB.

Share this post


Link to post
Share on other sites
Quote:
Original post by Nik02
As a separate note, it is a very bad practice to hard-code stuff like the number of indices and vertices. Instead, determine such values from the model file. This way, when the file changes, your code will not break. There are other problems with your code structure as well, but I don't iterate them here unless you want me to.

Also, Managed DX is effectively dead. I recommend using SlimDX to replace it, seeing as you use VB.


Of course you can tell me all my faults, i want to learn and thats the way.The reason i use managed directx is because slimdx seems to be a little bit diferent froma managed directx, and i tried to make the same program on slimdx and i can´t see anything in the screen

Share this post


Link to post
Share on other sites
I'll get back to you about the code tomorrow, as I need to sleep for a while now [smile]

In the meanwhile, apply my quick fix by setting the cull render state to "none".

Also, fcoelho was correct in that you don't use depth buffering. For anything but the most simple of meshes you do want to use it. It can be enabled by setting the AutoDepthStencil and DepthStencilFormat fields of your present parameters structure to appropriate values. If you do enable it, be sure to clear the depth buffer in addition to the ordinary color buffer when you call Clear.

You shouldn't give up on SlimDX so easily. While the syntax is a bit different than MDX (as SlimDX is closely modeled after native DX), the underlying concepts of drawing stuff to the screen are exactly same. And if you do your coding with the DX debug systems running, you can get very accurate info as to why something doesn't work.

Also, there's no guarantee that MDX still works on newer versions of Windows. I haven't tested it on "7" but I wouldn't be surprised if it ceased to initialize out of the box.

Share this post


Link to post
Share on other sites
Okay, here's my analysis of your code in general, and recommendations on how to fix the flaws. I don't drill very deep on the issues; for that, I recommend reading relevant articles from MSDN.

If I sound harsh here, it is unintentional. My goal in this post is to help you.


VB usage/coding style:

-You have defined all the functionality in one module, Form1. To reap the benefits of the object-oriented paradigm, you should divide your functionality into classes - for example, a Mesh class which has member functions Load(fileName as String, parentDevice as Direct3D.Device), Render() etc. (for example). This way, you don't have to search thru a lot of irrelevant code everytime you change something. This approach has a lot of other benefits too, but listing them would require a whole book.

-FreeFile and FileOpen are deprecated functions, they are only provided for backwards compatibility with older versions of Visual Basic. Consider using the stream classes to do your file handling - in addition to reading actual disk files, you can use network or memory streams instead for no additional work. Also, the stream classes have additional functionality such as asynchronous processing.

-You don't do any error checking whatsoever. You should check that a file open operation succeeded before reading data off it, and that a D3D device was successfully initialized before you send requests to it. If something goes wrong, your code will crash as it is. With proper error handling, you can gracefully handle the exception conditions. A D3D device can be especially crash-prone and cause blue screens upon exceptions, since it is only a relatively thin layer between your program and the hardware.



D3D usage:

-Usually, rendering is done on the idle time of the application instead of the OnPaint handler - that is, everytime the app's Windows message queue is empty, render. Google for "d3d message pump vb" for a proper implementation. Of course, if it is enough to paint the screen less often (such as in a chess game, for example), OnPaint can be fast enough.

-You don't seem to call Device.SetTransform anywhere in the code. MultiplyTransform multiplies the previous transform of the device with the new transform you provide, so the effect will be cumulative. This is usually not what you want. In your case, I could imagine that the side effects of MultiplyTransform cause your model to zoom away from the screen everytime you render, since you multiply the view and projection matrices by their previous values.

-Consider using vertex and index buffers to feed your geometry to the hardware. User primitives are not optimal since the device cannot allocate them statically for best performance, and you will upload the geometry every time you call the drawing function.

-You should release all device resources upon exiting your app. Otherwise, your app can cause memory leaks as the system cannot determine which objects it can unload from memory and/or release physical device resources from.

-Use the D3D debug runtime when developing apps. Seriously. If you don't know how, read up on MSDN. It is time well spent.



General best practices:

-You are re-loading and re-creating your texture every single frame. This destroys your performance, and it can't be good for your hard drive either in the long run.

-As I said previously, it is a bad practice to hard-code any values to your files. In your case, the number of vertices and indices should be read from the model file itself. Also, you should store material settings (and other related stuff) or at least references to them in the model file. From your code, I can deduce that the file format is too simple for this kind of robust handling, so consider defining a file format that can store all the data, or use a well-known file format. Obj format is pretty close to your current format.

-Don't hardcode file paths. Even though SpecialDirectories.Desktop is technically not a hard-coded path, wouldn't it make more sense to store your resources relative to the executable path?

-In general, in my opinion VB isn't the greatest language for game development. However, the priority should be in getting stuff done. If you know the language well, do keep using it but consider learning C-style languages as well. Native D3D development is done in C++, and it is the thinnest possible interface between your app and D3D.



Consider this list as a summary, not a comprehensive list of all possible issues.

I hope this helps!

Share this post


Link to post
Share on other sites
Firs of all thank´s for all the time you spent with me.
i don´t have time today to test all you said me, i will do it tomorrow and i will tell you the result.

Thank´s again for your time, if you want i could upload it to you to see my problems.



How can i dissable backface culling?
regards

Share this post


Link to post
Share on other sites
Quote:
Original post by jor1980
Firs of all thank´s for all the time you spent with me.
i don´t have time today to test all you said me, i will do it tomorrow and i will tell you the result.

Thank´s again for your time, if you want i could upload it to you to see my problems.



No problem.

Following my suggestions will require a complete rewrite of your code as well as a complete refactoring/replacement of your file format, so be sure to take a snapshot of the current app as it is. After a few years, you'll wonder what inspired you to write something like that :)

Having inspected your code the second time, I believe your problem stems from the fact that you haven't enabled depth buffering. Check the MDX documentation on how to do this, it is a very trivial thing. Essentially, it involves modifying your present parameters structure a little, and clearing the depth buffer in addition to the color buffer, like I said in my earlier post.

Quote:


How can i dissable backface culling?


I originally missed that part of your code, but you already do:

device.RenderState.CullMode = Cull.None


Usually, you'd want to cull counterclockwise triangles, because in practice they tend not to be visible anyway.

I frequently visit the DirectX board here, so if you have additional questions, please come there and ask! I like to think that we really know what we're talking about.

Share this post


Link to post
Share on other sites
Nik02 finally i have solved it.It was the depth buffer, i added this to my present parameters:

Present.EnableAutoDepthStencil = True
Present.AutoDepthStencilFormat = DepthFormat.D16


and also this to the device.clear:

device.Clear(ClearFlags.Target Or ClearFlags.ZBuffer, Color.Black, 1, 0)


i am very grateful, thanks for all

Share this post


Link to post
Share on other sites
Glad you got it to work.

Be sure to turn the culling on for performance, you don't (usually) want to draw stuff that isn't going to be visible on screen anyway.

That said, disabling culling can be useful when debugging drawing problems.

Share this post


Link to post
Share on other sites

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