3d drawing order

  • Thread starter Thread starter Darkness
  • Start date Start date
Status
Not open for further replies.
On a modern processor, floating point operations are perhaps slower than integer work. But your first question should be: does it matter?
You’re saying slower-than-necessary code is acceptable?
He’s writing a software 3-D engine.  There isn’t hardware acceleration here.  Order triangles, rasterize them to the screen, manually fill them, checking the z-buffer along the way, and you see how fast it goes without all the optimizations you can give it.


Even if they are, you get the code working first, writing it in the easiest and clearest manner possible, then you optimise it.
Absolutely.
But the optimizations I suggested won’t cause problems, and they are things that may cause problems in the future if you have to change them to optimize.
If he decided to go with an integer z-buffer after having already written it using floats, he is going to have to be very careful about which parts of his engine that will affect.
As for the organizing of the triangles from close to far, I am going off something he is already doing.
He already posted he has a working system for drawing triangles far-to-near, so such a change as I suggested shouldn’t be a problem.
That doesn’t mean I disagree with what you said.
If he looks at his code and thinks it may be something that can wait, or that it may cause problems for whatever reason, then certainly, keep it for last.
I just generally assume people can gauge these types of things for themselves.


Bear in mind, here, I just ran some quick profiles on my laptop (an Intel Celeron-M), and if you use SSE, floating point operations are over twice as quick as integer...
That’s crazy.
I didn’t expect SSE to be THAT fast.
I have no doubts they would be close or faster by a bit, but SSE is not supported on all instruction sets, and I have noticed that even among these boards many people have been stuck with low-end machines.
I’m not programming on 10-year-old processors, but I prefer compatible code.  That’s all.


L. Spiro
 
If I had to guess, LSpiro, I would say that your day job involves programming on 10 year old processors ;)
That would be me I tend to program things like ARM7 and ARM9 processors ;)

Cyb
 
The assumption I'm objecting to, really (partly because I see it among the developers at work too) is that you should make some changes "because it'll make the code quicker" even though you don't know whether it will make the code quicker! Hence the whole premature optimisation malarky. Rather than wasting time guessing which bits need to be made faster, it's preferable to get it working and then benchmark.

(How could using an integer zbuffer make it slower? Well, quite apart from the fact that if you want maximum speed, you'd later convert it back to floats to use 3dnow or SSE, do you know for sure what the overhead for converting all the incoming data from floats would be?)

I still have memories of the time I optimised all our string parsing code at work only to find out it wasn't the bottleneck after all and it was the database causing the slowdown ... not good.

Cyberman: ARM7+9 says Nintendo DS to me... ;)
 
Slightly off topic, but,
ficedula: how did you make data transfers between your computer and your Nintendo DS? Must've done it wireless or through one of the cartridge ports, correct?
 
Yep; I already had a flash2advance cartridge for my GBA, so originally I was using Wifime to boot the DS from the cartridge. I got tired of rewriting the cartridge every time, though, so then I've flashed the firmware on the DS to remove the signature checks; now I can boot the code directly over Wifime. The DS wifi bounty is nearly complete, so soon we'll have a TCP/IP stack on it...
 
ficedula you are having entirely too much fun with your DS LOL

It's too bad the GBA simply doesn't have enough internal memory even fake running FF7 :D

Cyb
 
Another (more or less unrelated) question:

I'm working on camera angle now, and im using the equation:

screen_x = distance_from_screen * tan(arccos(a dot b))

where a is the direction of the camera vector and b is the vector from the camera through the vertex.

This always gives a positive angle (at least in the viewable area)

How can I make this give me a negative value when the vertex lies below this camera vector / Is the a more effective way to do this?

Does this make any sense?
 
angle.PNG


I need to find the distance between the long black line and the red line along the short black line. In this case it needs to be negative because the red line falls below the black one.
 
Still not enough input. What should be usage of that angle ? Why should it be negative ?

Also, there are tons of math algorithms on the net, try to google for them (aproximate name should be sufficient for google).
 
The point? Displaying this on screen. You can add 400 (if the output is in range <-400 ; 400>) to the result and you'll get X coordinate in 800x600 resolution. Now... since that algorithm always gives positive numbers, after displaying, everything will be on the right side of the screen leaving the left side blank.

I think, that using arccos there is no easy way to get negative results. You'll need to check if the point is actually on the left "side" of that black line and correct the result if necessary.

dziugo
 
If you are referring to rasterization, you may find it easier to use these:


