MOUSEAXIS(0) and 1 inside X_MAKE3D

Previous topic - Next topic

MrTAToad

I've found that when trying to read the values from MOUSEAXIS(0) and MOUSEAXIS(1) between a X_MAKE3D and X_MAKE2D section, the values read are intermittent and are usually 0.  However, read the values after X_MAKE2D and everything is fine...

FutureCow

I'm not seeing quite the same behaviour, I'm seeing that MOUSEAXIS is 99% broken, almost always returning 0. I'm calling before x_make3d.

MrTAToad

I believe its fixed in the beta, although I dont think I tried it in 3D mode

Hemlos

Bing ChatGpt is pretty smart :O

MrTAToad


Hemlos

The way glbasic was intended to be used is 3d first then 2d then showscreen, as a standard.
But it can be used in infinite ways.

If you follow a regiment for your mouse controllers, you will never have an issue with it.
The concept of mouseaxis records movement from the last time showscreen is called.
So you need to put it right before showscreen.

Not only will it always give a correct response, it will run with perfect precision at any frame rate.
Bing ChatGpt is pretty smart :O

Hemlos


btw if you didnt realize, mouseaixs is good for 3d, as it is increments
this is accurate at the bottom of you loops.

mousestate is good too, it is exact position tho...not so good for 3d movement.
Its best for 2d positioning, and works fast at the top of the loop.
Bing ChatGpt is pretty smart :O

MrTAToad

Never really tried MOUSEAXIS in 3D :)

Hemlos



Well if you do heres a bad little func to handle time and distance compared to physical mouse movement...physics.


Code (glbasic) Select

// ======================================================================================== //
//  Super 3d mouse
FUNCTION SYS_IO_MOUSEAXIS:
//This function is for 3d mouse control, for moving player cam etc, based on time and distance of mouse movement.
// The idea is to make smooth and consistant mouse control behaviour no matter what FPS you/them are getting.
// GETTIMER() //you can only use this command once per loop!...so use it wisely throughout the entire program!
// Just use this reference of time FrameTime, this is in milliseconds since the last time showscreen is called.
// This function can only be called once.
// This function must, MUST be place exactly right before SHOWSCREEEN!
// If you use mousestate too....you should and probably will need to put it
// at the top of the main loop, it should work good there.
// Dont forget to DIM Mouse[5] // at the top of the header somewhere.
                FrameTime=GETTIMER()
Mouse[0] = MOUSEAXIS( 0 ) / SQR(FrameTime) * SQR(FrameTime)
Mouse[1] = MOUSEAXIS( 1 ) / SQR(FrameTime) * SQR(FrameTime)
Mouse[2] = MOUSEAXIS( 2 ) / SQR(FrameTime) * SQR(FrameTime)
Mouse[3] = MOUSEAXIS( 3 )
Mouse[4] = MOUSEAXIS( 4 )
MouseX = MouseX + Mouse[0]
MouseY = MouseY + Mouse[1]
MouseZ = MouseZ + Mouse[2]
ENDFUNCTION
Bing ChatGpt is pretty smart :O

FutureCow

Sorry, I disagree. There is no logical reason for having a link between 2D work, 3D work and reading data from the mouse. I should be able to call MOUSEAXIS at any point in my code and have it return the correct result. If I call it and it returns wrong/no information then it's a bug in my book.

Hemlos

fair enough futurecow...but what if the fix requires more math in the underlying code to achieve what is already achievable?

put mouseaxis right before showscreen and use a variable to record it.....use this variable throughout your code, and it will be consistant per frame.
Bing ChatGpt is pretty smart :O

FutureCow

