Original Post
Hi Guys, I'm trying to implement lightmapping in my application which is all going fine. I have implemented planar mapping and can successfully create lightmaps for each of my polygons. However, there is one downside - in all the articles and tutorials i've come accross, each lightmap is generated at a fixed resolution i.e. 16x16 or 32x32 etc. However, the nature of the polys in my scene means that some are much larger than others. I was wondering if anyone could point me in the direction of creating lightmaps at a resolution based on the size of the polygon? The method I am using is below: Any help or comments would be really appreciated, Kind Regards, Chris
public static void Generate(PolyFace face, Vector3[] polygon, Level level, bool smoothMap, bool fillInvalidLumels)
{
Vector3 pointonplane = polygon[0];
Vector3 poly_normal = Vector3.CalculateNormal(polygon[0], polygon[1], polygon[2]);
face.LightMap = new Lightmap();
int flag;
if (Math.Abs(poly_normal.x) > Math.Abs(poly_normal.y) &&
Math.Abs(poly_normal.x) > Math.Abs(poly_normal.z))
{
flag = 1;
face.LightMap.Vertex[0].u = polygon[0].y;
face.LightMap.Vertex[0].v = polygon[0].z;
face.LightMap.Vertex[1].u = polygon[1].y;
face.LightMap.Vertex[1].v = polygon[1].z;
face.LightMap.Vertex[2].u = polygon[2].y;
face.LightMap.Vertex[2].v = polygon[2].z;
}
else if (Math.Abs(poly_normal.y) > Math.Abs(poly_normal.x) &&
Math.Abs(poly_normal.y) > Math.Abs(poly_normal.z))
{
flag = 2;
face.LightMap.Vertex[0].u = polygon[0].x;
face.LightMap.Vertex[0].v = polygon[0].z;
face.LightMap.Vertex[1].u = polygon[1].x;
face.LightMap.Vertex[1].v = polygon[1].z;
face.LightMap.Vertex[2].u = polygon[2].x;
face.LightMap.Vertex[2].v = polygon[2].z;
}
else
{
flag = 3;
face.LightMap.Vertex[0].u = polygon[0].x;
face.LightMap.Vertex[0].v = polygon[0].y;
face.LightMap.Vertex[1].u = polygon[1].x;
face.LightMap.Vertex[1].v = polygon[1].y;
face.LightMap.Vertex[2].u = polygon[2].x;
face.LightMap.Vertex[2].v = polygon[2].y;
}
face.LightMap.MapMode = flag;
float Min_U = face.LightMap.Vertex[0].u;
float Min_V = face.LightMap.Vertex[0].v;
float Max_U = face.LightMap.Vertex[0].u;
float Max_V = face.LightMap.Vertex[0].v;
for (int i = 0; i < 3; i++)
{
if (face.LightMap.Vertex.u < Min_U )
Min_U = face.LightMap.Vertex.u;
if (face.LightMap.Vertex.v < Min_V )
Min_V = face.LightMap.Vertex.v;
if (face.LightMap.Vertex.u > Max_U )
Max_U = face.LightMap.Vertex.u;
if (face.LightMap.Vertex.v > Max_V )
Max_V = face.LightMap.Vertex.v;
}
float Delta_U = Max_U - Min_U;
float Delta_V = Max_V - Min_V;
for (int i = 0; i < 3; i++)
{
face.LightMap.Vertex.u -= Min_U;
face.LightMap.Vertex.v -= Min_V;
face.LightMap.Vertex.u /= Delta_U;
face.LightMap.Vertex.v /= Delta_V;
}
float X, Y, Z;
float Distance = - (poly_normal.x * pointonplane.x + poly_normal.y * pointonplane.y + poly_normal.z * pointonplane.z);
Vector3 UVVector = new Vector3();
Vector3 Vect1 = new Vector3();
Vector3 Vect2 = new Vector3();
switch (flag)
{
case 1: //YZ Plane
X = - ( poly_normal.y * Min_U + poly_normal.z * Min_V + Distance )
/ poly_normal.x;
UVVector.x = X;
UVVector.y = Min_U;
UVVector.z = Min_V;
X = - ( poly_normal.y * Max_U + poly_normal.z * Min_V + Distance )
/ poly_normal.x;
Vect1.x = X;
Vect1.y = Max_U;
Vect1.z = Min_V;
X = - ( poly_normal.y * Min_U + poly_normal.z * Max_V + Distance )
/ poly_normal.x;
Vect2.x = X;
Vect2.y = Min_U;
Vect2.z = Max_V;
break;
case 2: //XZ Plane
Y = - ( poly_normal.x * Min_U + poly_normal.z * Min_V + Distance )
/ poly_normal.y;
UVVector.x = Min_U;
UVVector.y = Y;
UVVector.z = Min_V;
Y = - ( poly_normal.x * Max_U + poly_normal.z * Min_V + Distance )
/ poly_normal.y;
Vect1.x = Max_U;
Vect1.y = Y;
Vect1.z = Min_V;
Y = - ( poly_normal.x * Min_U + poly_normal.z * Max_V + Distance )
/ poly_normal.y;
Vect2.x = Min_U;
Vect2.y = Y;
Vect2.z = Max_V;
break;
case 3: //XY Plane
Z = - ( poly_normal.x * Min_U + poly_normal.y * Min_V + Distance )
/ poly_normal.z;
UVVector.x = Min_U;
UVVector.y = Min_V;
UVVector.z = Z;
Z = - ( poly_normal.x * Max_U + poly_normal.y * Min_V + Distance )
/ poly_normal.z;
Vect1.x = Max_U;
Vect1.y = Min_V;
Vect1.z = Z;
Z = - ( poly_normal.x * Min_U + poly_normal.y * Max_V + Distance )
/ poly_normal.z;
Vect2.x = Min_U;
Vect2.y = Max_V;
Vect2.z = Z;
break;
}
Vector3 edge1 = new Vector3();
Vector3 edge2 = new Vector3();
edge1.x = Vect1.x - UVVector.x;
edge1.y = Vect1.y - UVVector.y;
edge1.z = Vect1.z - UVVector.z;
edge2.x = Vect2.x - UVVector.x;
edge2.y = Vect2.y - UVVector.y;
edge2.z = Vect2.z - UVVector.z;
int Width = level.Scene.LightMapWidthHeight;
int Height = level.Scene.LightMapWidthHeight;
face.LightMap.Lumels = new Lumel[Width * Height];
face.LightMap.Width = Width;
face.LightMap.Height = Height;
bool allShaded = true;
bool allLit = true;
for(int iY = 0; iY < Height; iY++)
{
for(int iX = 0; iX < Width; iX++)
{
Lumel lumel = new Lumel();
//we are on the border of pixels at this point, not the center
float ufactor = (iX / (float)Width) + 1.0f / (Width * 2.0f);
float vfactor = (iY / (float)Height) + 1.0f / (Height * 2.0f);
lumel.IsValid = true;
Vector3 newedge1 = new Vector3();
Vector3 newedge2 = new Vector3();
newedge1.x = edge1.x * ufactor;
newedge1.y = edge1.y * ufactor;
newedge1.z = edge1.z * ufactor;
newedge2.x = edge2.x * vfactor;
newedge2.y = edge2.y * vfactor;
newedge2.z = edge2.z * vfactor;
lumel.Position = new Vector3();
lumel.Position.x = UVVector.x + newedge2.x + newedge1.x;
lumel.Position.y = UVVector.y + newedge2.y + newedge1.y;
lumel.Position.z = UVVector.z + newedge2.z + newedge1.z;
LevelLight testLight = level.LevelLight;
Vector3 dir = level.LevelLight.Position - lumel.Position;
float dot = poly_normal * dir;
if (dot > 0.0f)
{
float RAY_LENGTH = 10000;
Vector3 lightDirection = lumel.Position - level.LevelLight.Position;
lightDirection.Normalize();
float lumel_t = Vector3.Distance(testLight.Position, lumel.Position) / RAY_LENGTH;
lightDirection = lightDirection * RAY_LENGTH;
bool intersects = false;
for (int objIndex = 0; objIndex < level.SceneObjects.Count; objIndex++)
{
if (level.SceneObjects[objIndex].ObjectType == IPlanObjectType.Mesh && level.SceneObjects[objIndex] != face.Parent)
{
PolyMesh mesh = (PolyMesh) level.SceneObjects[objIndex];
float mesh_t = mesh.IntersectsWithRay(testLight.Position, lightDirection);
float tolerence = 0.001f;
if (mesh_t != Intersections.NO_INTERSECTION && mesh_t < lumel_t)
{
float deltaT = Math.Abs(mesh_t - lumel_t);
if (deltaT > tolerence)
{
intersects = true;
}
}
}
}
if (intersects)
{
lumel.Value = level.Scene.ShadowIntensity;
allLit = false;
lumel.Shaded = true;
}
else
{
lumel.Value = 0xFF;
allShaded = false;
lumel.Shaded = false;
}
}
face.LightMap[iX, iY] = lumel;
}//end lightmap x loop
}//end lightmap y loop
if (fillInvalidLumels)
FillInvalidPixels(face.LightMap);
if (smoothMap)
SmoothLightMap(face.LightMap);
}