help : error somewhere to position a quad precisely at MouseX,MouseY

Started by RemiD, March 14, 2021, 10:20:52

Previous topic - Next topic

RemiD

hi !

i am trying to create a code example for our friend "RonTek" at blitzcoder.org

the goal is to be able to create / position a textured rectangle mesh like a rectangle image.

i have almost managed to do it, but there is an error somewhere and the rectangle mesh is positioned with some "lag". i wonder if this is due to a mistake in my code or because of float precision ?

if somebody can take a look :

;IElement (rectangle+text made / drawn with a image) vs QElement (rectangle+text made / positionned with a textured mesh)
;by RemiD (2021/03/14)
;there is an error somewhere which produces a "lag" when positioning the QElement...

Global GWidth% = 800
Global GHeight% = 600
Graphics3D(GWidth,GHeight,32,2)

Global Cam = CreateCamera()
CameraViewport(Cam,0,0,GWidth,GHeight)
CameraRange(Cam,0.09,99)

Shape = CreateCube() : ScaleMesh(Shape,1.0/2,1.0/2,1.0/2)
PositionEntity(Shape,0,0,0,True)

DLight = CreateLight(1) : LightColor(DLight,220,220,220)
PositionEntity(DLight,0,1000,-1000,True) : RotateEntity(DLight,45,0,0,True)
AmbientLight(025,025,025)

Arial16Font = LoadFont("Arial",16,True,False,False)
SetFont(Arial16Font)

;IElements list (rects made using images)
Global IElementsCount%
Dim IElement_Image(10)
Dim IElement_PWidth%(10)
Dim IElement_PHeight%(10)

;create a IElement
IStr$ = "test text on IElement (image)" : IWidth% = 10+StringWidth(IStr)+10 : IHeight% = 10+StringHeight(IStr)+10
DebugLog(IWidth)
DebugLog(IHeight)
I% = CreateIElement(IWidth,IHeight,220,220,120,IStr,030,030,030)

;QElements list (rects made using meshes + textures)
Global QElementsCount%
Dim QElement_Mesh(10)
Dim QElement_PWidth%(10)
Dim QElement_PHeight%(10)
;Dim QElement_Tex(10)

;create a QElement
QStr$ = "test text on QElement (textured mesh)" : QWidth% = 10+StringWidth(QStr)+10 : QHeight% = 10+StringHeight(QStr)+10
DebugLog(QWidth)
DebugLog(QHeight)
I% = CreateQElement(QWidth,QHeight,220,120,220,QStr,030,030,030)

PositionEntity(Cam,0,1.65,-5,True)

MoveMouse(GWidth/2,GHeight/2)

Repeat

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

TurnEntity(Shape,0,1,0)

If( KeyDown(30)=1 )
  TurnEntity(Cam,0,+1,0)
Else If( KeyDown(32)=1 )
  TurnEntity(Cam,0,-1,0)
EndIf
If( KeyDown(16)=1 )
  TurnEntity(Cam,+1,0,0)
Else If( KeyDown(18)=1 )
  TurnEntity(Cam,-1,0,0)
EndIf
If( KeyDown(17)=1 )
  MoveEntity(Cam,0,0,+0.1)
Else If( KeyDown(31)=1 )
  MoveEntity(Cam,0,0,-0.1)
EndIf

I% = 1
DrawQElement(I,MX,MY+QElement_PHeight(I)/2+10) ;since a QElement is a mesh+texture, update position before renderworld
;PositionEntity(QElement_Mesh(I),0,1.5,0,True)

WireFrame(False)
If( KeyDown(2)=1 )
  WireFrame(True)
EndIf

SetBuffer(BackBuffer())
RenderWorld()

I% = 1
DrawIElement(I,MX-IElement_PWidth(I)/2,MY-IElement_PHeight(I)-10) ;since a IElement is a image, update position / draw after renderworld

Flip(1)

Until( KeyDown(1)=1 )

End

Function CreateIElement%(PWidth%,PHeight%,BackgroundR%=180,BackgroundG%=180,BackgroundB%=180,TextStr$,TextR%=030,TextG%=030,TextB%=030) ;return IElement index

IElementsCount = IElementsCount + 1 : I% = IElementsCount

IElement_PWidth(I) = PWidth : IElement_PHeight(I) = PHeight
IElement_Image(I) = CreateImage(PWidth,PHeight)
SetBuffer(ImageBuffer(IElement_Image(I)))
  Color(BackgroundR,BackgroundG,BackgroundB) : Rect(0,0,PWidth,PHeight,True)
  Color(TextR,TextG,TextB) : Text(10,10,TextStr)

Return I

End Function