The ideal result in that instance would be the precompiler to enforce a showscreen directly after the mouse read (I appreciate that's likely almost impossible to implement with functions, conditional statements etc). Possibly having 2 versions of the command - an  inline one for speed and a generic "will always work but it's slower" version would be doable.

At the end of the day though, to not be a bug then like all other commands, it should always work, or it should be caught as a syntactical problem at compile time.

Hemlos

#12
I think i know why mouseaxis might be giving you a problem.
For example like my algorithm for movement:
This is wrong:

Mouse[2] = MOUSEAXIS( 2 ) / SQR(FrameTime) * SQR(FrameTime)
FrameTime=GETTIMER()

This will cause division by zero for example...resulting with a broken variable:

Mouse[2]=#IND or 0.0000000153456E-17

And this might be why you think mouseaxis is bugged....even if its a simpler division with the axis report value......any division by zero(you use this for movement, so there is likely a division somewhere)
to fix this problem, is SO simple, yet not obvious:

FrameTime=GETTIMER()
Mouse[2] = MOUSEAXIS( 2 ) / SQR(FrameTime) * SQR(FrameTime)

On the first pass of your main loop, the division by zero happens if you call gettimer LAST LAST...you SHOULD call it last, but not after the mouseaxis algorithm for your movment.
The one exception to the rule of what goes last....

gettimer
mouseaxis()/value*frametime
showscreen

Show me an example with the broken mouseaxis, i will review it for you.

Edit:
Thanks for your observation here Futurecow, i made an incorrect order and caused a division by zero in my sample in the tutorial. It bothered me to think that mouseaxis might be broken, and it is not.
Also, i have a program with 2 X_MAKE3d, and 2 X_MAKE2D......i put my algorithms betwen them, everywhere as a test to prove, or disprove my observation to be be correct.
I stand by my first quote...mouseaxis is not broken..prove me wrong.  =D
Bing ChatGpt is pretty smart :O

FutureCow

#13
Here's the 6DOF camera code from the forums. I've moved the variable declarations/functions around to make it compile, and changed the values shown on the screen slightly to display mouseaxis results.

Watch the figures returned by mouseaxis and tell me if it consistently reflects what you're doing with the mouse. If it does, you're getting different results to me. I get numbers sometimes, 0 other times (when I should be getting mouse movement values). Compare the difference if you use the mouseaxis near the top of the main routine against using the mouseaxis calls right before showscreen command. They SHOULD behave the same but they don't and therefore it's a bug as where it's called from in relation to X_MAKE3D, X_MAKE2D and SHOWSCREEN, should not impact the values returned!

Use the mouse buttons and see if it always changes the camera rotation like it should - it's inconsistent for me. (Note that the original code divided the mouseaxis returned values by 10, I took that out to really show when it was and wasn't working.)

Prove me wrong that MOUSEAXIS ISN'T broken!  :P

Code (glbasic) Select
// --------------------------------- //
// Project: 6DOFCam_lib
// Start: Thursday, November 19, 2009
// IDE Version: 7.177
//

CONSTANT rad = 3.1415926535/180

TYPE Tquaternion
    w#
    x#
    y#
    z#
ENDTYPE

TYPE Tcamera
    //position
    x#
    y#
    z#

    //look vector
    lx#
    ly#
    lz#

    //up vector
    ux#
    uy#
    uz#

    //right vector
    rx#
    ry#
    rz#

    FOV#
    aspect#
    nearClip#
    farClip#
ENDTYPE


LOCAL cam1 AS Tcamera

LOCAL speed# = .01
LOCAL xv#, yv#, zv#, p#=0, r#=0, y#=0
LOCAL mx%, my%, mw%, mba%, mbb%


// --------------------------------- //
// Project: 6DOFCam_test
// Start: Thursday, November 19, 2009
// IDE Version: 7.177



cam1.x# = 0
cam1.y = 0
cam1.z = 0

cam1.lx = 0
cam1.ly = 0
cam1.lz = -1

cam1.ux# = 0
cam1.uy# = 1
cam1.uz# = 0

cam1.rx = 1
cam1.ry = 0
cam1.rz = 0

cam1.FOV = 45
cam1.aspect = 1024/768
cam1.nearClip = .01
cam1.farClip = 5000

WHILE TRUE


MOUSESTATE mx, my, mba, mbb
mx = MOUSEAXIS(0)
my = -MOUSEAXIS(1)

