Sign in to follow this  

MS3D Texture Array.

This topic is 3343 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

I recently took up the task of making my ms3d loader compatible with vertex arrays. Which has been successfuly so far. I made a parser application which modified the triangle structure so that all the vertex indices were right next to each other. i could then point to the first vertex indice specified in the mesh struct specify how many to draw from the meshs triangle count variable and draw the mesh. My draw loop merely jumps to the next mesh and then its around 10 lines of ASSEMBLY code to setup the draw, nice eh? Kinda like this: Indice1,Normal1,Tex1,Indice2,Normal2,Tex2 becomes -> Indice1 Indice2 Tex1 Tex2 Normal1 Normal2 Now onto my problem, When i come to the texture coordinates. The s and t coordinate are separated in m_s[3] and m_t[3] in the triangle structure. so i need to interleave them right? so what i need is this: m_s[1],m_t[1],m_s[2],m_t[2],m_s[3],m_t[3] and i did just that. But unfortunatly it doesnt work. When the textures display theyre all distorted and skewed. This tells me that they are wrong. But before i spend several hours trying to port my assembly code into C :D. Am i doing it right? am i meant to do m_s[1],m_t[1],m_s[2],m_t[2],m_s[3],m_t[3]? In a bit of a rush atm, i can post some much more informative code later on.

Share this post


Link to post
Share on other sites
Quote:
Original post by whyisitalwaysme2
My draw loop merely jumps to the next mesh and then its around 10 lines of ASSEMBLY code to setup the draw, nice eh?
Why in all the hells are you writing an OpenGL application in assembly? I could possibly understand it if you were coding one of those 4k demos, but in that case you wouldn't be using a format as inefficient as milkshape.
Quote:
But before i spend several hours trying to port my assembly code into C :D
And why you would then port that assembly code to C is an absolute mystery...

Share this post


Link to post
Share on other sites
It's about speed/efficiency and control, if your doing something yourself as a hobby, you may as well do it properly. Assembly fair enough, can't actually be used for anything in the *real world* but once you start and see just how much lighter and less bloated it is, programming in c (low level by todays standards) irritates you :p.

As for milkshake, like i said, im building a parser which cuts out all useless information and then reorders it all for use with vertex arrays.etc And yes, its a crap file format. I was going to make an importer and exporter but its all written in c++ and i have to import lib files, so i figured it would be quicker just to parse an ms3d file.

And by porting to c i meant just the bits of code relevant to my problem, so that more people on here could actually make sense of it.

Share this post


Link to post
Share on other sites
I just tried something else. When i call glDrawElements, and it looks through the indices does it select texture coordinates out from the array like it does with the vertex coords? in other words do the the indices also index which texture coords to draw as well as which vertex coordinates?

Im really confused. My hex editor is showing a nice clean parse of the data being placed in the right places in my output file :/.

Heres my assembly code for parsing, havent ported it yet. its unoptimized since im constantly redoing it over and over in different ways. Assume Source points to the start of the original files triangle structures.


mov dword[Counter],0
TransferTriangleTex:
mov eax,dword[Counter]
mov ecx,70
mul ecx
add eax,44
mov ebx,eax
add ebx,dword[SourceFilePointer]
add ebx,dword[SourceFileBuffer]
mov eax,dword[DestinationFileBuffer]
add eax,dword[DestinationFilePointer] ;eax= dest, ebx= src

mov ecx,dword[ebx] ;s
mov dword[eax],ecx

mov ecx,dword[ebx+12]
mov dword[eax+4],ecx ;t

mov ecx,dword[ebx+4] ;s
mov dword[eax+8],ecx

mov ecx,dword[ebx+16] ;t
mov dword[eax+12],ecx

mov ecx,dword[ebx+8] ;s
mov dword[eax+16],ecx

mov ecx,dword[ebx+20] ;t
mov dword[eax+20],ecx





add dword[DestinationFilePointer],24
inc dword[Counter]
mov eax,dword[Count]
cmp dword[Counter],eax
jne TransferTriangleTex

Share this post


