News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

Mouse input in opengl 3D

Started by gelatine1, January 11, 2016, 12:16:39 AM

Previous topic - Next topic

gelatine1

Hi I am writing a program in masm that represents a rubik cube. In total there are 27*6 squares drawn to the screen (six for each small cube). Now i want to implement a feature that if a user clicks on a square it changes color.
Now im having a hard time trying to translate the 2D screen coordinates to the 3D world coordinates trying to determine which square was clicked on. (only the first visible square)
I have been reading and searching for how to do it and ive discovered i could be using ray casting. All of that seems quite complicated and i dont understand how i should implement it in assembly. Has anyone ever done this before or is there some masm specific documentation about this?  Any help would be welcome.

Siekmanski

Misschien is dit wat ?

http://gamedev.stackexchange.com/questions/109579/algorithm-for-triangle-picking
Creative coders use backward thinking techniques as a strategy.

gelatine1

Ziet er wel handig uit maar niet volledig wat ik wil denk ik. Daar berekent hij gewoon of het snijdt of niet terwijl ik eigenlijk iets zou moeten hebben die enkel het eerste vlak weergeeft (met de rotaties meegerekend). Maar ik ga al eens beginnen met die matrix dingen te implementeren en iets analoog te doen. Ik zie wel hoe ver ik geraak.

Siekmanski

Weet het niet zeker maar, volgens mij kan je d.m.v.de geinverteerde projectie en wereld matrix met elkaar te vermenigvuldigen zo de 2D posities weer terug rekenen van de 3D data. Je zou dan een intersectie kunnen doen met de muis x,y waarden en de vlakken x,y waarden.
Creative coders use backward thinking techniques as a strategy.

qWord

MREAL macros - when you need floating point arithmetic while assembling!

Siekmanski

Creative coders use backward thinking techniques as a strategy.

Siekmanski

Skipping our dialect.......  8)

I gave it a thought and I think you could do it very fast and totally without math.
You have 6 different colors and 9 the same in one face.

You only have to read the one pixel ( glReadPixel ) you clicked on from the back-buffer using your mouse coords, to get the color of that face.
So you need 9 different values for each color to make a difference among the 9 same colors per face ( 6 different colors for each face in total )
If you don't use the alpha-channel for the colors then use the alpha byte to fill it with 9 different values and keep the colors exactly the same color value.

Now you know exactly which of the 54 little faces you clicked on and know for free which of the 27 little cubes it is by reading the alpha color byte value you gave it.
Creative coders use backward thinking techniques as a strategy.

gelatine1

So each face is like red with alpha 0.995,0.996,... so they're not really the same but the same for the eye though ?
That sounds a good idea but the main problem with that is that right now I've created about 200 lines of data containing hardcoded rubik configurations (trying to learn F2L OLL and PLL in case you're interested) and I don't want to bother figuring them all out again. I'll think about it, maybe there's an easy way to convert the data.. :S. Otherwise I'll have to write a matrix inversion function (unless someone already wrote one? :) )

Siekmanski

If you don't use alpha for your colors, then use the alpha byte to distinguish between the 9 same colors per face, There will be no difference between all nine blue colors etc.

ARGB (1,0,0,255)
ARGB (2,0,0,255)
ARGB (3,0,0,255)
ARGB (4,0,0,255)
ARGB (5,0,0,255)
ARGB (6,0,0,255)
ARGB (7,0,0,255)
ARGB (8,0,0,255)
ARGB (9,0,0,255)
Creative coders use backward thinking techniques as a strategy.

gelatine1