X_6DOFCAMERA(cam1)

    //Linear Velocity Dampening (SPACE)
    IF KEY(57)
        xv = xv * .95
        yv = yv * .95
        zv = zv * .95
    ENDIF

    //Angular Velocity Dampening (CTRL)
    IF KEY(29)
        r = r * .95
        p = p * .95
        y = y * .95
    ENDIF

    //Accelerate Forward (W)
    IF KEY(17)
        xv = xv + (cam1.lx - cam1.x) * speed
        yv = yv + (cam1.ly - cam1.y) * speed
        zv = zv + (cam1.lz - cam1.z) * speed
    ENDIF
    //Accelerate Backward (S)
    IF KEY(31)
        xv = xv - (cam1.lx - cam1.x) * speed
        yv = yv - (cam1.ly - cam1.y) * speed
        zv = zv - (cam1.lz - cam1.z) * speed
    ENDIF
    //Accelerate Left (A)
    IF KEY(30)
        xv = xv + (cam1.rx - cam1.x) * speed
        yv = yv + (cam1.ry - cam1.y) * speed
        zv = zv + (cam1.rz - cam1.z) * speed
    ENDIF
    //Accelerate Right (D)
    IF KEY(32)
        xv = xv - (cam1.rx - cam1.x) * speed
        yv = yv - (cam1.ry - cam1.y) * speed
        zv = zv - (cam1.rz - cam1.z) * speed
    ENDIF
    //Accelerate Down (F)
    IF KEY(33)
        xv = xv + (cam1.ux - cam1.x) * speed
        yv = yv + (cam1.uy - cam1.y) * speed
        zv = zv + (cam1.uz - cam1.z) * speed
    ENDIF
    //Accelerate Up (R)
    IF KEY(19)
        xv = xv - (cam1.ux - cam1.x) * speed
        yv = yv - (cam1.uy - cam1.y) * speed
        zv = zv - (cam1.uz - cam1.z) * speed
    ENDIF

    // change IF the left mouse button is pressed
    IF mba = 1
        //Pitch mouse up AND
        p = p + my
        //Yaw
        y = y + mx
    ELSEIF mbb = 1
        //Roll with right mouse button
        r = r + mx
    ENDIF

    cam1.x = cam1.x + xv
    cam1.y = cam1.y + yv
    cam1.z = cam1.z + zv
    cam1.lx = cam1.lx + xv
    cam1.ly = cam1.ly + yv
    cam1.lz = cam1.lz + zv
    cam1.rx = cam1.rx + xv
    cam1.ry = cam1.ry + yv
    cam1.rz = cam1.rz + zv
    cam1.ux = cam1.ux + xv
    cam1.uy = cam1.uy + yv
    cam1.uz = cam1.uz + zv

    debug_view(0,0,0,100,RGB(255,255,0),RGB(255,0,255),RGB(0,255,255))

  camera_roll(cam1,r)
  camera_pitch(cam1,p)
  camera_yaw(cam1,y)

X_MAKE2D
PRINT "mx = "+mx,10,90
PRINT "my = "+my,10,100
PRINT "Cam Pitch = "+p,10,110
PRINT "Cam Yaw = "+y,10,120
PRINT "Cam Roll = "+r,10,130
// mx = MOUSEAXIS(0)
// my = -MOUSEAXIS(1)
SHOWSCREEN
WEND


FUNCTION quaternion_normalize AS Tquaternion: tmpQ AS Tquaternion
LOCAL mag# = SQR(tmpQ.w*tmpQ.w+tmpQ.x*tmpQ.x+tmpQ.y*tmpQ.y+tmpQ.z*tmpQ.z)
LOCAL q AS Tquaternion
q.w = tmpQ.w / mag
q.x = tmpQ.x / mag
q.y = tmpQ.y / mag
q.z = tmpQ.z / mag
RETURN q
ENDFUNCTION


FUNCTION quaternion_conj AS Tquaternion: tmpQ AS Tquaternion
LOCAL q AS Tquaternion
q.w = -tmpQ.w
q.x = -tmpQ.x
q.y = -tmpQ.y
q.z = -tmpQ.z
    RETURN q
ENDFUNCTION


FUNCTION quaternion_mult AS Tquaternion: lhs AS Tquaternion, rhs AS Tquaternion
LOCAL q AS Tquaternion
    q.w = lhs.w * rhs.w - lhs.x * rhs.x - lhs.y * rhs.y - lhs.z * rhs.z
    q.x = lhs.w * rhs.x + lhs.x * rhs.w + lhs.y * rhs.z - lhs.z * rhs.y
    q.y = lhs.w * rhs.y - lhs.x * rhs.z + lhs.y * rhs.w + lhs.z * rhs.x
    q.z = lhs.w * rhs.z + lhs.x * rhs.y - lhs.y * rhs.x + lhs.z * rhs.w
RETURN q
ENDFUNCTION


FUNCTION camera_advance: cam AS Tcamera, d#
        LOCAL xt#, yt#, zt#
        xt = (cam.lx - cam.x) * d
        yt = (cam.ly - cam.y) * d
        zt = (cam.lz - cam.z) * d
        cam.x = cam.x + xt
        cam.y = cam.y + yt
        cam.z = cam.z + zt
        cam.ux =cam.ux + xt
        cam.uy =cam.uy + yt
        cam.uz =cam.uz + zt
        cam.rx =cam.rx + xt
        cam.ry =cam.ry + yt
        cam.rz =cam.rz + zt
        cam.lx =cam.lx + xt
        cam.ly =cam.ly + yt
        cam.lz =cam.lz + zt
