0001: #include "stdafx.h"
0002: #include "math.h"
0003: #include "prim.h"
0004: 
0005: namespace Render {
0006: 
0007: // ---------------------------------------------------------------------------
0008: // 基本オブジェクト
0009: // ---------------------------------------------------------------------------
0010: void CPrimitive::Init(OBJ_DATA *pData)
0011: {
0012:     m_type=pData->type;
0013: 
0014:     this->m_material = pData->material;
0015: }
0016: // ---------------------------------------------------------------------------
0017: D3DXVECTOR3 *CPrimitive::GetColor(D3DXVECTOR3 *dest, float LN, float HN )
0018: {
0019:     *dest = *(D3DXVECTOR3*)&this->m_material.COLOR_AMB
0020:           + *(D3DXVECTOR3*)&this->m_material.COLOR_DIF * LN
0021:           + *(D3DXVECTOR3*)&this->m_material.COLOR_SPE * powf(HN, this->m_material.speq_power);
0022: 
0023:     return dest;
0024: }
0025: // ---------------------------------------------------------------------------
0026: // 球
0027: // ---------------------------------------------------------------------------
0028: CSphere::CSphere()
0029: {
0030: }
0031: // ---------------------------------------------------------------------------
0032: void CSphere::Init(OBJ_DATA *pData)
0033: {
0034:     ((CPrimitive*)this)->Init(pData);
0035: 
0036:     this->center.x = pData->sphere.center[0];
0037:     this->center.y = pData->sphere.center[1];
0038:     this->center.z = pData->sphere.center[2];
0039: 
0040:     radius_sq = pData->sphere.radius;
0041:     radius_sq *= radius_sq;
0042: }
0043: // ---------------------------------------------------------------------------
0044: float CSphere::IsAcross(D3DXVECTOR4 *n, D3DXVECTOR4 *p, const D3DXVECTOR4 *x, const D3DXVECTOR4 *v)
0045: {
0046:     FLOAT t, tp, tn;
0047: 
0048:     // 線分との判定
0049: 
0050:     D3DXVECTOR4 xc = (*x)-center;
0051:     FLOAT xc2 = D3DXVec3Dot((D3DXVECTOR3 *)&xc, (D3DXVECTOR3 *)&xc);
0052:     FLOAT vxc = D3DXVec3Dot((D3DXVECTOR3 *)v, (D3DXVECTOR3 *)&xc);
0053:     FLOAT D = sqrtf(vxc*vxc-xc2+radius_sq);
0054:     
0055:     if(D<0) return -INFINTY_DIST;
0056: 
0057:     tp = -vxc+D;
0058:     tn = -vxc-D;
0059: 
0060:     if(tn<0){
0061:         if(tp<0) return -INFINTY_DIST;
0062:         t = tp;
0063:     }else{
0064:         t = tn;
0065:     }
0066: 
0067:     *p = (*x)+t*(*v);
0068:     *n = *p-center;
0069:     D3DXVec3Normalize((D3DXVECTOR3*)n, (D3DXVECTOR3*)n);
0070: 
0071:     return t;
0072: }
0073: // ---------------------------------------------------------------------------
0074: // 3角形
0075: // ---------------------------------------------------------------------------
0076: CTriangle::CTriangle()
0077: {
0078: }
0079: // ---------------------------------------------------------------------------
0080: void CTriangle::Init(OBJ_DATA *pData)
0081: {
0082:     ((CPrimitive*)this)->Init(pData);
0083: 
0084:     this->pos[0] = D3DXVECTOR4( pData->triangle.x0[0],
0085:                                 pData->triangle.x0[1],
0086:                                 pData->triangle.x0[2],
0087:                                 1.0f);
0088:     this->pos[1] = D3DXVECTOR4( pData->triangle.x1[0],
0089:                                 pData->triangle.x1[1],
0090:                                 pData->triangle.x1[2],
0091:                                 1.0f);
0092:     this->pos[2] = D3DXVECTOR4( pData->triangle.x2[0],
0093:                                 pData->triangle.x2[1],
0094:                                 pData->triangle.x2[2],
0095:                                 1.0f);
0096: 
0097:     // 法線ベクトルの計算
0098:     D3DXVECTOR4 t0 = this->pos[1]-this->pos[0];
0099:     D3DXVECTOR4 t1 = this->pos[2]-this->pos[0];
0100:     D3DXVec3Cross((D3DXVECTOR3*)&normal, (D3DXVECTOR3*)&t1, (D3DXVECTOR3*)&t0);
0101:     D3DXVec3Normalize((D3DXVECTOR3*)&normal, (D3DXVECTOR3*)&normal);
0102:     normal.w = 0;
0103: }
0104: // ---------------------------------------------------------------------------
0105: float CTriangle::IsAcross(D3DXVECTOR4 *n, D3DXVECTOR4 *p, const D3DXVECTOR4 *x, const D3DXVECTOR4 *v)
0106: {
0107:     FLOAT t;
0108: 
0109:     // 線分との判定
0110:     D3DXVECTOR4 xp = this->pos[0]-(*x);
0111: 
0112:     FLOAT xpn = D3DXVec3Dot((D3DXVECTOR3 *)&xp, (D3DXVECTOR3 *)&normal);
0113:     FLOAT vn = D3DXVec3Dot((D3DXVECTOR3 *)v, (D3DXVECTOR3 *)&normal);
0114:     
0115:     if(-0.0000001f<=vn)return -INFINTY_DIST;// カリングと無限大を外す
0116: 
0117:     t = xpn/vn;
0118:     
0119:     if(t<0) return -INFINTY_DIST;// 後ろ向きのレイは無効
0120: 
0121:     *p = (*x)+t*(*v);
0122:     *n = normal;
0123: 
0124:     D3DXVECTOR4 d0, d1;
0125:     D3DXVECTOR3 c;
0126:     d0 = (*p)-this->pos[0];
0127:     d1 = this->pos[1]-this->pos[0];
0128:     D3DXVec3Cross(&c, (D3DXVECTOR3*)&d0, (D3DXVECTOR3*)&d1);
0129:     if(D3DXVec3Dot(&c, (D3DXVECTOR3 *)&normal)<0)return -INFINTY_DIST;
0130:     d0 = (*p)-this->pos[1];
0131:     d1 = this->pos[2]-this->pos[1];
0132:     D3DXVec3Cross(&c, (D3DXVECTOR3*)&d0, (D3DXVECTOR3*)&d1);
0133:     if(D3DXVec3Dot(&c, (D3DXVECTOR3 *)&normal)<0)return -INFINTY_DIST;
0134:     d0 = (*p)-this->pos[2];
0135:     d1 = this->pos[0]-this->pos[2];
0136:     D3DXVec3Cross(&c, (D3DXVECTOR3*)&d0, (D3DXVECTOR3*)&d1);
0137:     if(D3DXVec3Dot(&c, (D3DXVECTOR3 *)&normal)<0)return -INFINTY_DIST;
0138:     
0139:     return t;
0140: }
0141: 
0142: 
0143: // ---------------------------------------------------------------------------
0144: // ---------------------------------------------------------------------------
0145: // オブジェクト
0146: // ---------------------------------------------------------------------------
0147: // ---------------------------------------------------------------------------
0148: // コンストラクタ
0149: CMesh::CMesh()
0150: {
0151:     m_num = 0;
0152:     m_ppPrim = NULL;
0153: }
0154: // ---------------------------------------------------------------------------
0155: CMesh::~CMesh()
0156: {
0157:     Delete();
0158: }
0159: // ---------------------------------------------------------------------------
0160: void CMesh::Init(OBJ_DATA *pData, int num)
0161: {
0162:     this->m_num = num;
0163:     
0164:     m_ppPrim = new CPrimitive*[num];
0165: 
0166:     for(int i=0;i<num;i++){
0167:         switch(pData[i].type){
0168:         case OBJ_TYPE_SPHERE:
0169:             m_ppPrim[i] = new CSphere();
0170:             ((CSphere*)m_ppPrim[i])->Init(pData+i);
0171:             break;
0172:         case OBJ_TYPE_TRIANGLE:
0173:             m_ppPrim[i] = new CTriangle();
0174:             ((CTriangle*)m_ppPrim[i])->Init(pData+i);
0175:             break;
0176:         }
0177:     }
0178: }
0179: // ---------------------------------------------------------------------------
0180: void CMesh::Delete()
0181: {
0182:     int i;
0183: 
0184:     if(m_ppPrim){
0185:         for(i=0;i<m_num;i++){
0186:             if(m_ppPrim[i]) {delete m_ppPrim[i];m_ppPrim[i]=NULL;}
0187:         }
0188:         delete[] m_ppPrim;
0189:         m_ppPrim = NULL;
0190:     }
0191:     m_num = 0;
0192: }
0193: // ---------------------------------------------------------------------------
0194: float CMesh::IsAcross(float dist, D3DXVECTOR4 *n, D3DXVECTOR4 *p, CPrimitive **dest, const D3DXVECTOR4 *x, const D3DXVECTOR4 *v)
0195: {
0196:     float ttmp;
0197:     D3DXVECTOR4 ntmp, ptmp;
0198: 
0199:     for(int i = 0; i<m_num; i++){
0200:         switch(m_ppPrim[i]->m_type){
0201:         case OBJ_TYPE_SPHERE:
0202:             ttmp = ((CSphere*)m_ppPrim[i])->IsAcross(&ntmp, &ptmp, x, v);
0203:             break;
0204:         case OBJ_TYPE_TRIANGLE:
0205:             ttmp = ((CTriangle*)m_ppPrim[i])->IsAcross(&ntmp, &ptmp, x, v);
0206:             break;
0207:         }
0208:         if(0<=ttmp && ttmp<dist){
0209:             dist = ttmp;
0210:             *n = ntmp;
0211:             *p = ptmp;
0212:             *dest = m_ppPrim[i];
0213:         }
0214:     }
0215: 
0216:     return dist;
0217: }
0218: // ---------------------------------------------------------------------------
0219: bool CMesh::IsAcross(float dist, const D3DXVECTOR4 *x, const D3DXVECTOR4 *v)
0220: {
0221:     D3DXVECTOR4 ntmp, ptmp;
0222: 
0223:     for(int i = 0; i<m_num; i++){
0224:         float d;
0225:         switch(m_ppPrim[i]->m_type){
0226:         case OBJ_TYPE_SPHERE:
0227:             d = ((CSphere*)m_ppPrim[i])->IsAcross(&ntmp, &ptmp, x, v);
0228:             break;
0229:         case OBJ_TYPE_TRIANGLE:
0230:             d = ((CTriangle*)m_ppPrim[i])->IsAcross(&ntmp, &ptmp, x, v);
0231:             break;
0232:         }
0233:         if(0.001*dist<=d && d<0.99f*dist) return TRUE;
0234:     }
0235: 
0236:     return FALSE;
0237: }
0238: 
0239: 
0240: };// namespace Render
0241: