I want to do frustum culling for my engine :)
On this site seems to be nice example how to do this, but there is one thing I don't get:
if ( D3DXPlaneDotCoord( &m_frustum[i], pPosition ) + radius < 0 )
{
// Outside the frustum, reject it!
return FALSE;
}
Is why there is a radius for?
Or maybe what is dependence between dot product and distance from plane?
Cause with my actual knowledge I would calculate it like that:
calculate dot product of plane. And as vectors are normalized dot product is equal to cosinus of angle between vectors. So it can return values between -1 and 1.(Thats why I dont understand why radius is added). And if cos > 0 means that angle is between 0 and 90 degrees. So center point is in front of plane. Then I would use equation for distance of point from plane. And check if that distance is higer than radius of sphere. But this guy have this in that one equation. What magic is behid that?
Ok I see where is my mistake dot procuct is not equal to cos of angle, but cos of angle and length of vector P( describing position of center of sphere). So what exactly is cos*|P| = ?
http://tinypic.com/r/2vxrpkw/5( no rep for images )
Probably answered own question brb( wikipedia ) :)
Yeah exactly. My P is not P desribing point in coordinate system, but It's P - known point of plane. So it's vector between point and know point of plane. Everything seems legit. Thanks for help :P It's nicely explained here: www.songho.ca/math/plane/plane.html
This can be seen as a projection of the pPosition along the plane's normal.
If the length of this projection plus the plane's D component minus the sphere radius is less than zero means the sphere is behind.
Related
My maths is very rusty and I've never been great at imagining things past 2 dimensional space.
My question is this. Given a point of origin (p1), how can I calculate a new point (p2) which is a known distance (100 units) based on two angles (Yaw and Pitch).
What I know is the 3D dimensions for a virtual room, the point of origin within that room and the Yaw and Pitch (I've called this horizontal angle and vertical angle). To put it in to English, I would like to fire a line of 100 units within this room from that point of origin based on it's Yaw and Pitch values and get the point at the end of that line.
I would like this point in space because I would like to define my line using p1 and p2. I want to eventually go on to use this line in a line/plane intersection test. The planes are also known within the virtual room. I only mention this because with my lack of mathematical knowledge, someone may suggest I look at some other method.
If you just want to define a line, you don't need the second point. The line's direction vector can be calculated directly as:
/ cos pitch * sin yaw \
dir = | sin pitch |
\ cos pitch * cos yaw /
This assumes that the y-axis points upwards. A zero yaw points in positive z-axis. Increasing yaw will turn the direction towards the positive x-axis. These definitions are all interchangeable.
The line is then:
x = startPoint + t * dir | t \in R
If you really want the second point, just use 100 as t and calculate x.
I'd need a formula to calculate 3D position and direction or orientation of a camera in a following situation:
Camera starting position is looking directly into center of the Earth. Green line goes straight up to the sky
Position that camera needs to move to is looking like this
Starting position probably shouldn't matter, but the question is:
How to calculate camera position and direction given 3D coordinates of any point on the globe. In the camera final position, the distance from Earth is always fixed. From desired camera point of view, the chosen point should appear at the rightmost point of a globe.
I think what you want for camera position is a point on the intersection of a plane parallel to the tangent plane at the location, but somewhat further from the Center, and a sphere representing the fixed distance the camera should be from the center. The intersection will be a circle, so there are infinitely many camera positions that work.
Camera direction will be 1/2 determined by the location and 1/2 determined by how much earth you want in the picture.
Suppose (0,0,0) is the center of the earth, Re is the radius of the earth, and (a,b,c) is the location on the earth you want to look at. If it's in terms of latitude and longitude you should convert to Cartesian coordinates which is straightforward. Your camera should be on a plane perpendicular to the vector (a,b,c) and at a height kRe above the earth where k>1 is some number you can adjust. The equation for the plane is then ax+by+cz=d where d = kRe^2. Note that the plane passes through the point (ka,kb,kc) in space, which is what we wanted.
Since you want the camera to be at a certain height above the earth, say h*Re where 1 < k < h, you need to find points on ax+by+cz=d for which x^2+y^2+z^2 = h^2*Re^2. So we need the intersection of the plane and a sphere. It will be easier to manage if we have a coordinate system on the plane, which we get from an orthonormal system which includes (a,b,c). A good candidate for the second vector in the orthonormal system is the projection of the z-axis (polar axis, I assume). Projecting (0,0,1) onto (a,b,c),
proj_(a,b,c)(0,0,1) = (a,b,c).(0,0,1)/|(a,b,c)|^2 (a,b,c)
= c/Re^2 (a,b,c)
Then the "horizontal component" of (0,0,1) is
u = proj_Plane(0,0,1) = (0,0,1) - c/Re^2 (a,b,c)
= (-ac/Re^2,-bc/Re^2,1-c^2/Re^2)
You can normalize the vector to length 1 if you wish but there's no need. However, you do need to calculate and store the square of the length of the vector, namely
|u|^2 = ((ac)^2 + (bc)^2 + (Re^2-c^2))/Re^4
We could complicate this further by taking the cross product of (0,0,1) and the previous vector to get the third vector in the orthonormal system, then obtain a parametric equation for the intersection of the plane and sphere on which the camera lies, but if you just want the simplest answer we won't do that.
Now we need to solve for t such that
|(ka,kb,kc)+t(-ac/Re^2,-bc/Re^2,1-c^2/Re^2)|^2 = h^2 Re^2
|(ka,kb,kc)|^2 + 2t (a,b,c).u + t^2 |u|^2 = h^2 Re^2
Since (a,b,c) and u are perpendicular, the middle term drops out, and you have
t^2 = (h^2 Re^2 - k^2 Re^2)/|u|^2.
Substituting that value of t into
(ka,kb,kc)+t(-ac/Re^2,-bc/Re^2,1-c^2/Re^2)
gives the position of the camera in space.
As for direction, you'll have to experiment with that a bit. Some vector that looks like
(a,b,c) + s(-ac/Re^2,-bc/Re^2,1-c^2/Re^2)
should work. It's hard to say a priori because it depends on the camera magnification, width of the view screen, etc. I'm not sure offhand whether you'll need positive or negative values for s. You may also need to rotate the camera viewport, possibly by 90 degrees, I'm not sure.
If this doesn't work out, it's possible I made an error. Let me know how it works out and I'll check.
Alright, so I'm working on a ray tracer using phong shading. So far, everything is good. I've cast rays that have hit the spheres in my scene, applied phong shading to them, and it looks normal.
Now, I'm calculating shadow rays, which is shooting a ray from the point of intersection from the primary ray to the light source, and seeing if it hits any objects on the way. If it does, then it's in a shadow.
However, when computing whether the shadow ray hits any spheres, there seems to be an error with my discriminant that is calculated, which is odd since it's been correct so far for primary rays.
Here's the setup:
// Origin of ray (x,y,z)
origin: -1.9865333, 1.0925934, -9.8653316
// Direction of ray (x,y,z), already normalized
ray: -0.99069530, -0.13507602, -0.016648887
// Center of sphere (x,y,z)
cCenter: 1.0, 1.0, -10.0
// Radius of the sphere (x,y,z)
cRadius: 1.0
, and here's the code for finding the discriminant:
// A = d DOT d
float a = dotProd(ray, ray);
// B = 2 * (o - c) DOT d
Point temp (2.0*(origin.getX() - cCenter.getX()), 2.0*(origin.getY() - cCenter.getY()), 2.0*(origin.getZ() - cCenter.getZ()));
float b = dotProd(temp, ray);
// C = (o - c) DOT (o - c) - r^2
temp.setAll(origin.getX() - cCenter.getX(), origin.getY() - cCenter.getY(), origin.getZ() - cCenter.getZ());
float c = dotProd(temp, temp);
c -= (cRadius * cRadius);
// Find the discriminant (B^2 - 4AC)
float discrim = (b*b) - 4*a*c;
Clearly, the ray is pointing away from the sphere, yet the discriminant here is positive (2.88) indicating that the ray is hitting the sphere. And this code works fine for primary rays as their discriminants must be correct, yet not for these secondary shadow rays.
Am I missing something here?
So short answer for my problem, in case someone finds this and has the same problem:
The discriminant tells you whether a hit exists for a line (and not for a ray, like I thought). If it's positive, then it has detected a hit somewhere on the line.
So, when calculating the t-value(s) for the ray, check to see if they're negative. If they are, then it's a hit BEHIND the point of origin of the ray (ie. the opposite direction of the ray), so discard it. Only keep the positive values, as they're hits in the direction of the ray.
Even shorter answer: discard negative t-values.
Credit goes to woodchips for making me realize this.
The issue is, the trick to finding the intersection of a line and a sphere requires the solution of a quadratic equation. Such an equation has one of three possibilities as a solution - there are 0, 1, or 2 real solutions to that equation. The sign of the discriminant tells us how many real solutions there are (as well as helping us to solve for those solutions.)
If a unique solution exists, then the line just kisses the surface of the sphere. This happens when the discriminant is exactly zero.
If two solutions exist, then the line passes through the sphere, hitting the surface in TWO distinct points.
If no real solution exists (the case where the discriminant is negative) then the line lies too far away from the sphere to touch it at all.
Having discovered if the line ever goes near the sphere or not, only then do we worry if the ray hits it. For this, we can look at how we define the ray. A ray is a half line, extending to infinity in only one direction. So we look to see where on the line the intersection points happen. Only if the intersection happens on the half of the line that we care about is there a RAY-sphere intersection.
The point is, computation of the discriminant (and simply testing its sign) tells you ONLY about what the line does, not about where an intersection occurs along that line.
Of course, a careful reading of the link you yourself provided would have told you all of this.
Pretty sure "o-c" should be "c-o"
You're shooting a ray off in the wrong direction and finding the intersection on the other side of the sphere.
I've been looking at XNA's Barycentric method and the descriptions I find online are pretty opaque to me. An example would be nice. Just an explanation in English would be great... what is the purpose and how could it be used?
From Wikipedia:
In geometry, the barycentric coordinate system is a coordinate system in which the location of a point is specified as the center of mass, or barycenter, of masses placed at the vertices of a simplex (a triangle, tetrahedron, etc).
They are used, I believe, for raytracing in game development.
When a ray intersects a triangle in a normal mesh, you just record it as either a hit or a miss. But if you want to implement a subsurf modifier (image below), which makes meshes much smoother, you will need the distance the ray hit from the center of the triangle (which is much easier to work with in Barycentric coordinates).
Subsurf modifiers are not that hard to visualize:
The cube is the original shape, and the smooth mesh inside is the "subsurfed" cube, I think with a recursion depth of three or four.
Actually, that might not be correct. Don't take my exact word for it, but I do know that they are used for texture mapping on geometric shapes.
Here's a little set of slides you can look at: http://www8.cs.umu.se/kurser/TDBC07/HT04/handouts/HO-lecture11.pdf
In practice the barycentric coordinates of a point P in respect of a triangle ABC are just its weights (u,v,w) according to the triangle's vertices, such that P = u*A + v*B + w*C. If the point lies within the triangle, you got u,v,w in [0,1] and u+v+w = 1.
They are used for any task involving knowledge of a point's location in respect to the vertices of a triangle, like e.g. interpolation of attributes across a triangle. For example in raytracing you got a hitpoint inside the triangle. When you want to know that point's normal or other attributes, you compute its barycentric coordinates within the triangle. Then you can use these weights to sum up the attributes of the triangle's vertices and you got the interpolated attribute.
To compute a point P's barycentric coordinates (u,v,w) within a triangle ABC you can use:
u = [PBC] / [ABC]
v = [APC] / [ABC]
w = [ABP] / [ABC]
where [ABC] denotes the area of the triangle ABC.
Hey I can't figure out what the equation to find the new angle of travel of an object is after reflecting off of a wall.... The angle of travel is also based off the unit circle so 0degrees would be traveling right, 180 traveling left, 270 down, etc.
Just making the angle negative doesn't work either, any tips?
I think this is what you're looking for. I added in the angle of the wall, even if you didn't need it.
reflectionAngle = wallAngle + ((wallAngle + 180) - (incidenceAngle + 180))
If the wall is just vertical, its angle would be 90 degrees.
I hope this helps, and good luck!
EDIT: As a more simplified method, posted by Casey below:
reflectionAngle = 2*wallAngle - incidenceAngle
You have to change the angle relative to the wall coordinate system (t, n) and then transform back to (x, y) coordinates. The wall coordinate n is perpendicular to the wall; the direction t is created by taking the cross-product of the t-vector into the z-direction.
The algorithm would say that the incoming (v_t, v_n) velocity are changed as follows:
perpendicular component v_n changes sign.
tangential component v_t is unchanged, assuming no friction.
Once you have those, transform back to (x, y) coordinates.
It's easy if you think in terms of 2D vectors.
It would be
outAngle = 360 - inAngle