ENDFUNCTION


FUNCTION camera_strafe: cam AS Tcamera, d#
        LOCAL xt#, yt#, zt#
        xt = (cam.rx - cam.x) * d
        yt = (cam.ry - cam.y) * d
        zt = (cam.rz - cam.z) * d
        cam.x = cam.x + xt
        cam.y = cam.y + yt
        cam.z = cam.z + zt
        cam.ux = cam.ux + xt
        cam.uy = cam.uy + yt
        cam.uz = cam.uz + zt
        cam.rx = cam.rx + xt
        cam.ry = cam.ry + yt
        cam.rz = cam.rz + zt
        cam.lx = cam.lx + xt
        cam.ly = cam.ly + yt
        cam.lz = cam.lz + zt
ENDFUNCTION


FUNCTION camera_rise: cam AS Tcamera, d#
        LOCAL xt#, yt#, zt#
        xt = (cam.ux - cam.x) * d
        yt = (cam.uy - cam.y) * d
        zt = (cam.uz - cam.z) * d
        cam.x = cam.x + xt
        cam.y = cam.y + yt
        cam.z = cam.z + zt
        cam.ux = cam.ux + xt
        cam.uy = cam.uy + yt
        cam.uz = cam.uz + zt
        cam.rx = cam.rx + xt
        cam.ry = cam.ry + yt
        cam.rz = cam.rz + zt
        cam.lx = cam.lx + xt
        cam.ly = cam.ly + yt
        cam.lz = cam.lz + zt
ENDFUNCTION


FUNCTION camera_roll: cam AS Tcamera, a#
        LOCAL qUp AS Tquaternion
        qUp.w = 0
        qUp.x = cam.ux - cam.x
        qUp.y = cam.uy - cam.y
        qUp.z = cam.uz - cam.z

        LOCAL qRight AS Tquaternion
        qRight.w = 0
        qRight.x = cam.rx - cam.x
        qRight.y = cam.ry - cam.y
        qRight.z = cam.rz - cam.z

        LOCAL qRot AS Tquaternion
        qRot.w = COS(a * rad/2)
        qRot.x = (cam.lx - cam.x) * SIN(a * rad/2)
        qRot.y = (cam.ly - cam.y) * SIN(a * rad/2)
        qRot.z = (cam.lz - cam.z) * SIN(a * rad/2)

        LOCAL W AS Tquaternion,W1 AS Tquaternion,W2 AS Tquaternion
        W1 = quaternion_mult(qRot,qUp)
        W2 = quaternion_conj(qRot)
        W = quaternion_mult(W2,W1)
        W = quaternion_normalize(W)
            cam.ux = W.x + cam.x
            cam.uy = W.y + cam.y
            cam.uz = W.z + cam.z
//        W = quaternion_mult(quaternion_mult(qRot,qRight), quaternion_conj(qRot)) <<< This does not work?!?!
        W1 = quaternion_mult(qRot,qRight)
        W2 = quaternion_conj(qRot)
        W = quaternion_mult(W2,W1)
        W = quaternion_normalize(W)
            cam.rx = W.x + cam.x
            cam.ry = W.y + cam.y
            cam.rz = W.z + cam.z
ENDFUNCTION

FUNCTION camera_pitch: cam AS Tcamera, a#
        LOCAL qUp AS Tquaternion
        qUp.w = 0
        qUp.x = cam.ux - cam.x
        qUp.y = cam.uy - cam.y
        qUp.z = cam.uz - cam.z

        LOCAL qLook AS Tquaternion
        qLook.w = 0
        qLook.x = cam.lx - cam.x
        qLook.y = cam.ly - cam.y
        qLook.z = cam.lz - cam.z

        LOCAL qRot AS Tquaternion
        qRot.w = COS(a * rad/2)
        qRot.x = (cam.rx - cam.x) * SIN(a * rad/2)
        qRot.y = (cam.ry - cam.y) * SIN(a * rad/2)
        qRot.z = (cam.rz - cam.z) * SIN(a * rad/2)

        LOCAL W AS Tquaternion,W1 AS Tquaternion,W2 AS Tquaternion
        W1 = quaternion_mult(qRot,qUp)
        W2 = quaternion_conj(qRot)
        W = quaternion_mult(W2,W1)
        W = quaternion_normalize(W)
            cam.ux = W.x + cam.x
            cam.uy = W.y + cam.y
            cam.uz = W.z + cam.z
        W1 = quaternion_mult(qRot,qLook)
        W2 = quaternion_conj(qRot)
        W = quaternion_mult(W2,W1)
        W = quaternion_normalize(W)
            cam.lx = W.x + cam.x
            cam.ly = W.y + cam.y
            cam.lz = W.z + cam.z
