Thanks for that. I had a read of it, along with a couple of similar pages people suggested, and I came up with what I thought was good code, but it's not working properly. Perhaps someone with a better mathematical mind than me could take a look and spot where I've gone wrong.
It has a dash of TV and a dash of BMax but it should all be pretty readable whatever language/API you use. I've included all the important related functions and left out a couple of functions which I know are working perfectly and aren't related to this particular calculation anyway. ( For instance, PointInTri is definitely working and bears no correlation to the transformation from texture spsace to world space anyway.
It has a dash of TV and a dash of BMax but it should all be pretty readable whatever language/API you use. I've included all the important related functions and left out a couple of functions which I know are working perfectly and aren't related to this particular calculation anyway. ( For instance, PointInTri is definitely working and bears no correlation to the transformation from texture spsace to world space anyway.
' MAIN CODE - THIS IS THE ESSENCE OF THE LIGHTMAPPER. IT CHECKS IF EACH POINT IS IN A TRI ' AND IF IT IS, IT FINDS THE WORLD COORDINATES WITHIN THAT TRI THAT THE PIXEL COORDINATES MAP TO PrecalculateTriangles(Mesh,TexWidth,TexHeight,UVChannel) For Local TX:Int=0 To TexWidth-1 For Local TY:Int=0 To TexHeight-1 For Local T:LightmapTriangle=EachIn LightmapTriangle.List SearchU=(TX+0.5)/Float(TexWidth) ' TURN PIXEL COORDINATES INTO UV COORDINATES SearchV=(TY+0.5)/Float(TexHeight) Local PIT:Int=False Select UVChannel Case 0 If PointInTriangle(SearchU,SearchV,T.TA1.X,T.TA1.Y,T.TA2.X,T.TA2.Y,T.TA3.X,T.TA3.Y) PIT=True End If Case 1 If PointInTriangle(SearchU,SearchV,T.TB1.X,T.TB1.Y,T.TB2.X,T.TB2.Y,T.TB3.X,T.TB3.Y) PIT=True End If End Select If PIT=True Local DeltaUAdd:cTV_3DVECTOR=TVMathLibrary.VMultiply(T.DeltaU,SearchU) Local DeltaVAdd:cTV_3DVECTOR=TVMathLibrary.VMultiply(T.DeltaV,SearchV) TVMathLibrary.TVVec3Add(PointOut1,T.OriginWS3,DeltaUAdd) TVMathLibrary.TVVec3Add(PointOut2,PointOut1,DeltaVAdd) ' WORLD COORDINATES SHOULD NOW BE IN POINT OUT 2!! ' LIGHTING CALCULATION AND SETPIXEL'ING GOES HERE End If Next Next Next ' END OF LIGHTMAPPING CODE ' FUNCTIONS USED BY THE MAIN CODE Function PrecalculateTriangles(Mesh:cTVMesh,TexWidth:Int,TexHeight:Int,UVChannel:Int) For Local TCount:Int=0 To Mesh.GetTriangleCount()-1 Local T:LightmapTriangle=New LightmapTriangle T.Face=TCount Mesh.GetTriangleInfo(TCount,T.V1,T.V2,T.V3,T.Group) Mesh.GetVertex(T.V1,T.P1.x,T.P1.y,T.P1.z,T.N1.x,T.N1.y,T.N1.z,T.TA1.X,T.TA1.Y,T.TB1.X,T.TB1.Y,T.Col1) Mesh.GetVertex(T.V2,T.P2.x,T.P2.y,T.P2.z,T.N2.x,T.N2.y,T.N2.z,T.TA2.X,T.TA2.Y,T.TB2.X,T.TB2.Y,T.Col2) Mesh.GetVertex(T.V3,T.P3.x,T.P3.y,T.P3.z,T.N3.x,T.N3.y,T.N3.z,T.TA3.X,T.TA3.Y,T.TB3.X,T.TB3.Y,T.Col3) Select UVChannel Case 0 ComputeTangentBasis(T.P1,T.P2,T.P3,T.TA1,T.TA2,T.TA3,T.Tangent,T.BiTangent) Case 1 ComputeTangentBasis(T.P1,T.P2,T.P3,T.TB1,T.TB2,T.TB3,T.Tangent,T.BiTangent) End Select T.DeltaU=TVMathLibrary.VMultiply(T.Tangent,1/Float(TexWidth)) T.DeltaV=TVMathLibrary.VMultiply(T.BiTangent,1/Float(TexHeight)) T.OriginWS=cTV_3DVECTOR.create(T.P1.x,T.P1.y,T.P1.z) Select UVChannel Case 0 T.XMult=T.TA1.X*TexWidth-0.5 T.YMult=T.TA1.Y*TexHeight-0.5 Case 1 T.XMult=T.TB1.X*TexWidth-0.5 T.YMult=T.TB1.Y*TexHeight-0.5 End Select T.DeltaUSubtract=TVMathLibrary.VMultiply(T.DeltaU,T.XMult) T.DeltaVSubtract=TVMathLibrary.VMultiply(T.DeltaV,T.YMult) TVMathLibrary.TVVec3Subtract(T.OriginWS2,T.OriginWS,T.DeltaUSubtract) TVMathLibrary.TVVec3Subtract(T.OriginWS3,T.OriginWS2,T.DeltaVSubtract) ' CALCULATE THE SURFACE NORMAL TVMathLibrary.TVVec3Subtract(T.P1P2,T.P2,T.P1) TVMathLibrary.TVVec3Subtract(T.P1P3,T.P3,T.P1) TVMathLibrary.TVVec3Cross(T.SurfaceNormal,T.P1P2,T.P1P3) T.SurfaceNormal.Normalize() Next End Function Function ComputeTangentBasis(P1:cTV_3DVECTOR,P2:cTV_3DVECTOR,P3:cTV_3DVECTOR,UV1:cTV_2DVECTOR,UV2:cTV_2DVECTOR,UV3:cTV_2DVECTOR,Tangent:cTV_3DVECTOR,Bitangent:cTV_3DVECTOR) Local Edge1:cTV_3DVECTOR=cTV_3DVECTOR.create(0,0,0) TVMathLibrary.TVVec3Subtract(Edge1,P2,P1) Local Edge2:cTV_3DVECTOR=cTV_3DVECTOR.create(0,0,0) TVMathLibrary.TVVec3Subtract(Edge2,P3,P1) Local Edge1UV:cTV_2DVECTOR=cTV_2DVECTOR.create(0,0) TVMathLibrary.TVVec2Subtract(Edge1UV,UV2,UV1) Local Edge2UV:cTV_2DVECTOR=cTV_2DVECTOR.create(0,0) TVMathLibrary.TVVec2Subtract(Edge2UV,UV3,UV1) Local CP:Float=(Edge1UV.Y*Edge2UV.X)-(Edge1UV.X*Edge2UV.Y) If CP<>0 Local Mul:Float=1.0/CP Local TangentEdgeMult1:cTV_3DVECTOR=TVMathLibrary.VMultiply(Edge1,-Edge2UV.Y) Local TangentEdgeMult2:cTV_3DVECTOR=TVMathLibrary.VMultiply(Edge2,Edge1UV.Y) Local BiTangentEdgeMult1:cTV_3DVECTOR=TVMathLibrary.VMultiply(Edge1,-Edge2UV.X) Local BiTangentEdgeMult2:cTV_3DVECTOR=TVMathLibrary.VMultiply(Edge2,Edge1UV.X) Local TangentTotal:cTV_3DVECTOR=cTV_3DVECTOR.create(0,0,0) TVMathLibrary.TVVec3Add(TangentTotal,TangentEdgeMult1,TangentEdgeMult2) Local BiTangentTotal:cTV_3DVECTOR=cTV_3DVECTOR.create(0,0,0) TVMathLibrary.TVVec3Add(BiTangentTotal,BiTangentEdgeMult1,BiTangentEdgeMult2) Local VTangent:cTV_3DVECTOR=TVMathLibrary.VMultiply(TangentTotal,Mul) Local VBiTangent:cTV_3DVECTOR=TVMathLibrary.VMultiply(BiTangentTotal,Mul) Tangent.x=VTangent.x Tangent.y=VTangent.y Tangent.z=VTangent.z BiTangent.x=VBiTangent.x BiTangent.y=VBiTangent.y BiTangent.z=VBiTangent.z End If End Function