reman3/Rayman_X/cpa/tempgrp/TDE/tde_pick.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;
}