Given a plane and a 3D point, transform the 3D point to a 2D coordinate along the plane.

Blitz3D Forums/Blitz3D Programming/Given a plane and a 3D point, transform the 3D point to a 2D coordinate along the plane.

JoshK(Posted 2003) [#1]
This is harder than it sounds. This is to determine UV coords for any point in space, relative to any plane. The d# part of the equation is irrelevant, because the 3D point's distance from the plane doesn't matter, just it's 2D coordinates relative to that plane.

TextureCoord(x#,y#,z#,nx#,ny#,nz#)
Returns u# and v# values
End Function


DarkEagle(Posted 2003) [#2]
TformPoint maybe?

TformPoint(x,y,z,plane,0)


DarkEagle(Posted 2003) [#3]
infact heres your function:

TextureCoord(x#,y#,z#,nx#,ny#,nz#) 

plane = createplane()
aligntovector plane,nx,ny,nz,(i cant remember which axis),0

tformpoint x,y,z,plane,0

u = tformedx()
v = tformedy()

End Function


i think...


jhocking(Posted 2003) [#4]
I'm gonna bet that halo is going to say, "Oh yeah, I forgot to mention I'm not doing this in Blitz3D so I can't use TForm." Every other time he's asked this sort of question he forgot to mention that he can't use TForm to do it.

I'm not so hot at 3D math so I can't really help you here, but it sounds like a fairly basic question. I imagine the correct sequence of cross products and/or dot products is already noted down in linear algebra textbooks.


sswift(Posted 2003) [#5]
What you ask is impossible. You cannot define a point by a UV coordinate on a plane by merely specifying a point in space and a plane normal.

You must define an origin point on that plane for said coordinates to be relative to, and define one other point 90 degrees to that point to define the directions of the axis of the coordinate system.

Once you have done that though, the problem becomes simple.

Take the normal of the plane and apply this to your point in space to create a ray, and determine where that ray intersects the plane. Then determine where that point is relative to your coordinate system defined by your two points on the plane.

There's code in the code archives to dtermine where a ray intersects a triangle. And a triangle is exactly what you need to define your plane with. I said you only need two points to define your coordinate system, but that presumes a coordinate system with no scaling on either axis and with axis which are 90 degrees to one another. Create a 90 dgree triangle with the code in the code archies I posted so that the 90 degree corder is your plane's origin and the other two points are relative to it, and then do the ray intersect with it using that plane normal combined with the point in space to create the ray. The result is a UV coordinate of the collision point.


fredborg(Posted 2003) [#6]
This should get you started:
Global ProjectX#,ProjectY#,ProjectZ#

;
; x,y,z       = Position of the point
; px,py,pz    = A point on the plane
; pnx,pny,pnz = The plane normal
; returns the shortest distance from the point to the plane
;
Function ProjectPointOnPlane#(x#,y#,z#,px#,py#,pz#,pnx#,pny#,pnz#)
	
	Local sb#, sn#, sd#
	sn = - (pnx*(x-px) + pny*(y-py) + pnz*(z-pz))
	sd = (pnx*pnx + pny*pny + pnz*pnz)
	sb = sn / sd

	ProjectX = x + sb * pnx
	ProjectY = y + sb * pny
	ProjectZ = z + sb * pnz
	
	Return Sqr((x - ProjectX)^2 + (y - ProjectY)^2 + (y - ProjectY)^2)
	
End Function

Fredborg


jhocking(Posted 2003) [#7]
"it sounds like a fairly basic question..."
"What you ask is impossible"

Note that, by "fairly basic," I meant "impossible." :P


JoshK(Posted 2003) [#8]
haha...

Yes, this is Blitzplus.

I almost have it like this:

u#=nx*z+nz*x+ny*x
v#=nx*z+nz*y+ny*x

...but it is still a little off. I ran into a floating point error that was screwing everything up.

Thanks for the comments. I'll try the way I am doing it now a little more and see if it works. Will report my findings.


JoshK(Posted 2003) [#9]
My approach sucks.

A plane has no position other than distance from the origin. I don't care about the Z position of the point in plane space, because I just need UV coords. The answer would be just the same no matter what d is, so you only need x,y,z,nx,ny,nz to get u and v.

Keeping that in mind, any more ideas? I'll keep trying.


sswift(Posted 2003) [#10]
"The answer would be just the same no matter what d is, so you only need x,y,z,nx,ny,nz to get u and v."


As I said, you need a reference point on the plane for U and V to be realtive to. And you need to know the direction of the coordinate system on the plane. I told you how to do it. It's simple if you just grab that code I told you to from the code archives.


marksibly(Posted 2003) [#11]
Hi,

There are many ways to 'transform a point to a plane' - you'll have to be more specific.

Simplest is nearest point on plane to point, which *does* use 'd', so I take it its not that.

There also 'axial planar mapping' ala Fredborg's code above. But surely you've done that for the lightmapping in CShop?

Any example of 'real world' usage, please!


JoshK(Posted 2003) [#12]
My code sucks.

Okay...


You have a face of an object, defined as nx,ny,nz,d. You have a point on that face, defined as x,y,z.

The way I did this in Blitz 3D was to create a pivot, point it at the point nx,ny,nz with Chroma's point function (or pointing at another pivot works, too). I found I then had to rotate the entity to its own pitch, its own yaw, and a roll of 0.

I then Tformed the point x,y,z from world space to the pivot's space. TFormedX() supplied the U coordinate, and TFormedY() supplied the V coordinate. TFormedZ() was never used.

I have matrix routines that have been shown to produce the same results as Blitz3D transformations, but I am not very comfortable with them, and would prefer something simpler.


marksibly(Posted 2003) [#13]
How did you do your lightmapping?

Surely that was mapping a 3d point to a plane along one axis?


JoshK(Posted 2003) [#14]
(Edited the above while you were posting this, and it answers your question.)

I think what this will take is matrices aligned to the plane vector using Chroma's point function, then multiply the matrix with the 3D point matrix. I'll try it tommorrow.


BlitzSupport(Posted 2003) [#15]
Excuse me if this is irrelevant, but if you have the vector towards the plane (?), perhaps this code for finding the distance from the point to the plane would be of use? I don't have a clue about 3D maths stuff though...

http://www1.acm.org/pubs/tog/GraphicsGems/gemsiii/pt2plane.c


sswift(Posted 2003) [#16]
"The way I did this in Blitz 3D was to create a pivot, point it at the point x,y,z with Chroma's point function (or pointing at another pivot works, too). I found I then had to rotate the entity to its own pitch, its own yaw, and a roll of 0."


In doing so you are defining the up axis of the plane as being the Y axis of the world projected onto the plane.

If you do that, then when you are pointing exactly up or down then the Y axis projects to a single point on the plane and you lose your frame of reference.

This sort of hack would have resulted in a random direction for the plane's up direction being chosen in cases where the plane is aligned to the XZ plane of the world, unless the object you're pointing always starts from the same orientation or Mark's math is doing something funny.


fredborg(Posted 2003) [#17]
You need an origin for the plane! You cannot calculate an offset (which is essentially what UVW coordinates are), without having a reference point. But if you always consider 0,0,0 the origin of the plane, you can simplify the formulas quite a lot.

Fredborg


JoshK(Posted 2003) [#18]
Sorry, I mean position a pivot at 0,0,0 and align it to the normal of the plane, then transform the point x,y,z to the pivot's coordinates. If you pointed the pivot at the point x,y,z, as I accidentally said, your transformed points would be 0.0,0.0,z.


JoshK(Posted 2003) [#19]
I got it.

It's much more complex than just transforming points. It all has to do with which way a mapper will most likely consider "up" and want the texture to point.

Have you ever had a routine you wrote, and have no idea how you got it wo work, except just by going on hunches and looking for patterns, until suddenly it works perfectly? This was almost up there with CSG.

Take a look at this crazy-ass code:

Function TextureCoords(x#,y#,z#,nx#,ny#,nz#)
If nz<0.0
	nx=-nx
	ny=-ny
	nz=-nz
	EndIf
If Abs(nx#)<0.0000001 And Abs(nz#)<0.0000001
	texturev=z/64.0
	textureu=x/64.0*Sgn(ny)
	Return
	EndIf
If Abs(nx#)<0.0000001 And Abs(ny#)<0.0000001
	texturev=y/64.0
	textureu=x/64.0*-Sgn(nz)
	Return
	EndIf
If Abs(nz#)<0.0000001 And Abs(ny#)<0.0000001
	texturev=y/64.0
	textureu=z/64.0*Sgn(nx)
	Return
	EndIf
If Abs(nx)>Abs(nz)
	If Abs(ny)>Abs(nx) roll#=-90.0*Sgn(nx)
	EndIf
If Abs(nx)<Abs(nz)
	If Abs(ny)>Abs(nz)
		If ny>0.0
			If nz>0.0 roll#=180.0
			EndIf
		If ny<0.0
			If nz<0.0 roll#=180.0
			EndIf
		EndIf
	EndIf
If Abs(nx)>Abs(nz) And Abs(ny)>Abs(nz) nz=0
If Abs(nx)>Abs(ny) And Abs(nz)>Abs(ny) ny=0
If Abs(ny)>Abs(nx) And Abs(nz)>Abs(nx) nx=0
dx#=nx#
dy#=ny#
dz#=nz#
dist#=Sqr#((dx#^2)+(dz#^2))
pitch#=ATan2((dy#),dist#)
yaw#=ATan2(dx#,-dz#)
matrix=createtransmatrix(x,y,z)
matrix2=createrotmatrix3(pitch,yaw,roll)
matrix3=mulmatrices(matrix,matrix2)
textureu#=getmatrixelement(matrix3,4,1)/64.0
texturev#=getmatrixelement(matrix3,4,2)/64.0
FreeBank matrix
FreeBank matrix2
FreeBank matrix3
Return