#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); }