Advertisement

calcaulating the "right" vector of a plane

Started by December 10, 2002 04:39 PM
5 comments, last by Crispy 22 years, 2 months ago
Hi, I'm implementing lightmapping in my engine and so far I'v got the thing up and running, everything up to the point of actually mapping th lightmap which seems to be done incorrectly. Since I'm doing this on a heightmap, there's a lot of small faces involved and I find myself mathematically stumped. I'm not sure, but it seems that the fault is in texture coordinate calculation. I'll post some code - perhaps it'll make more sense:
      
//p is the polygon which is being lit

//h is the horizontal/right vector

//v is the vertical/up vector

//pSource is the light's origin

//pRadius is the radius of the light's volume


   float distance = fabs(p.DistanceToPlane(pSource));
   float scale = 1.0f / (pRadius + distance * 2.5);

   TVector3f h = p.VecHorizontal;
   TVector3f v = p.VecVertical;

  //find the intersection point of the light source on the plane; 

  //the second argument ought to be the light's direction.

  //Does this overlap with the polygon's normal?

  TVector3f pNearest = p.RayIntersection(pSource, p.Normal());

  /// ... ///


  //find the nearest vertex

  TVector3f VerNear = *p.Corners[2] - pNearest;
  /calculate the texture coords
  glTexCoord2f(VecDotProduct(&VerNear, &(h * scale)) + .5f,
    VecDotProduct(&VerNear, &(v * scale)) + .5f);
  glVertex3fv(*p.Corners[2]);
  ...
  //similar for all of the vertexes

   
The problem is that, when output, the texture coordinates go well out of normal boundaries (for those who don't know, tex coords in opengl are clamped into [0; 1], so basically when I draw the entire lightmap, most of the small triangles that make it up, have textures mapped on them incorrectly. I suspect the problem is in calculating the h and v vectors. Some more code...
  
 //for any given plane

 VecNormal = VecNormalize(VecCrossProduct(pVec3 - pVec1, pVec2 - pVec1));

 VecHorizontal = VecNormalize(VecCrossProduct(VecNormal, pVecUp)); //equals h in the previous code bit

 VecVertical = VecNormalize(VecCrossProduct(VecHorizontal, VecNormal)); //equals v

      
For some reason pVecUp = (1; 0; 0) as I found it to be in a sample project. I can't understand why - setting it to (0; 1; 0) causes the program to crash. Some help would be well appreciated, Crispy edit: sth weird... [edited by - crispy on December 10, 2002 5:45:38 PM]
"Literally, it means that Bob is everything you can think of, but not dead; i.e., Bob is a purple-spotted, yellow-striped bumblebee/dragon/pterodactyl hybrid with a voracious addiction to Twix candy bars, but not dead."- kSquared
It''s not quite correct, you need to project the ''up'' vector onto the plane:


  Vector3 project_onto(const Vector3& v,const Vector3& normal){  return v - ( normal * Dot(v,normal) );}Vector3 get_plane_vec(const Vector3& normal){  Vector3 v = Vector3(1,0,0);  if( LargestAxis(normal) == 0)    v = Vector3(0,1,0);  return Normalize( project_onto(v,normal) );}  


Call get_plane_vec with the normal. This will give you one normalized vector on the plane (that can be, say, h). The other is calculated as (normal cross h).

However, I''m kind of stumped with exactly what you are trying to do with the other code.
Advertisement
Ok, this is the place that''s actually the most confusing for me.

1) Does LargestAxis() return max(max(v.x, v.y), v.z); where return codes for v.x, v.y and v.z are 0, 1, 2, respectively?
2) What if the normal = (0, -1, 0) in get_plane_vec() and v = (0, 1, 0)? The dot product is then (0, 0, 0) and Normalize() crashes trying to return sqrt(0)! What should I do in that case?
3) Could you possibly elaborate on this bit of code a little:


     TVector3f v = TVector3f(1, 0, 0);   if(LargestAxis(pNormal) == 0)     v = TVector3f(0, 1, 0);  


What is v in this case? Why are you presuming it to be (1, 0, 0) and possibly (0, 1, 0), but never (0, 0, 1) ?



