tags:

views:

226

answers:

2

How to create the transformation matrix (4x4) that transforms a cylinder (of height 1 and diameter 1) into a cone that represents my spotlight (position, direction and cutoff angle) ?

--edit--
In other words: how to draw the cone that represents my spotlight by drawing a cylinder through a suitable transformation matrix.

--edit2--
The following (pseudo)code gives me the expected result:

PushMatrix();
LoadIdentity();
Perspective(lightCutoffAngle * 2, 1, 0.001, 10000); // fov, aspect, near, far
LookAt(lightPos.x,lightPos.y,lightPos.z, lightDir.x,lightDir.y,lightDir.z, 0,0,1);
Matrix44 mat = GetModelViewMatrix();
mat.Invert();
PopMatrix();
MultMatrix(mat);
DrawCone(1,1); // diameter, height

HIH

A: 

I do beleave that you want a matrix something like

x/y 0   0  0
 0  y   0  0
 0  0  z/y 0
 0  0   0  1

or possibly

x(1-y) 0   0    0
  0    1   0    0
  0    0 z(1-y) 0
  0    0   0    1

If you cone is a circle centred at the origin, lying on the z-x axis that has been extruded 1 unit along the y-axis. One of these matrices should work, as the points of the cone move further up the y axis, the more you want to them to move towards the y-axis.

Hopefully this should sort you out, or at least give you a good start... now to rest my head.

UPDATE

As pointed out in the comments, this want work. I think I half jumped the gun. If you replace the x ans z with 1, then multiply the matrix by your vector. you would get something like

x = x/y  or x(1-y)
y =  y
z = z/y  or z(1-y)

UPDATE

To take into account the angle of light, we will scale the radius of our cone but keep it unit length. if we have our angle of light L (this being from its centre point, not edge to edge) we can say that the radius our cone needs to be is tan^-1(L)

so if we factor that in, our final maths should be something like

x = tan^-1(L) * [ x/y  or x(1-y) ]
y =  y
z = tan^-1(L) * [ z/y  or z(1-y) ]
thecoshman
That won't work, because you can't multiply x and y with z this way.
SigTerm
Thanks for your response, however I wondering how to take the spotlight cutoff angle in account.
Soubok
You will need to either scale the diameter of the cone first so that the resultant angle is correct, or try to factor the angle in to the matrix. It is possible, just very hard to think about just in your head.
thecoshman
Dude, this is a normal scaling matrix. Cylinder will become squished cylinder if you use this one, but will not become a cone, no matter how you calculate scaling components. Build OpenGL/D3D app with cylinder and see it yourself. You can't divide x by z or y or multiply x by z or y with matrix and without using w component.
SigTerm
Just to be clear, this is not a matrix that you can set as model/view or projection. Those matrices are 'static'. Using a vertex shader would allow you 'modulate' the geometry of the cylinder. My method implies you take an 'array' of points, and apply this logic to them all, one at a time. And by tan^-1(L) I mean inverse tan, not some root of tan(L)
thecoshman
A: 

You don't normally transform cylinder into the cone using matrices. This is because it involves scaling of 2 components where scale factor is dependent on the 3rd component.

I think you can build matrix like that by building "look at" matrix (gluLookAt or D3DXMatrxiLookAtLH) and multiplying it with perspective matrix (gluPerspective or D3DXMatrixPerspectiveFovLH), but I seriously doubt you will be able to render that cylinder with either OpenGL or D3D. This is because in order for projection to work 3D rendering uses 4th vector component - W which is calculated by multiplying vectors with projection matrix. W component is typically hidden, and available only through shaders. Messing with this component normally screws up any geometry, and you can't transform cylinder into cone without using w component. I.e. if you transform cylinder into cone, you will have to use W, this will screw up projection transform.

I suggest to build cylinder normally - from vertices. This isn't hard in both D3D and OpenGL.

If you really want to transform cylinder into cone, writing vertex shader for transforming cylinder will be easier, although making sure all normals are all right might be a problem.

If you want to know which objects hit light cone, use math and collision detection. This isn't hard.

If you want to render objects visible within light cone, make additional render target (or framebuffer), viewport or whatever, and render objects visible from light's point of view.

About light cutoff angle.

Given point P, light position L, and light direction LDir, and cutoff angle you can easily check if P is within light cone. To do that, you'll need cosine of either full or half of cutoff angle (depends on whether cutoff angle is calculated relative to light direction, or determines width of the cone). Make vector PDir = P - L, normalize PDir, and calculate dot product between normalized PDir and normalized LDir, this will give cosine of angle between light direction at point P. IF cosine (between PDir and Ldir) is larger cosine of light cone, then point is within light cone.

SigTerm
You can do this. You are scaling x and z with respect to y. You don't need to touch W
thecoshman
I will use vertex shader to transform my cylinder into a cone, but I don't know how to setup the transformation matrix that will transform the vertexes of the cylinder into a cone that fit the spotlight cone.
Soubok
This is partly my point, there is not need to start using a vertex shader when you can just apply a matrix to your set of points that make up the cone. Either way you need a matrix to transform the cylinder into a cone, or have the geometry for a cone in the first place.
thecoshman
@thecoshmanNo, you can't do that. You can scale all vector components by fixed factor, you can add all 3 components together, but you can't multiply vectors x and y by z component of same vector using matrix and without using 4th component. This isn't an affine transform. If you disagree, give me a matrix that can do that.
SigTerm
Not such a matrix, but you can still scale the cylinder in such a away as to turn it into a cone.
thecoshman
@thecoshmanYes, you can process cylinder and make it a into a cone. But you can't do that with a matrix (which is what author requested). You'll need vertex shader, or you'll have to suffer some performance loss. also it is easy enough to build cone from triangles.
SigTerm