Code: [Select]
Code:
INT iHalfScreenX = g_piResolution.x >> 1;INT iHalfScreenY = g_piResolution.y >> 1;pntReturn.x = (LONG)((FLOAT)iHalfScreenX + (FLOAT)iHalfScreenX * (d3vTarg.fX / d3vTarg.fZ));pntReturn.y = (LONG)((FLOAT)iHalfScreenY - (FLOAT)iHalfScreenX * (d3vTarg.fY / d3vTarg.fZ));
Do not perform this equation if d3vTarg.fZ is 0.

This small section does not account for the rotation of the camera.
This is the whole code written for my Doom® 3 perfect-lock auto-aim.
Code: [Select]
Code:
// Transform a 3-D point into screen coordinates.  Returns TRUE if the coordinate is actually on the screen.BOOL Rasterize( PDoom3Vector pd3vPlayerPos, PDoom3Direction pd3dPlayerDirection, PDoom3Vector pd3vTargetPos, POINT &pntReturn ) { Doom3Vector d3vTarg; // Copy the target vector so we don’t change it. memcpy( &d3vTarg, pd3vTargetPos, sizeof( d3vTarg ) ); // Translate the vector to the center of the world, which would literally mean // our player. d3vTarg.fX -= pd3vPlayerPos->fX; d3vTarg.fY -= pd3vPlayerPos->fY; d3vTarg.fZ -= pd3vPlayerPos->fZ; // The pitch and yaw are in radians. FLOAT fPitch = 0.0f - D3DXToRadian( pd3dPlayerDirection->fPitch ); FLOAT fYaw = D3DXToRadian( pd3dPlayerDirection->fYaw - 90.0f ); // Rotate accordingly.  This must be done in this order! if ( fYaw != 0.0f ) {  FLOAT fTemp = d3vTarg.fZ * (FLOAT)cos( fYaw ) - d3vTarg.fX * (FLOAT)sin( fYaw );  d3vTarg.fX = d3vTarg.fX * (FLOAT)cos( fYaw ) + d3vTarg.fZ * (FLOAT)sin( fYaw );  d3vTarg.fZ = fTemp; } if ( fPitch != 0.0f ) {  FLOAT fTemp = d3vTarg.fY * (FLOAT)cos( fPitch ) - d3vTarg.fZ * (FLOAT)sin( fPitch );  d3vTarg.fZ = d3vTarg.fZ * (FLOAT)cos( fPitch ) + d3vTarg.fY * (FLOAT)sin( fPitch );  d3vTarg.fY = fTemp; } // The result will be where the enemy is in relation to our player. // From this 3-D point, we can directly determine the 2-D screen point where the 3-D point would be drawn. // This is useful for drawing targets over objects or determining if an object is on the screen. if ( d3vTarg.fZ == 0.0f ) {  pntReturn.x = (LONG)(d3vTarg.fX * (FLOAT)(g_pntResolution.x >> 1) + (FLOAT)(g_pntResolution.x >> 1));  pntReturn.y = (LONG)(d3vTarg.fY * (FLOAT)(g_pntResolution.y >> 1) + (FLOAT)(g_pntResolution.x >> 1)); } else {  pntReturn.x = (LONG)((FLOAT)(g_pntResolution.x >> 1) + (FLOAT)(g_pntResolution.x >> 1) * (d3vTarg.fX / d3vTarg.fZ));  pntReturn.y = (LONG)((FLOAT)(g_pntResolution.y >> 1) - (FLOAT)(g_pntResolution.x >> 1) * (d3vTarg.fY / d3vTarg.fZ)); } if ( d3vTarg.fZ < 0.0f ) { return FALSE; } if ( pntReturn.x < 0 || pntReturn.x >= g_pntResolution.x ) { return FALSE; } if ( pntReturn.y < 0 || pntReturn.y >= g_pntResolution.y ) { return FALSE; } return TRUE;}


For my auto-aim, I manually transform according to the rotation of my player’s head (camera [math shown]) but in your engine you are going to have more control over how your rotations work and you should use an optimized rotation routine.
This routine is also not optimized for handling a massive number of points.
You would want to handle your rotations separately from your rasterization, using the first code I posted as your primary rasterization method.
Pass it the final X, Y, and Z points of each vertex (or whatever) after you have rotated the whole scene according to the camera.

You can modify the formula to handle view ports also, and note that I used iHalfScreenX in both sides of the formula.  This is to keep a 1-to-1 aspect ratio.  Aspect ratios can be added to the equation as well.

I have not benchmarked it for speed.


L. Spiro
 
Status
Not open for further replies.
Back
Top