2d texture coordinate (TX,TY) to 3d world coordinate (WX,WY,WZ) by Jeppe Nielsen

Started by RemiD, October 04, 2019, 20:41:08

Previous topic - Next topic

RemiD

a great code by "Jeppe Nielsen", that was apparently not in the codes archives :

;Texel to world coordinates, use the TFormTexel function (by Jeppe Nielsen)

Graphics3D 800,600,32,2

HidePointer

camera=CreateCamera()

PositionEntity camera,3,4,-4
RotateEntity camera,50,0,0
CameraClsColor camera,0,0,255

tex=CreateTexture(512,512)

quad=CreateMesh()

surface=CreateSurface(quad)

AddVertex surface,0,0,0,0,0
AddVertex surface,2,0,0,1,0
AddVertex surface,2,0,-2,1,1
AddVertex surface,0,0,-4,0,1

AddTriangle surface,0,1,3
AddTriangle surface,1,2,3

EntityFX quad,1

sphere=CreateSphere(32)
PositionEntity sphere,3,0,0

EntityFX sphere,1

cube=CreateCube()
PositionEntity cube,6,0,0

EntityFX cube,1

EntityTexture quad,tex
EntityTexture sphere,tex
EntityTexture cube,tex

Local marker[2]

For n=0 To 2
marker[n]=CreateCube()
ScaleEntity marker[n],0.15,0.15,0.15
EntityAlpha marker[n],0.8
EntityFX marker[n],1
Next

Repeat

mx=MouseX()
my=MouseY()

DrawToTexture(tex,mx,my)

If TFormTexel(quad,tex,mx,my)=True

PositionEntity marker[0],TFormedX(),TFormedY(),TFormedZ()

Else

PositionEntity marker[0],10000,10000,10000

EndIf

If TFormTexel(sphere,tex,mx,my)=True

PositionEntity marker[1],TFormedX(),TFormedY(),TFormedZ()

Else

PositionEntity marker[1],10000,10000,10000

EndIf

If TFormTexel(cube,tex,mx,my)=True

PositionEntity marker[2],TFormedX(),TFormedY(),TFormedZ()

Else

PositionEntity marker[2],10000,10000,10000

EndIf

RenderWorld()

Plot mx,my

Rect 0,0,TextureWidth(tex),TextureHeight(tex),False
Color 255,255,255
Oval mx-4/2,my-4/2,4,4,True
Oval mx-40,my-40,80,80,False

Flip

Until KeyDown(1)
End

;this will calculate the world coordinates of a texel, at the texture pixel coordinates specified
;results are grabbed with TFormedX(),TFormedY() and TFormedZ()
Function TFormTexel(mesh,texture,pixelx,pixely)

twid=TextureWidth(texture)-1
thei=TextureHeight(texture)-1

px#=Float(pixelx)/twid
py#=Float(pixely)/thei

surfs=CountSurfaces(mesh)

For surf=1 To surfs

surface=GetSurface(mesh,surf)

tris=CountTriangles(surface)-1

For triangle=0 To tris

vert0=TriangleVertex(surface,triangle,0)
vert1=TriangleVertex(surface,triangle,1)
vert2=TriangleVertex(surface,triangle,2)

x0#=VertexU(surface,vert0)
y0#=VertexV(surface,vert0)

x1#=VertexU(surface,vert1)
y1#=VertexV(surface,vert1)

x2#=VertexU(surface,vert2)
y2#=VertexV(surface,vert2)

