| | LHS
Registered: Dec 2002 Posts: 66 |
Vector visibility - Z axis solution
Hi all,
I am coding a classical demo part - filled vector. I have a routine for vertex transformation (rotation) and a routine for EOR surface filling.
If I have f.e. a simple opaque cube (all angles are 90dgrs), what is the best technique to check which surface I may show and which I mustn't? I have f.e. 4 vertexes of a side (X, Y and Z coordinates in signed variable), how can I calculate, if is this surface (of the cube) visible or invisible? I think the same technique can be used for a glanz cube which surface is inner or outer.
Thanks,
LHS |
|
| | JackAsser
Registered: Jun 2002 Posts: 2014 |
It's all quite easy. Simply check which side of the plane you're on.
A plane is defined by the following equation:
Ax+By+Cz+D=0 where A,B,C is the normal of the plane.
Conviniently the normals for a cube's surfaces are the unit vectors definied by your rotation matrix.
If you further assume that the cube is rotated around origo and doesn't move, then the x and y component of the equation is 0, only z is defined (distance from eye to rotation origo). This reduces the plane equation to:
Cz+D=0
If Cz+D>0 then z lies outside the plane (visible).
Now, C is derived (taken from) directly from the rotation matrix.
z is the eye relative to the cube, i.e. the distance to the cube (constant).
D is the distance from rotation origo to the plane's center expressed in units of normal-length (1).
Hence:
C*z+D>0 => C>D/z => C>constant (visible).
So, it's a simple compare on the Z-value of one of the unit axises in the rotation matrix depending on which of the 6 surfaces you want to check visibility on.
Now, I know Graham have an alternative explanation to this, but it boils down to the exact same equations (and code). I find his explanations less understandable, however you might not. Graham, please post your explanation.
Note: This method assumes:
1) Convex objects
2) If same constant is used for all surfaces then all surfaces must lie from the same distance from rotation origo, else you need one constant per surface.
3) No x,y,z movement of the object, i.e. fixed rotation origo.
4) If you're using the values of the rotation matrix directly to derive surface normals, all you can do is cubes. For other surfaces you need to rotate the normals first and use their rotated Z-values in the compare.
Good luck!
|
| | Oswald
Registered: Apr 2002 Posts: 5094 |
(p1x-p2x*p1y-p3y)-(p1y-p2y*p1x-p3x)
- all 3 points must lie in a plane of the face you're checking
- the rotational order of these points will decide about default visibility. (ie when defining an object faces visible by default must have the opposite rotational order compared to faces invisible)
- you have to calculate this AFTER projections were done
- you only need the sign of the result to decide visibility (trial and error, depends on how you set up rotational orders)
- dont ask me about the math background I've forgot it through the years :/ derived from cross product, and gives Z coordinate iirc, but my google findings were against that. |
| | Oswald
Registered: Apr 2002 Posts: 5094 |
read the different perspective series. issue 8-9-10
http://www.ffd2.com/fridge/chacking/
also you might find some help here:
http://codebase64.com/
btw, you can simply compare the Z coordinates of a normal for each side for a cube (which one is smaller), and you can get "inside" pointing normals from the default 8 cube coordinates (this is roughly what jackasser talks about but in human language:), but with perspective projection you will get incorrect results. as projected faces visibility differs from unprojected ones. |
| | LHS
Registered: Dec 2002 Posts: 66 |
Thanks,
I have read this technique in a book about universal 3D gfx, but I have disbelieved in usability at C64 :-)
The simple Z compare doesn't give me sufficient solution (I mean this technique is sufficient, but maybe I have a bug in my routine, maybe I must check signed overflow etc...).
Oswald, do you mean
((p1x-p2x)*(p1y-p3y))-((p1y-p2y)*(p1x-p3x))
or
(p1x-(p2x*p1y)-p3y)-(p1y-(p2y*p1x)-p3x)
(I mean the firts is right)???
If I have f.e. a hexagonal polygon with right rotation order, check first 3 vertexes (p1, p2, p3 - with your comparasion) is enough?
p.s. sorry, I don't like read english books, as you can see in my english diction... |
| | Oswald
Registered: Apr 2002 Posts: 5094 |
((p1x-p2x)*(p1y-p3y))-((p1y-p2y)*(p1x-p3x)) is the right one.
you can check any vertexes they only should be on the plane of the face in the right order, tho with low precision c64 routines it is better to check ones which are as far as possible. :) sorry for no math background but I'm using this formula since ~10 years, and forgot :/. (copied this one straight from desert dream's raster cube so it should work ;) |
| | JackAsser
Registered: Jun 2002 Posts: 2014 |
Quote: Thanks,
I have read this technique in a book about universal 3D gfx, but I have disbelieved in usability at C64 :-)
The simple Z compare doesn't give me sufficient solution (I mean this technique is sufficient, but maybe I have a bug in my routine, maybe I must check signed overflow etc...).
Oswald, do you mean
((p1x-p2x)*(p1y-p3y))-((p1y-p2y)*(p1x-p3x))
or
(p1x-(p2x*p1y)-p3y)-(p1y-(p2y*p1x)-p3x)
(I mean the firts is right)???
If I have f.e. a hexagonal polygon with right rotation order, check first 3 vertexes (p1, p2, p3 - with your comparasion) is enough?
p.s. sorry, I don't like read english books, as you can see in my english diction...
Z-compare is sufficient. I've implemented in my own vectors and Graham uses the technique in Natural Wonder. ;D
Also, Oswalds method using the cross-product is correct, however a lot slower on a c64 but also much more general.
Use what ever method you like, it can always be changed later. ;D
|
| | Oswald
Registered: Apr 2002 Posts: 5094 |
Z compare on projected faces is sufficient? iirc, projected faces gets hidden "sooner" than non projected ones -> will bug.
"you need to rotate the normals first and use their rotated Z-values in the compare."
how is a rotation faster than 2 mul in the cross method? |
| | JackAsser
Registered: Jun 2002 Posts: 2014 |
Quote: Z compare on projected faces is sufficient? iirc, projected faces gets hidden "sooner" than non projected ones -> will bug.
"you need to rotate the normals first and use their rotated Z-values in the compare."
how is a rotation faster than 2 mul in the cross method?
Given the constraints I gave a simple Z-compare of the normal is sufficient, please read the math I posted and you will understand (I mean, it's based on which side the eye is of a plane, projected or not).
The problem you think of is to simply check the SIGN of the Z-component. That would yield the problem you say. In my example I calculate a CONSTANT to compare against and this constant depends on object<->eye distance AND object size.
So, yes and no. :D I hope I make myself clear.
However, for general back face culling I'd also go for the re-creation of the Z-component of the normal by using the cross product of the projected vectors of course.
|
| | LHS
Registered: Dec 2002 Posts: 66 |
Huh, there is a misunderstanding from my side. I am sorry, I forgot a lot of school geometry...
How can I calculate the normal?
I have 4 points (p1-p4) of a plane (with X, Y and Z coordinates). How can I use these coordinates for the "Z-normal compare"?
The universal definition is Ax+By+Cz+D=0, but what is the implementation (algorithm, no 6502 code)?
|
| | JackAsser
Registered: Jun 2002 Posts: 2014 |
Quote: Huh, there is a misunderstanding from my side. I am sorry, I forgot a lot of school geometry...
How can I calculate the normal?
I have 4 points (p1-p4) of a plane (with X, Y and Z coordinates). How can I use these coordinates for the "Z-normal compare"?
The universal definition is Ax+By+Cz+D=0, but what is the implementation (algorithm, no 6502 code)?
Assuming a cube that is world axis aligned the normals for the faces are the world axises defined by your rotation matrix, neat huh? =D
Otherwise to recalculate a face normal you simply take the cross product for two vectors in the plane of the desired face, then normalize it. This you NEVER want to do on the c64. |
| | JackAsser
Registered: Jun 2002 Posts: 2014 |
Quote: Assuming a cube that is world axis aligned the normals for the faces are the world axises defined by your rotation matrix, neat huh? =D
Otherwise to recalculate a face normal you simply take the cross product for two vectors in the plane of the desired face, then normalize it. This you NEVER want to do on the c64.
Ok, I can give you a really thourough explanation of this, but please first give me your constraints. What kind of object do you have, how does it move, can the camera move etc. Do you have perspective? Etc... Then I can help you finding the most optimal way for backface culling. |
| | Oswald
Registered: Apr 2002 Posts: 5094 |
I have 4 points (p1-p4) of a plane (with X, Y and Z coordinates). How can I use these coordinates for the "Z-normal compare"?
"4) If you're using the values of the rotation matrix directly to derive surface normals, all you can do is cubes. For other surfaces you need to rotate the normals first and use their rotated Z-values in the compare."
btw, you need some extra trickery to rotate an extra coordinate faster than 2 muls. most probably reusing rotation matrix, and a very symmetric object. |
| | LHS
Registered: Dec 2002 Posts: 66 |
Thanks you for your helps and I am sorry for my incomprehension.
I have read a book with tens pages about 3D transformation with a lot of theory and complex formulas. And then I have read a book with a few pages with 3D simple interpretation like: "you need 3 coordinates X-Y-Z, for rotation around centre use these formulas, huh now we have rotated object, but what must we do with Z axis? - here you are simple formulas for paralel or perspective projection, the variables in formula mean... etc.".
I am not profesional programer and I prefer the second (simple) way of comment. Unfortunately the book includes only wireframe models.
Well, I would like code objects like in this demos (screenshots):
Filled Vectors
Vector Overdose
I have a cube - vertexes with X, Y and Z units, f.e. like this:
p0 20, 20, 20
p1 20,-20,20
p2 -20,-20,20
p3 -20, 20, 20
p4 20, 20, -20
p5 20,-20,-20
p6 -20,-20,-20
p7 -20, 20, -20
I have formulas for transformation(rotation) like this:
newX = someX*sin + someY*cos
newY =...
newZ=... etc etc.
Then I have all 8 vertexes rotated aroud axis X, Y and Z, f.e.
p1 30, 10, -10
p2 ... etc.
I will use paralel projection (discard Z axis, but I have the Z values in memory). All vertexes are every time in visible space.
Now I have a routine for EOR line-drawing and EOR plane filling. The routine takes 4 vertexes. Before I need calculate, if is the plane visible.
Is there a formula how can I check visibility? f.e.
if p0.z + p1.z + p2.z + p3.z > 0
then plane is visible
else plane is invisible
or something like this? |
| | JackAsser
Registered: Jun 2002 Posts: 2014 |
Ok, my explanations will require you to know the basics of linear algebra, something I won't teach you. ;D
How ever, with parallel projection (i.e. without perspective), to backface cull you simply only need to check the rotation angles to directly know if a face is visible or not. Consider the front face, if you rotate around the x-axis 90 degrees or more it'll be invisible. I mean, u KNOW which faces that are visible or not directly. (assuming cube, assuming paralell projection) |
| | Oswald
Registered: Apr 2002 Posts: 5094 |
well, it depends on how you deep you want to crawl into this. honestly for me it took TEN years to CLEARLY understand most concepts used, and still learning. either you give yourslef some time and your vectors will be fast and smooth rotating (=accurate) or you go the fast way and they will be slow and jerky.
if you can understand how 2d -> 3d rotations work, and then the matrix method you are kinda there. but dont forget about signed numbers, fast multiply etc neither.
if you have a working signed multiply routine you can build your routine fast with equations you find, but it will be not the best one can come up on c64. |
| | Oswald
Registered: Apr 2002 Posts: 5094 |
for the fast way here are the magic formuls for rotations:
http://www.siggraph.org/education/materials/HyperGraph/modeling..
back face hiding:
((p1x-p2x)*(p1y-p3y))-((p1y-p2y)*(p1x-p3x))
read my previous posts on this.
perspective projection:
x=(x/z)*n -> build a table with z=(1/(z+d))*n, use your mul routine x=x*table(z), drop lowmost 8 bits from result.
(finding a good 'd' and 'n' are subject to trial and error) |
| | Slammer
Registered: Feb 2004 Posts: 416 |
The JackAsser/Graham method is neat but perhaps I was not the only one who where confused about the explanation of how it works. I guess there is something missing?
I found an alternative explanation instead:
I think you found that the point where the surface goes from hidden to visible is when the surface extended into a plane intersects the eye-point. Now you can draw a 90 degree triangle like the one on the sketch below. Then you use the small cosine relation (Cos A=Adjacent/Hypotenuse - look under Right triangle definitions in http://en.wikipedia.org/wiki/Cosine)
and find that Cos A = D/z and since Cos A is the same as the z point of the surface normal we have that normalZ=D/z when the surface goes from hidden to visible.
|
| | Oswald
Registered: Apr 2002 Posts: 5094 |
now that explains a few things jackie forgot to mention & I was too shy to ask about :) nice one slammer. |
| | Graham Account closed
Registered: Dec 2002 Posts: 990 |
The Z-compare method works for all surfaces where the midpoint stays on a sphere no matter what angles you rotate.
This applies to all surfaces of all platonic/archimedian solids. |
| | Nightlord Account closed
Registered: Jan 2003 Posts: 131 |
what a nice thread this is ...
hmm i guess most of the time the z comparison for normal will be a faster method as opposed to Oswald's method that is based on the cross product of the projected 2d coordinates (i used to use a variant of the cross product method in my vectors too).
But depending on the methods you use to render poligons and do the vertex rotations and the shape you rotate, i think this might change. For instance if you are using a shape where you have to rotate additional vertices that represent the normals, then you might end up paying a higher cost for that as 9 multiplications and 9 additions in the worst case per face
Well my point is not to claim one method better over the other but i just wanted to point out something that I thought might be missed :) so just my 2c.
|
| | LHS
Registered: Dec 2002 Posts: 66 |
JackAsser, Oswald and the rest <<thanks you very much for your hints, now I am going to try code function filled vector and then I will let you know my result
Oswald <<I like your demos, specially I mean VOID or SOILED LEGACY are one the best demos at C64 (I like your combination of high code & high design). When you released your first demos under COMA (btw. your first(?) COMA demo with real multitasking from Flag96 is not on CSDB - why? if you don't have a copy I think I can find it in my archive...), I was active coder too -> I don't know all hard C64 calculation (f.e. Graham's or AEG's vectors), but after 12 years of coding I know C64 limits and I don't contend with 6502 implementation ;-)
Of course I know transformation matrix of 3D vertex, I know a fast signed multiplication routine with bits rotation etc. I have coded a fast dots vector and now I will only code a classic filled vector.
Do you mean is perspective projection necessary for a simple filled vector? I have an implementation of the projection without divine:
if you know max Z of all vertexes then
constP = Zmax - Z(of actual point)
ASL constP (possible several times over)
perspX = constP * X
perspY = constP * Y
but now I am using paraler projection. |
| | JackAsser
Registered: Jun 2002 Posts: 2014 |
Ok people, since I was a bit unclear I've written a little tut:
1) A little bit of matrices
First of all it's essential that you understand what a normal 3x3 matrix is
made up of. Let's consider the unit matrix, i.e. the one that's implicitly used
for a non-transformed space:
|1 0 0|
|0 1 0|
|0 0 1|
What this matrix actually tells us is the X,Y,Z coordinates for the X,Y,Z
unit world axises.
|1 0 0|
|0 1 0|
|0 0 1|
^ ^ ^
| | +- Zw = [0,0,1]
| +--- Yw = [0,1,0]
+----- Xw = [1,0,0]
As you can see, for a normal untransformed spaces it's quite obvious that
the world axises have coords [1,0,0] (the x-axis), [0,1,0] (the y-axis),
[0,0,1] (the z-axis).
Important: Conslusion, each column in the rotation matrix gives us the
coordinates for each of the unit axises in our transformed space, described
in the untransformed space's coordinates.
More generally the rotation matrix:
|Rxx, Ryx, Rzx|
Mr = |Rxy, Ryy, Rzy|
|Rxz, Ryz, Rzz|
^ ^ ^
| | +- Zw = [Rzx, Rzy, Rzz]
| +------ Yw = [Ryx, Ryy, Ryz]
+----------- Xw = [Rxx, Rxy, Rxz]
I.e. the world axises for our rotated space expressed in our current
untransformed space coordinates are:
Xw = [Rxx, Rxy, Rxz]
Yw = [Ryx, Ryy, Ryz]
Zw = [Rzx, Rzy, Rzz]
Ok, enough about rotation matrices and world axises. If you don't get it,
re-read and only move forward until you really get this.
2) Deriving the vertices for the unit cube using the rotation matrix
The coordinates for a unit cube are:
p1 = [ 1, 1, 1 ]
p2 = [ 1, 1, -1 ]
p3 = [ 1, -1, 1 ]
p4 = [ 1, -1, -1 ]
p5 = [-1, 1, 1 ]
p6 = [-1, 1, -1 ]
p7 = [-1, -1, 1 ]
p8 = [-1, -1, -1 ]
By symmetry we quickly se that it can be reduced to:
p1 = [ 1, 1, 1 ]
p2 = [ 1, 1, -1 ]
p3 = [ 1, -1, 1 ]
p4 = [ 1, -1, -1 ]
p5 = -p4
p6 = -p3
p7 = -p2
p8 = -p1
So, we really only need to calculate p1-p4. Let's consider p1 first:
p1 = [1,1,1]
Remeber the unit matrix:
|1 0 0|
|0 1 0|
|0 0 1|
^ ^ ^
| | +- Zw = [0,0,1]
| +--- Yw = [0,1,0]
+----- Xw = [1,0,0]
Xw+Yw+Zw = [1,0,0] + [0,1,0] + [0,0,1] = [1,1,1] = p1
As you see, by simply adding the world axises you get a corner of the unit
cube. It's quite obvious; to get from origo to a corner of a cube you need
to take one step in each dimension.
For p1-p4 we get:
Xw+Yw+Zw = [1,0,0] + [0,1,0] + [0,0,1] = [ 1, 1, 1 ] = p1
Xw+Yw-Zw = [1,0,0] + [0,1,0] - [0,0,1] = [ 1, 1, -1 ] = p2
Xw-Yw+Zw = [1,0,0] - [0,1,0] + [0,0,1] = [ 1, -1, 1 ] = p3
Xw-Yw-Zw = [1,0,0] - [0,1,0] - [0,0,1] = [ 1, -1, -1 ] = p4
Now, in general rotation matrix form:
|Rxx, Ryx, Rzx|
Mr = |Rxy, Ryy, Rzy|
|Rxz, Ryz, Rzz|
^ ^ ^
| | +- Zw = [Rzx, Rzy, Rzz]
| +------ Yw = [Ryx, Ryy, Ryz]
+----------- Xw = [Rxx, Rxy, Rxz]
Hence we get:
Xw+Yw+Zw = [Rxx, Rxy, Rxz] + [Ryx, Ryy, Ryz] + [Rzx, Rzy, Rzz] = [Rxx+Ryx+Rzx, Rxy+Ryy+Rzy, Rxz+Ryz+Rzz] = p1
Xw+Yw-Zw = [Rxx, Rxy, Rxz] + [Ryx, Ryy, Ryz] - [Rzx, Rzy, Rzz] = [Rxx+Ryx-Rzx, Rxy+Ryy-Rzy, Rxz+Ryz-Rzz] = p2
Xw-Yw+Zw = [Rxx, Rxy, Rxz] - [Ryx, Ryy, Ryz] + [Rzx, Rzy, Rzz] = [Rxx-Ryx+Rzx, Rxy-Ryy+Rzy, Rxz-Ryz+Rzz] = p3
Xw-Yw-Zw = [Rxx, Rxy, Rxz] - [Ryx, Ryy, Ryz] - [Rzx, Rzy, Rzz] = [Rxx-Ryx-Rzx, Rxy-Ryy-Rzy, Rxz-Ryz-Rzz] = p4
So, we have now stated that given a general rotation matrix you can derive all eight vertices of a cube by simple additions. (Good for a C64!!)
3) Deriving the normals of the faces of the unit cube using the rotatio matrix:
For filled vectors we must do backface culling, and the approach I'll give will use the face normals hence we need to derive them.
The coordinates for the 6 face normals are:
n1 = [ 1, 0, 0 ]
n2 = [ -1, 0, 0 ]
n3 = [ 0, 1, 0 ]
n4 = [ 0, -1, 0 ]
n5 = [ 0, 0, 1 ]
n6 = [ 0, 0, -1 ]
By symmetry:
n1 = [ 1, 0, 0 ]
n2 = -n1
n3 = [ 0, 1, 0 ]
n4 = -n3
n5 = [ 0, 0, 1 ]
n6 = -n5
Remeber the unit matrix:
|1 0 0|
|0 1 0|
|0 0 1|
^ ^ ^
| | +- Zw = [0,0,1]
| +--- Yw = [0,1,0]
+----- Xw = [1,0,0]
As you can see:
Xw = [1,0,0] = n1
Yw = [0,1,0] = n3
Zw = [0,0,1] = n5
Now, in general rotation matrix form:
|Rxx, Ryx, Rzx|
Mr = |Rxy, Ryy, Rzy|
|Rxz, Ryz, Rzz|
^ ^ ^
| | +- Zw = [Rzx, Rzy, Rzz]
| +------ Yw = [Ryx, Ryy, Ryz]
+----------- Xw = [Rxx, Rxy, Rxz]
Hence we get:
Xw = [Rxx, Rxy, Rxz] = n1
Yw = [Ryx, Ryy, Ryz] = n3
Zw = [Rzx, Rzy, Rzz] = n5
To sum 2) and 3) up, the coordinates for all eight vertices and all six normals expressed in rotational matrix terms are:
Xw+Yw+Zw = [Rxx, Rxy, Rxz] + [Ryx, Ryy, Ryz] + [Rzx, Rzy, Rzz] = [Rxx+Ryx+Rzx, Rxy+Ryy+Rzy, Rxz+Ryz+Rzz] = p1
Xw+Yw-Zw = [Rxx, Rxy, Rxz] + [Ryx, Ryy, Ryz] - [Rzx, Rzy, Rzz] = [Rxx+Ryx-Rzx, Rxy+Ryy-Rzy, Rxz+Ryz-Rzz] = p2
Xw-Yw+Zw = [Rxx, Rxy, Rxz] - [Ryx, Ryy, Ryz] + [Rzx, Rzy, Rzz] = [Rxx-Ryx+Rzx, Rxy-Ryy+Rzy, Rxz-Ryz+Rzz] = p3
Xw-Yw-Zw = [Rxx, Rxy, Rxz] - [Ryx, Ryy, Ryz] - [Rzx, Rzy, Rzz] = [Rxx-Ryx-Rzx, Rxy-Ryy-Rzy, Rxz-Ryz-Rzz] = p4
p5=-p4
p6=-p3
p7=-p2
p8=-p1
Xw = [Rxx, Rxy, Rxz] = n1
n2 = -n1
Yw = [Ryx, Ryy, Ryz] = n3
n4 = -n3
Zw = [Rzx, Rzy, Rzz] = n5
n6 = -n5
4) Back face culling by checking which side the eye is of a plane
First consider the plane equation:
A*x+B*y+C*z+D = 0
[A,B,C] = plane normal
[x,y,z] = reference point to test
D = distance from origo to the plane expressed in negative normal lengths.
If [x,y,z] is chosen to be exactly on the plane the equation will be =0.
If [x,y,z] is chosen to be below the plane, i.e. on the anti-normal side, the equation will be <0.
If [x,y,z] is chosen to be above the plane, i.e. on the normal side, the equation will be >0.
Consider one of the faces of the unit cube, for example the face with a normal n1.
n1 = [1,0,0] = [A,B,C]
D = -1 since the distance negative distance from origo to the unit cube's faces are exactly one normal in length.
1*x + 0*y + 0*z - 1 = 0
If we chose an [x,y,z] that should lie in the plane, for example [1,0,0] we get:
1*1 + 0*0 + 0*0 - 1 = 1-1 = 0
If we chose an [x,y,z] that lies below the plane, for example [0,0,0] we get:
1*0 + 0*0 + 0*0 - 1 = 0-1 = -1
If we chose an [x,y,z] that lies above the plane, for example [10,0,0] we get:
1*10 + 0*0 + 0*0 - 1 = 10-1 = 9
As you can see, the experimental values coincide with what we stated above.
Now let's consider how to use this for backface culling:
If you eye is on the normal side of a plane we consider the plane visible, i.e. if the result of Ax+By+Cz+D > 0 the plane is considered visible.
More over, let's assume the object rotated around origo and that the eye is fixed at a distance say [0,0,-3] (typical for c64 vectors) we get:
A*0 + B*0 + C*-3 + D > 0
I.e. to determine if a plane A,B,C,D is visible, simply calculate A*0+B*0+C*-3+D and check if it's positive. Or to simplify: C*-3+D > 0.
Now, as I stated before, for the unit cube the negative distance to all faces from origo is -1. I.e. D=-1 for all planes of the unit cube in origo. This reduced our check to:
C*-3-1 > 0
Shuffle around:
C > 1/-3
Let's call 1/-3 for e. e = 1 / -distance to object (still assuming unit cube where D=-1 for all planes).
5) Combine 3) and 4) to get useful results for a c64 vector:
We've stated that D=-1 for all 6 planes of the unit cube.
We've stated that the normal vectors for all 6 planes of the unit cube expressed in general rotation matrix form are:
Xw = [Rxx, Rxy, Rxz] = n1
n2 = -n1
Yw = [Ryx, Ryy, Ryz] = n3
n4 = -n3
Zw = [Rzx, Rzy, Rzz] = n5
n6 = -n5
We've fixed the eye position at [0,0,-3] giving us an e-value of e=1/-3.
We've stated that if C>e then the plane is visible.
We've stated that [A,B,C] is the coordinats of a plane normal.
I.e. to determine if n1 is visible:
Check if: Rxz > e
For all faces:
n1: Rxz > e
n2: -n1 > e = -Rxz > e = Rxz <= e
n3: Ryz > e
n4: -n1 > e = -Ryz > e = Ryz <= e
n5: Rzz > e
n6: -n1 > e = -Rzz > e = Rzz <= e
6) Conclusion
We've shown that giving the rotational matrix we can derive all 8 vertices of the unit cube by simple additions.
We've further shown that we can also derive all 6 face normals by simply extract the world axises.
We've shown that assuming a fixed eye position at [0,0,-z] we can simply compare the z-component of a face normal with a constant (e).
We've shown how to calculate e properly.
If you wonder how to calculate a rotational matrix quickly on the C64 I recommend you read Krill's 3d-math tutorials.
Have fun! |
| | Cruzer
Registered: Dec 2001 Posts: 1048 |
Doing stuff like this in realtime on C64 in a demo where you don't need interactivity and therefore can predict everything is pretty stupid, since it can be precalculated and packed down to almost nothing.
All you need to do is calculate the initial visibility state of each face, and then make a table for each face for the number of frames before it switches state. E.g. if you have a cube with 6 faces, where each face on average changes state 20 times = 120 bytes, +6 for the initial states. And it's fast to look up too.
|
| | Oswald
Registered: Apr 2002 Posts: 5094 |
demos are about showing off. what are you showing off with an animation? not much. |
| | Danzig
Registered: Jun 2002 Posts: 440 |
@oswald: hm, imho "glenz each frame" shows off :D |
| | Oswald
Registered: Apr 2002 Posts: 5094 |
danzig, imho stamp sized, every 2nd line, semi animations are not impressive. there are other routines by cruzer which I like, but not this one. anyways tastes are different I prefer fullscreen and realtime instead of small 50fps semi animations. |
| | JackAsser
Registered: Jun 2002 Posts: 2014 |
Quote: Doing stuff like this in realtime on C64 in a demo where you don't need interactivity and therefore can predict everything is pretty stupid, since it can be precalculated and packed down to almost nothing.
All you need to do is calculate the initial visibility state of each face, and then make a table for each face for the number of frames before it switches state. E.g. if you have a cube with 6 faces, where each face on average changes state 20 times = 120 bytes, +6 for the initial states. And it's fast to look up too.
You mean just "animate" the hidden surface states or animate all coords? Because if you only animate the surfaces states and calculate the rest, then a matrix z-cmp is still faster... ;D But I guess you meant to animate everything. |
| | Nightlord Account closed
Registered: Jan 2003 Posts: 131 |
cruzer: no matter how you approach it i do not think doing realtime vectors in C64 is stupid dude :) |
| | Cruzer
Registered: Dec 2001 Posts: 1048 |
Oswald: Showing off doesn't count in my book if it produces no visible difference on the screen. If you wanna make something that couldn't be done as an "animation" then cool, but if it's a vector cube running for 256 frames I think it's stupid to do coord calculation and especially hidden face status in realtime.
JackAsser: I was actually only talking about hidden face status, although I usually precalculate everything since I prefer something that is smooth and runs for a short time rather than the opposite, but that's another story. Even if I was to do the coord calculations in realtime, I would assume it would still be faster to precalc the hidden states, even though I must admit I haven't researched it much, and I don't know what matrix z-cmp means. But are you sure it's faster than this?
ldx frameLo
!: cpx visibilityTable0
bne !+
lda faceVisible+0
eor #1
sta faceVisible+0
inc !- +1
!: cpx visibilityTable1
bne !+
lda faceVisible+1
eor #1
sta faceVisible+1
inc !- +1
!: cpx visibilityTable2
bne !+
... This routine would work even if the effect is longer than 256 frames, as long as each face maximum has the same visibility status for 256 consecutive frames. It takes 7 cycles/face when no change occurs, and 20 when it changes state. Including the initial ldx I get this to 45 cycles when there's no change, and when a face switches, which probably mostly happens one at a time, it would be 58 cycles total. Less than a rasterline - can you beat that?
It could actually be even faster if the status was stored as bits in one byte rather than individual bytes, but then the precalced table would have to be about twice as long, and it would probably also be slower for each line to figure out whether it needs to be drawn and in which color.
|
|