Link to post
Share on other sites
Quote:
Original post by whyisitalwaysme2
It's about speed/efficiency and control, if your doing something yourself as a hobby, you may as well do it properly.
That assumes that you have sufficient knowledge of instruction scheduling, caching, memory latencies, etc. to optimise better than the compiler. Your code is SIMD optimised, right?
Quote:
Assembly fair enough, can't actually be used for anything in the *real world* but once you start and see just how much lighter and less bloated it is, programming in c (low level by todays standards) irritates you :p.
Methinks you missed the entire point of programming languages, if you regard C as bloated in this day and age...
Quote:
As for milkshake, like i said, im building a parser which cuts out all useless information and then reorders it all for use with vertex arrays.etc And yes, its a crap file format. I was going to make an importer and exporter but its all written in c++ and i have to import lib files, so i figured it would be quicker just to parse an ms3d file.
This is even less a job for assembly. Write a converter in a high-level language (such as python, or ruby), that outputs a slimmed-down binary format you can load with your assembly. Even if you insist on writing your application in assembly for (very dubious) performance reasons, simple tools don't need that level of performance, so you should be writing them in an easy language.
Quote:
And by porting to c i meant just the bits of code relevant to my problem, so that more people on here could actually make sense of it.
A fair number of us can read ASM - it is a requirement for most CS degrees, after all.
Quote:
I just tried something else. When i call glDrawElements, and it looks through the indices does it select texture coordinates out from the array like it does with the vertex coords? in other words do the the indices also index which texture coords to draw as well as which vertex coordinates?
All vertex elements use the very same index - i.e each value in the index array specifies the same offset into each of the vertex, normal and texture-coord arrays.

Share this post


Link to post
Share on other sites
Okay thats ruled something out at least.

Although a lot of people can read asm its not exactly a mainstream language, im not trying to sound elitist or anything, its just i want this solved :/. I do try to follow basic optimization procedures such as caching and byte alignment for memory, i am aware of how complex and intelligent compilers are these days.

SIMD? not so much, Couple of areas where my code could benefit from some SSE/MMX with maybe parallel processing but not enough to make me actually stop and get the intel docs out and spend several hours on a small piece of code for 10-20 cycles. Obviously wherever theres code that does a repeated job on a large amount of data ill be more inclined to go for SIMD optimized first time :p. But this is things like a couple of trig operations for basic movement. This May contradict my previous statement of taking my time or even using assembly at all but i like to get a *section* of a program done before i go back and clean it up.


I could of definetly used python/ruby and hell, i should have. But i had actually written half the code in assembly before i even realised it. You see my code is derived from Nehe's lesson 31 where the guy does all the parsing at load time. I was porting this and realised i should probably run this process on the file at development time instead of runtime. So it was a bit of a copy and paste job but your right, assembly is stupid for this.



Share this post


Link to post
Share on other sites
Okay in my draw loop i set my vertice pointer to the start of my vertices for all meshes, and since all my triangle structures have been altered to be in chunks. All my normals and texture pointers point to the start of a large array for all meshes.

Here i after i load the file i set the pointers


;Find Vertices
mov eax,[ModelBuffer]
movzx ecx,word[eax]
mov [VerticeCount],ecx
add eax,2
mov [VerticePointer],eax
;Find Triangles
mov eax,13
mul [VerticeCount]
add eax,[VerticePointer]
movzx ebx,word[eax]
mov [TriangleCount],ebx
add eax,2
mov [TrianglePointer],eax
;Find Meshes
mov eax,66
mul [TriangleCount]
add eax,[TrianglePointer]
movzx ecx,word[eax]
mov [MeshCount],ecx
add eax,2
mov [MeshPointer],eax
;Find Normals
mov eax,6
mul [TriangleCount]
add eax,[TrianglePointer]
mov [NormalPointer],eax
;find Texture Coords
mov eax,36
mul [TriangleCount]
add eax,[NormalPointer]
mov [TexturePointer],eax





