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