Not logged in, Join Here! or Log In Below:  
 
News Articles Search    
 

 Home / 3D Theory & Graphics / Normalize in fixed point Account Manager
 
Archive Notice: This thread is old and no longer active. It is here for reference purposes. This thread was created on an older version of the flipcode forums, before the site closed in 2005. Please keep that in mind as you view this thread, as many of the topics and opinions may be outdated.
 
Rhinoid

May 27, 2005, 02:16 AM

Hi Guyz,

I've ported my 3d engine to fixed point to get it running on the PocketPC and it is starting to get some decent performance, but I bumped into a little problem.

After adding lighting (which is quit a killer for any decent performance) I noticed weird color sparks. After debugging for quit a while I found the source of the problem. Normalize in fixed point is not as straightforward as one might expect.

If the vector is huge to begin with, then the final division through the length of the vector does not give problems. But if the vector is tiny (a lot smaller then the unit vector) then the precision is so off that the resulting vector could end up bigger then the unit vector.


to make this more clear, assume this realworld example where we have 8bit fixed point and a vector of (41,23,2).

The length in fixed point would be: ((41*41)>>8), ((23*23)>>8), ((2*2)>>8)
= (1681+529+4)>>8 = 8 (actually 8.6)

sqrt(8) in fixed point is 32 in fixed point

so dividing the vector through fixedpoint 32 gives:

(-328, 184, 16)

as you can see...this resulting unit vector has it's first element already 1.5 times the unit size.

This gets crappier results, the smaller the elements of the vector to normalize are.


I know this all has to do with precision but I'm wondering how to fix this elegantly in fixed point without having to fallback on floating point.

Should I switch to 64bit calculations here? I could always choose to implement this in Arm assembly of course with maybe a small penalty.
Or should I do some kind of initial check to see what kind of vector I have and then prescale the vector before doing the normalization?

Any thoughts?

Cheers,

Reinier

 
fman256

May 27, 2005, 04:59 AM

You can do a fixed point divide without using anymore iterations, because the result still has the same # of bits.

This divides two numbers in 16.16 fixed point,although there may be bugs in it. Also it's an unsigned division.

  1.  
  2. |fixdivu|        PROC
  3.         sub             r3,r3,r3
  4.         rsb             r1,r1,#0
  5.  
  6.         mov     r3,r0,lsr #16
  7.         mov     r0,r0,lsl       #16
  8.         adds    r0,r0,r0
  9.  
  10. ; repeat 32 times
  11.         adcs    r3,r1,r3,lsl #1
  12.         subcc   r3,r3,r1
  13.         adcs    r0,r0,r0
  14.  
  15.         mov       pc, lr
  16.  

 
Twistofchaos

May 27, 2005, 06:00 AM

>weird color sparks

Hey those sounds neat. You might want to keep them in.

Stan

 
Rhinoid

May 27, 2005, 06:28 AM

;^)

The color fluctuates rapidly from dark to ultrabright, but since it uses vertex shading and gouraud the resulting effect is weird color patches flowing over the model.

I think you are right that it is a neat effect if one wanted this. One for the 'unwanted effect but neat nonetheless' list.

R

 
Rhinoid

May 27, 2005, 06:32 AM

Hi,

how would this code fragment help?
Would it help because it uses more precision? Or would it only cover up the problem to more localised situations?

thanks for the input!

R

 
Japigeman

May 27, 2005, 07:49 AM

Just a little thought, could you make sure you get the most of the 16 bit range by making the numbers as huge as possible from the start?

I mean, as soon as you are about to do the whole normalisation, shift all the the numbers of the input vector left until one of the numbers is about to get "too big".

This way you always work with "huge" vectors, and the normalisation will return the same value anyway.


 
Rhinoid

May 27, 2005, 04:30 PM

great idea...I'll give that a try...!

 
fman256

May 27, 2005, 04:41 PM

Sorry, i missed the point. I was thrown off by the fact you mentioned using floating point. You could try something like this:

int m=v.x*v.x+v.y*v.y+v.z*v.z;
if(m

 
Rhinoid

May 29, 2005, 04:04 AM

Just wanted to let you know that your trick works like a charm!

Cheers,

R

 
This thread contains 9 messages.
 
 
Hosting by Solid Eight Studios, maker of PhotoTangler Collage Maker.