proc ModelRender
invoke glVertexPointer,3,GL_FLOAT,0,[VerticePointer]
invoke glNormalPointer,GL_FLOAT,0,[NormalPointer]
invoke glTexCoordPointer,2,GL_FLOAT,0,[TexturePointer]
mov eax,[MeshPointer]
mov [CurrentMeshPointer],eax
mov [MeshCounter],0
DrawMesh:
cmp [MeshCounter],0
je SkipMeshJump
mov eax,[MeshTriangleCount]
mov ebx,2
mul ebx
add eax,3
add [CurrentMeshPointer],eax
SkipMeshJump:
mov ebx,[CurrentMeshPointer]
movzx eax,word[ebx+3]
mov ecx,6
mul ecx
mov ecx,eax
add ecx,[TrianglePointer]
movzx eax,word[ebx+1]
mov [MeshTriangleCount],eax
mov ebx,3
mul ebx
invoke glDrawElements,GL_TRIANGLES,eax,GL_UNSIGNED_SHORT,ecx
inc [MeshCounter]
mov eax,[MeshCount]
cmp [MeshCounter],eax
jne DrawMesh
ret
endp




And Here is my parse loop which is unchanged from yesterday which converts the data file which the above code reads.


mov dword[Counter],0
TransferTriangleTex:
mov eax,dword[Counter]
mov ecx,70
mul ecx
add eax,44
mov ebx,eax
add ebx,dword[SourceFilePointer]
add ebx,dword[SourceFileBuffer]
mov eax,dword[DestinationFileBuffer]
add eax,dword[DestinationFilePointer] ;eax= dest, ebx= src

mov ecx,dword[ebx] ;s
mov dword[eax],ecx

mov ecx,dword[ebx+12]
mov dword[eax+4],ecx ;t

mov ecx,dword[ebx+4] ;s
mov dword[eax+8],ecx

mov ecx,dword[ebx+16] ;t
mov dword[eax+12],ecx

mov ecx,dword[ebx+8] ;s
mov dword[eax+16],ecx

mov ecx,dword[ebx+20] ;t
mov dword[eax+20],ecx





add dword[DestinationFilePointer],24
inc dword[Counter]
mov eax,dword[Count]
cmp dword[Counter],eax
jne TransferTriangleTex




Ive kind of narrowed it down to 2 thing. Either theres a tiny barely noticeable mistake *somewhere* or im not actually interleaving the coordinates correctly.
Sorry for the crappy code :/.

Share this post


Link to post
Share on other sites
Quote:
Original post by whyisitalwaysme2
SIMD? not so much, Couple of areas where my code could benefit from some SSE/MMX with maybe parallel processing but not enough to make me actually stop and get the intel docs out and spend several hours on a small piece of code for 10-20 cycles.
My point is that modern compilers offer automatic SIMD optimisation, as well as all that pesky register allocation and cache optimisation...

Quote:
Ive kind of narrowed it down to 2 thing. Either theres a tiny barely noticeable mistake *somewhere* or im not actually interleaving the coordinates correctly.
Despite my earlier statement, I am finding your assembly pretty hard to follow [smile]
However, it does appear that you are interleaving your texture coordinates correctly, so I would guess a bug somewhere.

Share this post


Link to post
Share on other sites
Quote:

The t values are all set to 1.0-(original value). The reason for this is that OpenGL uses a lower-left coordinate system, whereas Milkshape uses an upper-left coordinate system for it's texture coordinates. This reverses the y coordinate.


Just went through the nehe tut and noticed that by sheer chance. God dammit. i HATE this file format XD.

Share this post


Link to post
Share on other sites
okay i made a model with a single triangle. Here is the actual data stored from [TexturePointer] when its non interleaved (note i havent inverted the t coords yet):

What i have currently:

Uninterleaved
S = 3F 00 00 00/00 00 00 00/00 00 00 80
T = 3F 00 00 00/00 00 00 80/3F 00 00 80

Interleaved:

s1 t1 s2 t2 s3 t3
3F 00 00 00/3F 00 00 00/00 00 00 00/00 00 00 80/00 00 00 80/3F 00 00 80

Okay so what i need to know is, which is the negative flag? 80 or 3F?

Once i know this i can calculate the T coords values...make up a triangle in immediate mode with manually calculated coords and see exactly how to arrange them.

So close!

Share this post


Link to post
Share on other sites

This topic is 3343 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