ENDFUNCTION


FUNCTION camera_yaw: cam AS Tcamera, a#
        LOCAL qRight AS Tquaternion
        qRight.w = 0
        qRight.x = cam.rx - cam.x
        qRight.y = cam.ry - cam.y
        qRight.z = cam.rz - cam.z

        LOCAL qLook AS Tquaternion
        qLook.w = 0
        qLook.x = cam.lx - cam.x
        qLook.y = cam.ly - cam.y
        qLook.z = cam.lz - cam.z

        LOCAL qRot AS Tquaternion
        qRot.w = COS(a * rad/2)
        qRot.x = (cam.ux - cam.x) * SIN(a * rad/2)
        qRot.y = (cam.uy - cam.y) * SIN(a * rad/2)
        qRot.z = (cam.uz - cam.z) * SIN(a * rad/2)

        LOCAL W AS Tquaternion,W1 AS Tquaternion,W2 AS Tquaternion
        W1 = quaternion_mult(qRot,qRight)
        W2 = quaternion_conj(qRot)
        W = quaternion_mult(W2,W1)
        W = quaternion_normalize(W)
            cam.rx = W.x + cam.x
            cam.ry = W.y + cam.y
            cam.rz = W.z + cam.z
        W1 = quaternion_mult(qRot,qLook)
        W2 = quaternion_conj(qRot)
        W = quaternion_mult(W2,W1)
        W = quaternion_normalize(W)
            cam.lx = W.x + cam.x
            cam.ly = W.y + cam.y
            cam.lz = W.z + cam.z
ENDFUNCTION


FUNCTION X_6DOFCAMERA: cam AS Tcamera
X_MAKE3D cam.nearClip, cam.farClip, cam.FOV
X_CAMERAUP cam.x - cam.ux, cam.y - cam.uy, cam.z - cam.uz
X_CAMERA cam.x, cam.y, cam.z, cam.lx, cam.ly, cam.lz
ENDFUNCTION


FUNCTION debug_view: x, y, z, crad, rgb1, rgb2, rgb3
LOCAL rad, x1, y1, j, x2, y2
y1=SIN(0)*crad
x1=COS(0)*crad
FOR j=4 TO 360 STEP 4
    y2=SIN(j)*crad
    x2=COS(j)*crad
    X_LINE x+x1,y+y1,z  , x+x2,y+y2,z,0.1,rgb1
    X_LINE x+x1,y+0,y1+z, x+x2,y+0,y2+z,1,rgb2
    X_LINE x+0,y+x1,y1+z, x+0,y+x2,y2+z,1,rgb3
    x1=x2
    y1=y2
NEXT
X_DOT x,y,z,10,rgb1
X_DRAWAXES x+crad,y,z
    X_DRAWAXES x-crad,y,z
    X_DRAWAXES x,y+crad,z
    X_DRAWAXES x,y-crad,z
    X_DRAWAXES x,y,crad+z
    X_DRAWAXES x,y,-crad+z
    X_PRINT "RIGHT X+",x+crad,y,z,0
    X_PRINT "LEFT X-",x-crad,y,z,0
    X_PRINT "UP Y+",x,y+crad,z,0
    X_PRINT "DOWN Y-",x,y-crad,z,0
    X_PRINT "OUT Z+",x,y,crad+z,0
    X_PRINT "IN Z-",x,y,-crad+z,0
    X_SETTEXTURE -1, -1
ENDFUNCTION





Hemlos

#14
Replace this at the top of the loop...fixed...i tried with the mouseaxis at the bottom
both ways work 100%
Code (glbasic) Select

// MOUSESTATE mx, my, mba, mbb
mx = MOUSEAXIS(0)
my = -MOUSEAXIS(1)
mba=MOUSEAXIS(3)
mbb=MOUSEAXIS(4)



Keep in mind that code is not perfect...that sample needs alot of work...
i know because i use it for my flight simulator, the quaternions.

ps. this was your conflict: MOUSESTATE mx, my, mba, mbb


8) 8)
Bing ChatGpt is pretty smart :O