JD2022-TU1/main/extern/Camcam/LIBS/Render/OGL_Picking.cpp

280 lines
8.3 KiB
C++

#include "OGL_Class.h"
#include "SCENE.h"
//#define DBG_DRAW_RED_PIXELS
//#define DBG_DRAW_PickedPrim
void OGL_DI::PickMesh(Mesh *pMyMesh,u32 Num, u32 Base)
{
if (MotherClass && MotherClass->PickReportCurrent.PickFrozed) return;
START_RASTER(Picking);
SAVE_MATRIXES();
u32 AlphaThreshold;
AlphaThreshold = 0;
if ((CurrentRS.BlendingMode == 1)||(CurrentRS.BlendingMode == 3)) AlphaThreshold = MotherClass->PickReportCurrent.AlphaThreshold;
float Viewport[4];
glGetFloatv(GL_VIEWPORT,Viewport);
u32 Counter;
FaceIndex *Indexes;
FaceIndex *Indexes_UV;
Vector Fake;
Vector MouseVector;
Vector *PointsUV,*Points;
#ifdef DBG_DRAW_PickedPrim
glDisable(GL_TEXTURE_2D);
glDisable(GL_LIGHTING);
glDisable(GL_BLEND);
glDisable(GL_ALPHA_TEST);
#endif
Points = pMyMesh->Points;
PointsUV = pMyMesh->PointsUV;
if (!Points) Points = &Fake;
if (!PointsUV) PointsUV = &Fake;
Indexes = pMyMesh->Indexes + Base;
Indexes_UV = pMyMesh->Indexes_UV + Base;
float TransMat[16];
Vector I,J,K,L;
Mul4x4Matrix(_4x4_Model,_4x4_Persp,TransMat);
I.x = TransMat[0];
I.y = TransMat[4];
I.z = TransMat[8];
J.x = TransMat[0+1];
J.y = TransMat[4+1];
J.z = TransMat[8+1];
K.x = TransMat[0+2];
K.y = TransMat[4+2];
K.z = TransMat[8+2];
L.x = TransMat[0+3];
L.y = TransMat[4+3];
L.z = TransMat[8+3];
{
GLfloat _4x4[16];
glGetFloatv(GL_MODELVIEW_MATRIX,_4x4);
glMatrixMode(GL_MODELVIEW);
Counter = 15;
while (Counter--) _4x4[Counter] *= 0.995f;
glLoadMatrixf(_4x4);
}
if (Num == -1)
Counter = pMyMesh->NumberOfFaces;
else
Counter = Num;
MouseVector.x = (MousePicking.x) - FB_SX/2.0f;
MouseVector.y = (FB_SY - MousePicking.y ) - FB_SY/2.0f;
MouseVector.x += (float)FB_SX/2.0f - Viewport[0] - Viewport[2] / 2.0f;
MouseVector.y += (float)FB_SY/2.0f - Viewport[1] - Viewport[3] / 2.0f;
MouseVector.x *= 2.0f / Viewport[2] ;
MouseVector.y *= 2.0f / Viewport[3] ;
if ((fabs(MouseVector.x) < 1.0f) && (fabs(MouseVector.y) < 1.0f) )
{
while (Counter--)
{
Vector *P1,*P2,*P3;
Vector Pr1,Pr2,Pr3;
Vector Po1,Po2,Po3;
float Pw1,Pw2,Pw3;
float aPw1,aPw2,aPw3;
float D1,D2,D3;
P1 = Points + Indexes->I[0];
P2 = Points + Indexes->I[1];
P3 = Points + Indexes->I[2];
Pw1 = ( *P1 * L ) + TransMat[15];
Pw2 = ( *P2 * L ) + TransMat[15];
Pw3 = ( *P3 * L ) + TransMat[15];
if ((Pw1 > 0.0f) || (Pw2 > 0.0f) || (Pw3 > 0.0f))
{
Pr1.x = ( *P1 * I ) + TransMat[12];
Pr1.y = ( *P1 * J ) + TransMat[13];
Pr1.z = ( *P1 * K ) + TransMat[14];
Pr2.x = ( *P2 * I ) + TransMat[12];
Pr2.y = ( *P2 * J ) + TransMat[13];
Pr2.z = ( *P2 * K ) + TransMat[14];
Pr3.x = ( *P3 * I ) + TransMat[12];
Pr3.y = ( *P3 * J ) + TransMat[13];
Pr3.z = ( *P3 * K ) + TransMat[14];
Po1 = Pr1;
Po2 = Pr2;
Po3 = Pr3;
if (Pw1 < 0) aPw1 = 1.0f/1000000.0f;
if (Pw2 < 0) aPw2 = 1.0f/1000000.0f;
if (Pw3 < 0) aPw3 = 1.0f/1000000.0f;
aPw1 = fabs(Pw1);
aPw2 = fabs(Pw2);
aPw3 = fabs(Pw3);
Pr1 *= 1.0f / aPw1;
Pr2 *= 1.0f / aPw2;
Pr3 *= 1.0f / aPw3;
D1 = MouseVector.DistanceToLineXY(Pr3 , Pr2);
D2 = MouseVector.DistanceToLineXY(Pr1 , Pr3);
D3 = MouseVector.DistanceToLineXY(Pr2 , Pr1);
u32 Pos;
Pos = 0;
#define EPSILON 0.0
if ((D1 >= -EPSILON) && (D2 >= -EPSILON) && (D3 >= -EPSILON)) Pos |= 1;
if ((D1 <= EPSILON) && (D2 <= EPSILON) && (D3 <= EPSILON)) Pos |= 2; // OGL FRONTFACE
if (CurrentRS.BACKFACE)
{
if ((Pos == 1) && (CurrentRS.BACKFACE_INVERT)) Pos = 0;
if ((Pos == 2) && (!CurrentRS.BACKFACE_INVERT)) Pos = 0;
}
if (Pos)
{
Vector IP,IP3D;
float IPw;
u32 Color;
Color = 0xff;
if ((Pw1 < 0.0f) || (Pw2 < 0.0f) || (Pw3 < 0.0f)) Color = 0xff00;
#ifdef DBG_DRAW_PickedPrim
DrawLine(Color,Points + Indexes->I[0],Points + Indexes->I[1]);
DrawLine(Color,Points + Indexes->I[1],Points + Indexes->I[2]);
DrawLine(Color,Points + Indexes->I[2],Points + Indexes->I[0]);
#endif
D1 /= Pr1.DistanceToLineXY(Pr2 , Pr3);
D2 /= Pr2.DistanceToLineXY(Pr3 , Pr1);
D3 /= Pr3.DistanceToLineXY(Pr1 , Pr2);
D1 = fabs(D1);
D2 = fabs(D2);
D3 = fabs(D3);
IP = Po1 * D1 + Po2 * D2 + Po3 * D3;
IPw = Pw1 * D1 + Pw2 * D2 + Pw3 * D3;
IP *= 1.0f / IPw;
if (CurrentRS.NOZTEST || (MousePickingCurrentZ <= IP.z))
{
u32 OKAffect = 1;
Vector IPUVW;
IPw = D1/aPw1 + D2/aPw2 + D3/aPw3;
IP3D = *(Points + Indexes->I[0]) * (D1/aPw1) +
*(Points + Indexes->I[1]) * (D2/aPw2) +
*(Points + Indexes->I[2]) * (D3/aPw3);
IP3D *= 1.0f / IPw;
Vector UVW;
UVW = *(PointsUV + Indexes_UV->I[0]) * (D1/aPw1) +
*(PointsUV + Indexes_UV->I[1]) * (D2/aPw2) +
*(PointsUV + Indexes_UV->I[2]) * (D3/aPw3) ;
UVW *= 1.0f / IPw;
IPUVW.x = UVW.x * _4x4_Texture[0] + UVW.y * _4x4_Texture[4] + _4x4_Texture[12];
IPUVW.y = UVW.x * _4x4_Texture[1] + UVW.y * _4x4_Texture[5] + _4x4_Texture[13];
IPUVW.z = UVW.x * _4x4_Texture[3] + UVW.y * _4x4_Texture[7] + _4x4_Texture[15];
if (IPUVW.z && (IPUVW.z != 1.0f))
{
IPUVW.x /= IPUVW.z;
IPUVW.y /= IPUVW.z;
}
/* Affect Here */
if (ulCurrentTexture != -1)
{
u32 PX,PY;
PX = (u32)(IPUVW.x * (float)GetUpperPO2(AllRef[ulCurrentTexture].pExtRef->SX));
PY = (u32)(IPUVW.y * (float)GetUpperPO2(AllRef[ulCurrentTexture].pExtRef->SY));
PX %= AllRef[ulCurrentTexture].pExtRef->SX;
PY %= AllRef[ulCurrentTexture].pExtRef->SY;
#ifdef DBG_DRAW_RED_PIXELS
*(AllRef[ulCurrentTexture].pExtRef->BASE + PX + PY * AllRef[ulCurrentTexture].pExtRef->PITCH) = 0xff0000;
UpdateTexture_BM_2_HW(ulCurrentTexture);
#endif
IPUVW.x = PX;
IPUVW.y = PY;
if (AlphaThreshold)
{
if (AlphaThreshold > (*(u32 *)(AllRef[ulCurrentTexture].pExtRef->BASE + PX + PY * AllRef[ulCurrentTexture].pExtRef->PITCH))>>24)
OKAffect = 0;
}
}
if (OKAffect)
{
#ifdef DBG_DRAW_PickedPrim
DrawLine(Color,Points + Indexes->I[0],Points + Indexes->I[1]);
DrawLine(Color,Points + Indexes->I[1],Points + Indexes->I[2]);
DrawLine(Color,Points + Indexes->I[2],Points + Indexes->I[0]);
DrawLine(Color,&IP3D,Points + Indexes->I[0]);
DrawLine(Color,&IP3D,Points + Indexes->I[1]);
DrawLine(Color,&IP3D,Points + Indexes->I[2]);
#endif
if (!CurrentRS.NOZWRITE)
{
MousePickingCurrentZ = IP.z;
}
MousePickingXYZ = IP3D;
MousePickingUVW = IPUVW;
MousePickingTri = Counter;
if (MotherClass)
{
memcpy(&MotherClass->PickReportResult,&MotherClass->PickReportCurrent,sizeof(PickingReport));
MotherClass->PickReportResult.CollidedMap = NULL;
if (ulCurrentTexture != -1)
MotherClass->PickReportResult.CollidedMap = AllRef[ulCurrentTexture].pExtRef;
if (MotherClass->PickReportResult.CollidedMap == NULL)
ulCurrentTexture = ulCurrentTexture;
MotherClass->PickReportResult.PickingCoordUV = MousePickingUVW;
MotherClass->PickReportResult.PickingCoordXYZ_Global = MotherClass->PickReportResult.CurrentGlobalMatrix * IP3D;
MotherClass->PickReportResult.PickingCoordXYZ_Local = IP3D;
}
}
}
}
}
Indexes++;
Indexes_UV++;
}
}
#ifdef DBG_DRAW_PickedPrim
SetRS(&CurrentRS,ulCurrentTexture);
#endif
RESTORE_MATRIXES();
STOP_RASTER(Picking);
}
void OGL_DI::PickQuad(u32 Color,float X, float Y,float Xsize, float Ysize,float TX,float TY,float TW,float TH)
{
if (MotherClass && MotherClass->PickReportCurrent.PickFrozed) return;
X-=MotherClass->PickReportCurrent.GrowCaptureSize;
Y-=MotherClass->PickReportCurrent.GrowCaptureSize;
Xsize += MotherClass->PickReportCurrent.GrowCaptureSize * 2.0f;
Ysize += MotherClass->PickReportCurrent.GrowCaptureSize * 2.0f;
Vector QuadXYZ[4] = {Vector(X,Y,ZQuad),Vector(X+Xsize,Y,ZQuad),Vector(X+Xsize,Y+Ysize,ZQuad),Vector(X,Y+Ysize,ZQuad)};;
Vector QuadUV[4] = {Vector(TX,TY,0),Vector(TX+TW,TY,0),Vector(TX+TW,TY+TH,0),Vector(TX,TY+TH,0)};
FaceIndex FIndexes[2] = {{0,1,2},{0,2,3}};
Mesh MyPMesh;
MyPMesh.NumberOfPoints = 4;
MyPMesh.NumberOfPointsUV = 4;
MyPMesh.Points = (Vector *)QuadXYZ;
MyPMesh.PointsUV = (Vector *)QuadUV;
MyPMesh.NumberOfFaces = 2;
MyPMesh.Indexes = (FaceIndex*)FIndexes;
MyPMesh.Indexes_UV = (FaceIndex*)FIndexes;
PickMesh(&MyPMesh,-1, 0);
}