;check if the point is in the texture triangle
If IsInTriangle( px#,py#, x0#,y0#,x1#,y1#,x2#,y2# )

;equations taken from here:
;
;http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/
;
ua#=( (x2-x1)*(y0-y1)-(y2-y1)*(x0-x1) ) / ( (y2-y1)*(px-x0)-(x2-x1)*(py-y0) )

ex#=x0+ua*(px-x0)
ey#=y0+ua*(py-y0)

dx#=ex-x1
dy#=ey-y1
le#=Sqr(dx*dx+dy*dy)

dx#=x2-x1
dy#=y2-y1
d1#=le#/Sqr(dx*dx+dy*dy)

ua#=( (x2-x0)*(y1-y0)-(y2-y0)*(x1-x0) ) / ( (y2-y0)*(px-x1)-(x2-x0)*(py-y1) )

ex#=x1+ua*(px-x1)
ey#=y1+ua*(py-y1)

dx#=ex-x0
dy#=ey-y0
le#=Sqr(dx*dx+dy*dy)

dx#=x2-x0
dy#=y2-y0
d2#=le#/Sqr(dx*dx+dy*dy)

px1#=VertexX(surface,vert0)
py1#=VertexY(surface,vert0)
pz1#=VertexZ(surface,vert0)

px3#=VertexX(surface,vert1)
py3#=VertexY(surface,vert1)
pz3#=VertexZ(surface,vert1)

dx#=VertexX(surface,vert2)-VertexX(surface,vert1)
dy#=VertexY(surface,vert2)-VertexY(surface,vert1)
dz#=VertexZ(surface,vert2)-VertexZ(surface,vert1)

px2#=px3+dx*d1#
py2#=py3+dy*d1#
pz2#=pz3+dz*d1#

dx#=VertexX(surface,vert2)-VertexX(surface,vert0)
dy#=VertexY(surface,vert2)-VertexY(surface,vert0)
dz#=VertexZ(surface,vert2)-VertexZ(surface,vert0)

px4#=px1+dx*d2#
py4#=py1+dy*d2#
pz4#=pz1+dz*d2#

;equations taken from here:
;http://mathworld.wolfram.com/Line-LineIntersection.html

ax#=px2#-px1#
ay#=py2#-py1#
az#=pz2#-pz1#

bx#=px4#-px3#
by#=py4#-py3#
bz#=pz4#-pz3#

cx#=px3#-px1#
cy#=py3#-py1#
cz#=pz3#-pz1#

qx1# = cy * bz - by * cz
qy1# = cz * bx - bz * cx
qz1# = cx * by - bx * cy

qx2# = ay * bz - by * az
qy2# = az * bx - bz * ax
qz2# = ax * by - bx * ay

dot#=qx1*qx2+qy1*qy2+qz1*qz2

le#=Sqr(qx2*qx2+qy2*qy2+qz2*qz2)

si#=dot#/(le#*le#)

pointx#=px1#+ax#*si#
pointy#=py1#+ay#*si#
pointz#=pz1#+az#*si#

TFormPoint pointx,pointy,pointz,mesh,0

Return True

EndIf

Next

Next

End Function

;taken from the blitzbasic site:
;http://www.blitzbasic.co.nz/codearcs/codearcs.php?code=483
Function IsInTriangle( px#,py#, ax#,ay#,bx#,by#,cx#,cy# )

Local bc#,ca#,ab#,ap#,bp#,cp#,abc#

bc# = bx*cy - by*cx
ca# = cx*ay - cy*ax
ab# = ax*by - ay*bx
ap# = ax*py - ay*px
bp# = bx*py - by*px
cp# = cx*py - cy*px
abc# = Sgn(bc + ca + ab)

Return (abc*(bc-bp+cp)>0) And (abc*(ca-cp+ap)>0) And (abc*(ab-ap+bp)>0)
End Function

Function DrawToTexture(tex,mx,my,size=4)

SetBuffer TextureBuffer(tex)

Cls

Color 255,255,255
Oval mx-size/2,my-size/2,size,size,True
Oval mx-40,my-40,80,80,False

SetBuffer BackBuffer()

End Function


and another example on how to use :

;2d texture coordinate (TX,TY) to 3d world coordinate (WX,WY,WZ) by Jeppe Nielsen
;another example on how to use it...

Graphics3D(854,480,32,2)

Camera = CreateCamera()
CameraRange(Camera,0.15,150)
CameraClsColor(Camera,000,000,000)

XMesh = CreateQuad()
ScaleMesh(XMesh,1.28/2,1.28/2,1.28/2)
PositionEntity(XMesh,1.5,1.5,1.5,True)
EntityFX(XMesh,1)

XTexture = CreateTexture(128,128,1)
SetBuffer(TextureBuffer(XTexture))
ClsColor(125,125,125) : Cls()
Color(255,255,255) : Rect(0,0,128,128,False)

EntityTexture(XMesh,XTexture,0,0)

;for displaying the texture on the screen
XImage = CreateImage(TextureWidth(XTexture),TextureHeight(XTexture))
CopyRect(0,0,TextureWidth(XTexture),TextureHeight(XTexture),0,0,TextureBuffer(XTexture),ImageBuffer(XImage))

Marker = CreateCube()
ScaleMesh(Marker,0.03/2,0.03/2,0.03/2)
EntityColor(Marker,255,000,255)
EntityFX(Marker,1)

PositionEntity(Camera,1.5,1.5+1.65,1.5-1.5)
RotateEntity(Camera,33.6,0,0)

Repeat


MX% = MouseX() : MY% = MouseY()

If( MX > 0 And MX < 0+ImageWidth(XImage) And MY > 0 And MY < 0+ImageHeight(XImage) ) ;if cursor above 2d area of the image (to get texel coordinate TX,TY)
  TX% = MX : TY% = MY
  TFormTexel(XMesh,XTexture,TX,TY)
  WX# = TFormedX() : WY# = TFormedY() : WZ# = TFormedZ()
  PositionEntity(Marker,WX,WY,WZ,True) : ShowEntity(Marker)
Else
  TX% = 0 : TY% = 0
  WX# = 0 : WY# = 0 : WZ# = 0
  PositionEntity(Marker,0,-1000,0,True) : HideEntity(Marker)
EndIf

SetBuffer(BackBuffer())
RenderWorld()

DrawImage(XImage,0,0)
If( MX > 0 And MX < 0+ImageWidth(XImage) And MY > 0 And MY < 0+ImageHeight(XImage) ) ;if cursor above 2d area of the image (to get texel coordinate TX,TY)
  Color(255,000,255) : Oval(MX-1,MY-1,2,2,True)
EndIf

Color(255,255,255)
TStr$ = TX+","+TY+"->"+WX+","+WY+","+WZ
Text(GraphicsWidth()/2-StringWidth(TStr)/2,0,TStr)

Flip(1)

Until( KeyDown(1)=1 )

WaitKey()

End()

Function CreateQuad()

TMesh = CreateMesh()
TSurface = CreateSurface(TMesh)
AddVertex(TSurface,-1.0,0.0,+1.0) : VertexTexCoords(TSurface,0,0.0/128,0.0/128)
AddVertex(TSurface,+1.0,0.0,+1.0) : VertexTexCoords(TSurface,1,128.0/128,0.0/128)
AddVertex(TSurface,-1.0,0.0,-1.0) : VertexTexCoords(TSurface,2,0.0/128,128.0/128)
AddVertex(TSurface,+1.0,0.0,-1.0) : VertexTexCoords(TSurface,3,128.0/128,128.0/128)
AddTriangle(TSurface,0,1,2)
AddTriangle(TSurface,2,1,3)
UpdateNormals(TMesh)
Return TMesh

End Function

;function TFormTexel() by Jeppe Nielsen
Function TFormTexel%(mesh,texture,texelx%,texely%)

twidth%=TextureWidth(texture)-1
theight%=TextureHeight(texture)-1

px#=Float(texelx)/twidth
py#=Float(texely)/theight

surfs=CountSurfaces(mesh)

For surf=1 To surfs
  surface=GetSurface(mesh,surf)

  tris=CountTriangles(surface)-1

  For tri=0 To tris

   vert0=TriangleVertex(surface,tri,0)
   vert1=TriangleVertex(surface,tri,1)
   vert2=TriangleVertex(surface,tri,2)

   x0#=VertexU(surface,vert0)
   y0#=VertexV(surface,vert0)

   x1#=VertexU(surface,vert1)
   y1#=VertexV(surface,vert1)

   x2#=VertexU(surface,vert2)
   y2#=VertexV(surface,vert2)

   ;check if the point is in the texture triangle
   If( IsInTriangle( px#,py#, x0#,y0#,x1#,y1#,x2#,y2# ) = True )

    ;equations taken from here:
    ;http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/
    ua#=( (x2-x1)*(y0-y1)-(y2-y1)*(x0-x1) ) / ( (y2-y1)*(px-x0)-(x2-x1)*(py-y0) )

    ex#=x0+ua*(px-x0)
    ey#=y0+ua*(py-y0)

    dx#=ex-x1
    dy#=ey-y1
    le#=Sqr(dx*dx+dy*dy)

    dx#=x2-x1
    dy#=y2-y1
    d1#=le#/Sqr(dx*dx+dy*dy)

    ua#=( (x2-x0)*(y1-y0)-(y2-y0)*(x1-x0) ) / ( (y2-y0)*(px-x1)-(x2-x0)*(py-y1) )

    ex#=x1+ua*(px-x1)
    ey#=y1+ua*(py-y1)

    dx#=ex-x0
    dy#=ey-y0
    le#=Sqr(dx*dx+dy*dy)

    dx#=x2-x0
    dy#=y2-y0
    d2#=le#/Sqr(dx*dx+dy*dy)

    px1#=VertexX(surface,vert0)
    py1#=VertexY(surface,vert0)
    pz1#=VertexZ(surface,vert0)

    px3#=VertexX(surface,vert1)
    py3#=VertexY(surface,vert1)
    pz3#=VertexZ(surface,vert1)

    dx#=VertexX(surface,vert2)-VertexX(surface,vert1)
    dy#=VertexY(surface,vert2)-VertexY(surface,vert1)
    dz#=VertexZ(surface,vert2)-VertexZ(surface,vert1)

    px2#=px3+dx*d1#
    py2#=py3+dy*d1#
    pz2#=pz3+dz*d1#

    dx#=VertexX(surface,vert2)-VertexX(surface,vert0)
    dy#=VertexY(surface,vert2)-VertexY(surface,vert0)
    dz#=VertexZ(surface,vert2)-VertexZ(surface,vert0)

    px4#=px1+dx*d2#
    py4#=py1+dy*d2#
    pz4#=pz1+dz*d2#

    ;equations taken from here:
    ;http://mathworld.wolfram.com/Line-LineIntersection.html
   
    ax#=px2#-px1#
    ay#=py2#-py1#
    az#=pz2#-pz1#

    bx#=px4#-px3#
    by#=py4#-py3#
    bz#=pz4#-pz3#

    cx#=px3#-px1#
    cy#=py3#-py1#
    cz#=pz3#-pz1#

    qx1# = cy * bz - by * cz
    qy1# = cz * bx - bz * cx
    qz1# = cx * by - bx * cy

    qx2# = ay * bz - by * az
    qy2# = az * bx - bz * ax
    qz2# = ax * by - bx * ay

    dot#=qx1*qx2+qy1*qy2+qz1*qz2

    le#=Sqr(qx2*qx2+qy2*qy2+qz2*qz2)

    si#=dot#/(le#*le#)

    pointx#=px1#+ax#*si#
    pointy#=py1#+ay#*si#
    pointz#=pz1#+az#*si#

    TFormPoint(pointx,pointy,pointz,mesh,0)

    Return True

   EndIf

  Next

Next

End Function

Function IsInTriangle( px#,py#, ax#,ay#,bx#,by#,cx#,cy# )

Local bc#,ca#,ab#,ap#,bp#,cp#,abc#

bc# = bx*cy - by*cx
ca# = cx*ay - cy*ax
ab# = ax*by - ay*bx
ap# = ax*py - ay*px
bp# = bx*py - by*px
cp# = cx*py - cy*px
abc# = Sgn(bc + ca + ab)

Return (abc*(bc-bp+cp)>0) And (abc*(ca-cp+ap)>0) And (abc*(ab-ap+bp)>0)

End Function