alright after some work i finally got my matrix operations finished. Now I wrote code as suggested in the link by Siekmanski (http://gamedev.stackexchange.com/questions/109579/algorithm-for-triangle-picking). The code currently calculates end- and startpoint of the ray and draws it through the cube. Sadly enough the ray doesnt actually match my mouseclicks (which it is supposed to do). I'll show some pseudocode (just to make it easier to see if there would be any mathematical mistake) below and then my real code that converts a mouseclick to a point in 3D space.


temp_vec[0]=(2*x / viewportMat[2]) -1
temp_vec[1]=(2*(viewportMat[3]-y) / viewportMat[3]) -1
temp_vec[2]=1
temp_vec[3]=1
productMat = (projectionMat*modelViewMat)^-1
near_point_vec = productMat * temp_vec
temp_vec[2]=-1
far_point_vec = productMat * temp_vec

near_point_vec/=near_point_vec[3] ; convert from homogenous coords
far_point_vec/=far_point_vec[3]

dir_vec = near_point_vec - far_point_vec
near_point_vec+=32*dir_vec ; increase the length of the line
far_point_vec+=32*dir_vec



convertclick proc x:DWORD,y:DWORD
invoke glGetIntegerv,GL_VIEWPORT,addr viewportMat

fild x
fld FLT4(2.0) ;FLT4 is a custom macro. this line loads 2.0 into st(0)
fmulp st(1),st
fild dword ptr [viewportMat+8]
fdivp st(1),st
fld1
fsubp st(1),st
fstp dword ptr [temp_vec] ;normalised_x

fild y
fild dword ptr [viewportMat+12]
fsubrp st(1),st
fld FLT4(2.0)
fmulp st(1),st
fild dword ptr [viewportMat+12]
fdivp st(1),st
fld1
fsubp st(1),st
fstp dword ptr [temp_vec+4] ;normalised_y

fld1
fstp dword ptr [temp_vec+8]
fld1
fstp dword ptr [temp_vec+12]

invoke glGetFloatv,GL_MODELVIEW_MATRIX,addr modelViewMat
invoke glGetFloatv,GL_MODELVIEW_MATRIX,addr projectionMat

invoke MatMulFlt4,addr projectionMat,addr modelViewMat,addr productMat
invoke MatInverse,addr productMat,addr productMat

invoke MatMulVecFlt4,addr productMat,addr temp_vec,addr near_point_vec
fld FLT4(-1.0)
fstp dword ptr [temp_vec+8]
invoke MatMulVecFlt4,addr productMat,addr temp_vec,addr camera_pos_vec

lea esi,near_point_vec
fld dword ptr [esi+12]
xor ecx,ecx
.while ecx!=4
fld dword ptr [esi+4*ecx]
fdiv st,st(1)
fstp dword ptr [esi+4*ecx]
inc ecx
.endw
fstp st

lea edi,camera_pos_vec
fld dword ptr [edi+12]
xor ecx,ecx
.while ecx!=4
fld dword ptr [edi+4*ecx]
fdiv st,st(1)
fstp dword ptr [edi+4*ecx]
inc ecx
.endw
fstp st

fld dword ptr [esi]
fld dword ptr [edi]
fsubp st(1),st
fld FLT4(32.0)
fmulp st(1),st
fstp dword ptr [dir_vec]

fld dword ptr [esi+4]
fld dword ptr [edi+4]
fsubp st(1),st
fld FLT4(32.0)
fmulp st(1),st
fstp dword ptr [dir_vec+4]

fld dword ptr [esi+8]
fld dword ptr [edi+8]
fsubp st(1),st
fld FLT4(32.0)
fmulp st(1),st
fstp dword ptr [dir_vec+8]

lea esi,near_point_vec
lea edi,camera_pos_vec

fld dword ptr [esi]
fld dword ptr [dir_vec]
fsubp st(1),st
fstp dword ptr [esi]
fld dword ptr [edi]
fld dword ptr [dir_vec]
faddp st(1),st
fstp dword ptr [edi]

fld dword ptr [esi+4]
fld dword ptr [dir_vec+4]
fsubp st(1),st
fstp dword ptr [esi+4]
fld dword ptr [edi+4]
fld dword ptr [dir_vec+4]
faddp st(1),st
fstp dword ptr [edi+4]

fld dword ptr [esi+8]
fld dword ptr [dir_vec+8]
fsubp st(1),st
fstp dword ptr [esi+8]
fld dword ptr [edi+8]
fld dword ptr [dir_vec+8]
faddp st(1),st
fstp dword ptr [edi+8]

mov eax,1
ret
convertclick endp


Does anyone see if there is a mathematically issue ? Or maybe theres some mistake I can't find in the implementaton of it ? or is the whole idea just wrong and doomed to fail ? I have tested the matrix inverse and multiplication procedures and they should be working correctly.

Thanks in advance