283 lines
9.0 KiB
C
283 lines
9.0 KiB
C
/**************************************************************************************
|
|
|
|
File : PICKING.CPP
|
|
Author : Marc Villemain
|
|
Last update : 13 September 1996
|
|
|
|
***************************************************************************************/
|
|
|
|
|
|
#include "tde.h"
|
|
|
|
// Precision de la souris en pixels
|
|
#define C_PREC_SOURIS TDE_M_FloatToValue((float)3.0)
|
|
|
|
// Distance euclidienne entre deux points 2D
|
|
#define M_DistancePointPoint(A,B) TDE_M_Sqrt(TDE_M_Add(TDE_M_Sq(TDE_M_Sub(A->xX,B->xX)), \
|
|
TDE_M_Sq(TDE_M_Sub(A->xY,B->xY))))
|
|
|
|
|
|
|
|
static long lViewPortW, lViewPortH;
|
|
static TDE_tdsSuperObjectMatrix stSprMatrix;
|
|
|
|
void fn_vChangeRepere ( TDE_tdsVertex *p_stP,
|
|
TDE_tdsVertex *p_stA,
|
|
TDE_tdsVertex *p_stB,
|
|
TDE_tdsVertex *p_stC,
|
|
TDE_tdsVertex *p_stR )
|
|
{
|
|
TDE_tdsVertex stAB, stAC, stAP;
|
|
TDE_tdxValue denominateur;
|
|
|
|
// calcul des vecteurs de base du triangle
|
|
TDE_vSubVertexToVertex( p_stB, p_stA, &stAB) ;
|
|
TDE_vSubVertexToVertex( p_stC, p_stA, &stAC) ;
|
|
TDE_vSubVertexToVertex( p_stP, p_stA, &stAP) ;
|
|
|
|
// coordonnee de p_stP dans le repere A,AB,AC
|
|
denominateur = TDE_M_Sub(TDE_M_Mul(stAB.xX,stAC.xY),TDE_M_Mul(stAB.xY,stAC.xX));
|
|
|
|
p_stR->xX = TDE_M_Div(TDE_M_Sub(TDE_M_Mul(stAP.xX,stAC.xY),TDE_M_Mul(stAP.xY,stAC.xX)),
|
|
denominateur);
|
|
p_stR->xY = TDE_M_Div(TDE_M_Sub(TDE_M_Mul(stAB.xX,stAP.xY),TDE_M_Mul(stAB.xY,stAP.xX)),
|
|
denominateur);
|
|
}
|
|
|
|
|
|
BOOL GLI_bPickTriangle( TDE_tdsVertex *p_stSouris,
|
|
TDE_tdsVertex *p_stA,
|
|
TDE_tdsVertex *p_stB,
|
|
TDE_tdsVertex *p_stC )
|
|
{
|
|
TDE_tdsVertex stRet;
|
|
|
|
fn_vChangeRepere(p_stSouris, p_stA, p_stB, p_stC, &stRet);
|
|
|
|
/* on teste si le point est dans le triangle A,B,C */
|
|
if ( ( stRet.xX >= TDE_M_FloatToValue( 0.0 ))
|
|
&& ( stRet.xY >= TDE_M_FloatToValue( 0.0 ))
|
|
&& ( TDE_M_Add( stRet.xX, stRet.xY ) <= TDE_M_FloatToValue( 1.0 )))
|
|
return TRUE;
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL GLI_bPickPoly4( TDE_tdsVertex *p_stSouris,
|
|
TDE_tdsVertex *p_stA,
|
|
TDE_tdsVertex *p_stB,
|
|
TDE_tdsVertex *p_stC,
|
|
TDE_tdsVertex *p_stD )
|
|
{
|
|
BOOL ret1,ret2;
|
|
|
|
ret1 = GLI_bPickTriangle(p_stSouris,p_stA,p_stB,p_stC)
|
|
|| GLI_bPickTriangle(p_stSouris,p_stA,p_stC,p_stD);
|
|
|
|
ret2 = GLI_bPickTriangle(p_stSouris,p_stD,p_stA,p_stB)
|
|
|| GLI_bPickTriangle(p_stSouris,p_stD,p_stB,p_stC);
|
|
|
|
return ret1 && ret2;
|
|
}
|
|
|
|
|
|
BOOL GLI_bPickPoint( TDE_tdsVertex *p_stSouris,
|
|
TDE_tdsVertex *p_stA )
|
|
{
|
|
return M_DistancePointPoint(p_stSouris, p_stA) <= C_PREC_SOURIS;
|
|
}
|
|
|
|
|
|
BOOL GLI_bPickSegment( TDE_tdsVertex *p_stSouris,
|
|
TDE_tdsVertex *p_stP1,
|
|
TDE_tdsVertex *p_stP2 )
|
|
{
|
|
TDE_tdsVertex stA,stB,stC,stD; // vecteurs du quadrilatere
|
|
TDE_tdsVertex stDir,stNor; // vecteurs directeur et normal
|
|
|
|
// calcul des vecteurs directeur et normal
|
|
TDE_vSubVertexToVertex( p_stP2, p_stP1, &stDir) ;
|
|
stNor.xX = TDE_M_Neg(stDir.xY);
|
|
stNor.xY = stDir.xX;
|
|
|
|
// on leur donne la longueur C_PREC_SOURIS
|
|
TDE_vNormerVertex(&stDir, &stDir);
|
|
TDE_vNormerVertex(&stNor, &stNor);
|
|
TDE_vMulVertexToValue(&stDir, C_PREC_SOURIS, &stDir);
|
|
TDE_vMulVertexToValue(&stNor, C_PREC_SOURIS, &stNor);
|
|
|
|
stA.xX = TDE_M_Sub( TDE_M_Add( p_stP1->xX, stNor.xX ), stDir.xX );
|
|
stA.xY = TDE_M_Sub( TDE_M_Add( p_stP1->xY, stNor.xY ), stDir.xY );;
|
|
|
|
stB.xX = TDE_M_Sub( TDE_M_Sub( p_stP1->xX, stNor.xX ), stDir.xX );
|
|
stB.xY = TDE_M_Sub( TDE_M_Sub( p_stP1->xY, stNor.xY ), stDir.xY );;
|
|
|
|
stC.xX = TDE_M_Add( TDE_M_Sub( p_stP2->xX, stNor.xX ), stDir.xX );
|
|
stC.xY = TDE_M_Add( TDE_M_Sub( p_stP2->xY, stNor.xY ), stDir.xY );;
|
|
|
|
stD.xX = TDE_M_Add( TDE_M_Add( p_stP2->xX, stNor.xX ), stDir.xX );
|
|
stD.xY = TDE_M_Add( TDE_M_Add( p_stP2->xY, stNor.xY ), stDir.xY );
|
|
|
|
return GLI_bPickPoly4(p_stSouris, &stA, &stB, &stC, &stD);
|
|
}
|
|
|
|
|
|
BOOL GLI_bPickSprite( TDE_tdsVertex *p_stSouris,
|
|
TDE_tdsSprite *p_stSprite )
|
|
{
|
|
TDE_tdsRect stRect;
|
|
TDE_tdxValue xScaledSpriteW, xScaledSpriteH, xSpriteCenterY;
|
|
TDE_tdxValue xSpriteCornerX, xSpriteCornerY, xSpriteCenterX;
|
|
|
|
xScaledSpriteW = TDE_M_Mul(lViewPortW,p_stSprite->stDim.xX);
|
|
xScaledSpriteH = TDE_M_Mul(lViewPortH,p_stSprite->stDim.xY);
|
|
xSpriteCenterX = TDE_M_Mul(lViewPortW,stSprMatrix.stTranslateVertex.xX);
|
|
xSpriteCenterY = TDE_M_Mul(lViewPortH,stSprMatrix.stTranslateVertex.xY);
|
|
|
|
xSpriteCornerX = xSpriteCenterX - TDE_M_Div(xScaledSpriteW,2);
|
|
xSpriteCornerY = xSpriteCenterY - TDE_M_Div(xScaledSpriteH,2);
|
|
|
|
iTDE_vFillsRect(&stRect, xSpriteCornerX, xSpriteCornerY, xScaledSpriteW, xScaledSpriteH);
|
|
|
|
return GLI_bPickPoly4( p_stSouris,
|
|
&stRect.tdsSommet[0],
|
|
&stRect.tdsSommet[1],
|
|
&stRect.tdsSommet[2],
|
|
&stRect.tdsSommet[3] );
|
|
}
|
|
|
|
BOOL GLI_bPickSpriteAbs( TDE_tdsVertex *p_stSouris,
|
|
TDE_tdsSprite *p_stSprite,
|
|
TDE_tdxPixel *p_Color )
|
|
{
|
|
long decal;
|
|
TDE_tdsRect stRect;
|
|
TDE_tdxValue xScaledSpriteW, xScaledSpriteH, xSpriteCenterY;
|
|
TDE_tdxValue xSpriteCornerX, xSpriteCornerY, xSpriteCenterX;
|
|
|
|
xScaledSpriteW = p_stSprite->stDim.xX;
|
|
xScaledSpriteH = p_stSprite->stDim.xY;
|
|
xSpriteCenterX = stSprMatrix.stTranslateVertex.xX;
|
|
xSpriteCenterY = stSprMatrix.stTranslateVertex.xY;
|
|
|
|
xSpriteCornerX = xSpriteCenterX - TDE_M_Div(xScaledSpriteW,2);
|
|
xSpriteCornerY = xSpriteCenterY - TDE_M_Div(xScaledSpriteH,2);
|
|
|
|
iTDE_vFillsRect(&stRect, xSpriteCornerX, xSpriteCornerY, xScaledSpriteW, xScaledSpriteH);
|
|
|
|
decal = TDE_M_ValueToLong(p_stSprite->stDim.xX) * (TDE_M_ValueToLong(p_stSouris->xY)-TDE_M_ValueToLong(stRect.tdsSommet[0].xY)) + TDE_M_ValueToLong((p_stSouris->xX)-TDE_M_ValueToLong(stRect.tdsSommet[0].xX));
|
|
if( (decal < 0) || (decal >= p_stSprite->stDim.xX*p_stSprite->stDim.xY) )
|
|
{
|
|
*p_Color = 0;
|
|
return 0;
|
|
}
|
|
else
|
|
*p_Color = p_stSprite->v_pData[decal];
|
|
|
|
|
|
return GLI_bPickPoly4( p_stSouris,
|
|
&stRect.tdsSommet[0],
|
|
&stRect.tdsSommet[1],
|
|
&stRect.tdsSommet[2],
|
|
&stRect.tdsSommet[3] );
|
|
}
|
|
|
|
|
|
BOOL GLI_bPickLine( TDE_tdsVertex *p_stSouris,
|
|
TDE_tdsLine *p_stLine )
|
|
{
|
|
TDE_tdxAngle xAngle;
|
|
TDE_tdsVertex stP1, stP2;
|
|
|
|
// calcul des sommets P1 et P2 du segment
|
|
TDE_vGetTranslateVertexMatrix(&stSprMatrix, &stP1);
|
|
TDE_vGetAngleMatrix(&stSprMatrix, &xAngle);
|
|
stP2.xX = TDE_M_Mul( p_stLine->xLength, TDE_M_Cos(xAngle) );
|
|
stP2.xY = TDE_M_Mul( p_stLine->xLength, TDE_M_Sin(xAngle) );
|
|
TDE_vAddVertexToVertex(&stP1, &stP2, &stP2);
|
|
|
|
return GLI_bPickSegment( p_stSouris, &stP1, &stP2 );
|
|
}
|
|
|
|
|
|
BOOL GLI_bIsObjectPick( TDE_tdsVertex *p_stSouris,
|
|
TDE_tdeType eType,
|
|
void *p_stObject,
|
|
TDE_tdxPixel *p_Color )
|
|
{
|
|
switch(eType)
|
|
{
|
|
case TDE_eOT_SPRITE :
|
|
//return GLI_bPickSprite( p_stSouris, (TDE_tdsSprite *)p_stObject );
|
|
return GLI_bPickSpriteAbs( p_stSouris, (TDE_tdsSprite *)p_stObject, p_Color );
|
|
break;
|
|
|
|
case TDE_eOT_LINE :
|
|
return GLI_bPickLine( p_stSouris, (TDE_tdsLine *)p_stObject );
|
|
break;
|
|
|
|
default :
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
/*On trouve dans a_tdxSprObjPick[] les indices des fils successifs
|
|
pour arriver a l'objet sous la souris
|
|
le premier fils porte le numero 1 */
|
|
BOOL TDE_bGetSuperObjectPick( GLD_tdpstViewportAttributes p_stViewAttrib,
|
|
TDE_tdsVertex *p_stSouris,
|
|
TDE_tdstPickInfo *p_stPickInfo )
|
|
{
|
|
TDE_tdsSuperObject *p_stSprObjInter, *p_stSprObjPick;
|
|
BOOL ret = FALSE;
|
|
TDE_tdxPixel xColor;
|
|
int i;
|
|
|
|
p_stPickInfo->iNbSprPick = 0;
|
|
lViewPortW = p_stViewAttrib->dwWidth;
|
|
lViewPortH = p_stViewAttrib->dwHeight;
|
|
p_stSprObjPick = NULL;
|
|
|
|
for(i=0 ; i<TDE_kMAXPRIORITY ; i++)
|
|
{
|
|
p_stSprObjInter = TDE_g_apZList[i];
|
|
|
|
while (p_stSprObjInter != NULL)
|
|
{
|
|
stSprMatrix = p_stSprObjInter->stModifiedMatrix;
|
|
|
|
ret = GLI_bIsObjectPick(p_stSouris, p_stSprObjInter->eType, p_stSprObjInter->p_vPointer, &xColor);
|
|
if(ret)
|
|
{
|
|
int j;
|
|
|
|
j=p_stPickInfo->iNbSprPick-1;
|
|
while(j >= 0)
|
|
{
|
|
if( j < (TDE_kMAXPICK-1) )
|
|
p_stPickInfo->aDEF_stInfo[j+1] = p_stPickInfo->aDEF_stInfo[j];
|
|
j--;
|
|
}
|
|
|
|
if ( j < (TDE_kMAXPICK-1) )
|
|
{
|
|
p_stPickInfo->aDEF_stInfo[j+1].p_stSprObj = p_stSprObjInter;
|
|
p_stPickInfo->aDEF_stInfo[j+1].xColor = xColor;
|
|
if ( p_stPickInfo->iNbSprPick < TDE_kMAXPICK )
|
|
p_stPickInfo->iNbSprPick++;
|
|
}
|
|
}
|
|
|
|
p_stSprObjInter = p_stSprObjInter->p_stNextZList;
|
|
}
|
|
}
|
|
|
|
if(p_stPickInfo->iNbSprPick != 0)
|
|
{
|
|
ret = TRUE;
|
|
}
|
|
|
|
return ret;
|
|
}
|