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