Regarding the other piece of code (which is, in fact, placed in a "chronologically" incorrect order - my bad), that''s where I''m calculating the texture coordinates. It seems kind of logical, but is obviously wrong. I''ll try and explain it a little (to the best of my abilities):


     //first calculate the distance of the light source to the plane.   //This is used to determine whether the light should be   //applied to this specific polygon, and if so, how "bright" it needs to be   float distance = fabs(p.DistanceToPlane(pSource));      //depending on the distance of the light source from the polygon,   //the lighmap is either larger or smaller - calculate the   //scale value. When the light source is on the plane, the lighmap   //is scaled by 1   float scale = 1.0f / (pRadius + distance * 2.5);      //h and v are shorthand for the values calculated in the other   //piece of code   TVector3f h = p.VecHorizontal;      TVector3f v = p.VecVertical;     //find the intersection point of the light source on the plane;      //the second argument should to be the light''s direction.     //I''m not at all sure about the second argument, though...   TVector3f pNearest = p.RayIntersection(pSource, p.Normal());     /// ... ///     //next we find the nearest vertex to the intersection point   TVector3f VerNear = *p.Corners[2] - pNearest;     //calculate the texture coords - this I don''t really understand...   glTexCoord2f(VecDotProduct(&VerNear, &(h * scale)) + .5f,    VecDotProduct(&VerNear, &(v * scale)) + .5f);     //draw the vertex   glVertex3fv(*p.Corners[2]);  


Crispy
"Literally, it means that Bob is everything you can think of, but not dead; i.e., Bob is a purple-spotted, yellow-striped bumblebee/dragon/pterodactyl hybrid with a voracious addiction to Twix candy bars, but not dead."- kSquared
The idea of

  TVector3f v = TVector3f(1, 0, 0);     if(LargestAxis(pNormal) == 0)         v = TVector3f(0, 1, 0);   


This piece of code is to avoid precisely problem 2).

My definition of LargestAxis:


  int LargestAxis(const Vector3& v){    int axis = 0;    if( fabs(v.c[axis]) < fabs(v.c[1]) ) axis = 1;    if( fabs(v.c[axis]) < fabs(v.c[2]) ) axis = 2;    return axis;}  


(which is pretty much as you said)

The exact value of v is unimportant, v is basically just a random vector which we can project onto the plane defined by normal.

Ok, the other bit of code does make sense, I just didn''t get why you were only calculating the lighting once, do you have one lightmap texture element per triangle or something?

"do you have one lightmap texture element per triangle or something?"

I''m afraid I don''t quite follow.

I have a whole bunch of polys (triangles) that form a landscape over which the light source is moving. As it comes close enough I need to calculate the texture coordinates for each vertex in the triangles based on the vertex position, and the horizontal and verical vecors, but I''m still getting texture coordinate values > 1 which effectively indicates that they''re wrong...

Crispy
"Literally, it means that Bob is everything you can think of, but not dead; i.e., Bob is a purple-spotted, yellow-striped bumblebee/dragon/pterodactyl hybrid with a voracious addiction to Twix candy bars, but not dead."- kSquared
Oh right, so you have a single lightmap for the entire terrain yes? In that case why not just use an extremely simple mapping using just the x and y coordinates of the points?

Ignore the method I was proposing, that is for calculating coordinates for texture-per-poly. Your original method was basically a straight mapping with some weird warping, where did you get the idea for it? Maybe it would help if I could see where your trying to get to.
Advertisement
Ok, I finally put my brains into it and did it the easy way - it just needs scaling now. Here''s a screenshot (I''m still having problems with blending - just know that the lightmap is mapped correctly now):



However, the way I''m doing it now is very heightmap- friendly and thereby heightmap-specific - I won''t be able to light any other faces in the world using it - something I''m not sure if it''s trivial or not, yet...

http://romka.demonews.com/opengl/demos/texture_eng.htm

Look for the "Lightmap Demo". It includes the method I was trying to implement (source and exe available).

Crispy
"Literally, it means that Bob is everything you can think of, but not dead; i.e., Bob is a purple-spotted, yellow-striped bumblebee/dragon/pterodactyl hybrid with a voracious addiction to Twix candy bars, but not dead."- kSquared

This topic is closed to new replies.

Advertisement