Function DrawIElement(I%,PX%,PY%)

DrawImage(IElement_Image(I),PX,PY)

End Function

Function CreateQElement(PWidth%,PHeight%,BackgroundR%=180,BackgroundG%=180,BackgroundB%=180,TextStr$,TextR%=030,TextG%=030,TextB%=030) ;return QElement index

QElementsCount = QElementsCount + 1 : I% = QElementsCount

QElement_PWidth(I) = PWidth : QElement_PHeight(I) = PHeight

XRatio# = 1.0 : YRatio# = Float(GHeight)/GWidth ;to correct the distortion since graphicswidth is usualy larger than graphicsheight...

QElement_Mesh(I) = CreateMesh()
Surface = CreateSurface(QElement_Mesh(I))
AddVertex(Surface,-Float(PWidth)/Float(GWidth)*XRatio,+Float(PHeight)/Float(GHeight)*YRatio,1.0) : VertexTexCoords(Surface,0,Float(0)/256,Float(0)/64)
AddVertex(Surface,+Float(PWidth)/Float(GWidth)*XRatio,+Float(PHeight)/Float(GHeight)*YRatio,1.0) : VertexTexCoords(Surface,1,Float(PWidth)/256,Float(0)/64)
AddVertex(Surface,-Float(PWidth)/Float(GWidth)*XRatio,-Float(PHeight)/Float(GHeight)*YRatio,1.0) : VertexTexCoords(Surface,2,Float(0)/256,Float(PHeight)/64)
AddVertex(Surface,+Float(PWidth)/Float(GWidth)*XRatio,-Float(PHeight)/Float(GHeight)*YRatio,1.0) : VertexTexCoords(Surface,3,Float(PWidth)/256,Float(PHeight)/64)
AddTriangle(Surface,0,1,2)
AddTriangle(Surface,2,1,3)
;UpdateNormals(QElement_Mesh(I))

;the texture must have its width and height power of 2 (16,32,64,128,256,512,1024,2048, etc...)
;for simplication i use a bigger texture than the area the text + margins will fill
;if you plan to draw many QElements, it would be better to use only 1 surface and 1 big texture for all QElements...
QTex = CreateTexture(256,64,1+16+32)
SetBuffer(TextureBuffer(QTex))
  Color(BackgroundR,BackgroundG,BackgroundB) : Rect(0,0,PWidth,PHeight,True)
  Color(TextR,TextG,TextB) : Text(10,10,TextStr)

EntityFX(QElement_Mesh(I),1) ;Fx fullbright
EntityTexture(QElement_Mesh(I),QTex)
;EntityOrder(QElement_Mesh(I),-999) ;-999 drawn after (on top of) everything else, +999 drawn before (below of) everything else

Return I

End Function

Function DrawQElement(I%,PX%,PY%)

XRatio# = 1.0 : YRatio# = Float(GHeight)/GWidth : Dist# = YRatio/10
PositionEntity(QElement_Mesh(I),EntityX(Cam,True),EntityY(Cam,True),EntityZ(Cam,True),True)
RotateEntity(QElement_Mesh(I),EntityPitch(Cam,True),EntityYaw(Cam,True),EntityRoll(Cam,True),True)
MoveEntity(QElement_Mesh(I),-XRatio,+YRatio,Dist)
OffsetX# = +Float(PX)/Float(GWidth)*2*XRatio : OffsetY# = -Float(PY)/Float(GHeight)*2*YRatio
MoveEntity(QElement_Mesh(I),OffsetX,OffsetY,0)

End Function


thanks!

STEVIE G

To get the correct scaling, the easiest way is to initially put a plane in front of the camera, make it pickable and camera pick at 0,0 and 1,1 and the  scale is the diff between the two picks.. You can use this for scaling and position. Simple.

RemiD

QuoteTo get the correct scaling, the easiest way is to initially put a plane in front of the camera, make it pickable and camera pick at 0,0 and 1,1 and the  scale is the diff between the two picks.. You can use this for scaling and position.
good idea, i am going to try, thanks

you position the plane at 0,0,+1 ? or ?

STEVIE G

Quote from: RemiD on March 14, 2021, 19:22:52
QuoteTo get the correct scaling, the easiest way is to initially put a plane in front of the camera, make it pickable and camera pick at 0,0 and 1,1 and the  scale is the diff between the two picks.. You can use this for scaling and position.
good idea, i am going to try, thanks

you position the plane at 0,0,+1 ? or ?

Aye if your min camera range is 1. Remember to rotate it on pitch axis to face camera.  ;D

peteswansen

why don't you just use a "cube" with a very small depth?  So much easier to move and rotate or turn...