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: // ---------------------------------------------------------------------------
0075: // 3角形
0076: // ---------------------------------------------------------------------------
0077: CTriangle::CTriangle()
0078: {
0079: }
0080: // ---------------------------------------------------------------------------
0081: void CTriangle::Init(OBJ_DATA *pData)
0082: {
0083:     ((CPrimitive*)this)->Init(pData);
0084: 
0085:     this->pos[0] = D3DXVECTOR4( pData->triangle.x0[0],
0086:                                 pData->triangle.x0[1],
0087:                                 pData->triangle.x0[2],
0088:                                 1.0f);
0089:     this->pos[1] = D3DXVECTOR4( pData->triangle.x1[0],
0090:                                 pData->triangle.x1[1],
0091:                                 pData->triangle.x1[2],
0092:                                 1.0f);
0093:     this->pos[2] = D3DXVECTOR4( pData->triangle.x2[0],
0094:                                 pData->triangle.x2[1],
0095:                                 pData->triangle.x2[2],
0096:                                 1.0f);
0097: 
0098:     // 法線ベクトルの計算
0099:     D3DXVECTOR4 t0 = this->pos[1]-this->pos[0];
0100:     D3DXVECTOR4 t1 = this->pos[2]-this->pos[0];
0101:     D3DXVec3Cross((D3DXVECTOR3*)&normal, (D3DXVECTOR3*)&t1, (D3DXVECTOR3*)&t0);
0102:     D3DXVec3Normalize((D3DXVECTOR3*)&normal, (D3DXVECTOR3*)&normal);
0103:     normal.w = 0;
0104: }
0105: // ---------------------------------------------------------------------------
0106: float CTriangle::IsAcross(D3DXVECTOR4 *n, D3DXVECTOR4 *p, const D3DXVECTOR4 *x, const D3DXVECTOR4 *v)
0107: {
0108:     FLOAT t;
0109: 
0110:     // 線分との判定
0111:     D3DXVECTOR4 xp = this->pos[0]-(*x);
0112: 
0113:     FLOAT xpn = D3DXVec3Dot((D3DXVECTOR3 *)&xp, (D3DXVECTOR3 *)&normal);
0114:     FLOAT vn = D3DXVec3Dot((D3DXVECTOR3 *)v, (D3DXVECTOR3 *)&normal);
0115:     
0116:     if(-0.00001f<=vn)return -INFINTY_DIST;// カリングと無限大を外す
0117: 
0118:     t = xpn/vn;
0119:     
0120:     if(t<0) return -INFINTY_DIST;// 後ろ向きのレイは無効
0121: 
0122:     *p = (*x)+t*(*v);
0123:     *n = normal;
0124: 
0125:     D3DXVECTOR4 d0, d1;
0126:     D3DXVECTOR3 c;
0127:     d0 = (*p)-this->pos[0];
0128:     d1 = this->pos[1]-this->pos[0];
0129:     D3DXVec3Cross(&c, (D3DXVECTOR3*)&d1, (D3DXVECTOR3*)&d0);
0130:     if(D3DXVec3Dot(&c, (D3DXVECTOR3 *)&normal)>0)return -INFINTY_DIST;
0131:     d0 = (*p)-this->pos[1];
0132:     d1 = this->pos[2]-this->pos[1];
0133:     D3DXVec3Cross(&c, (D3DXVECTOR3*)&d1, (D3DXVECTOR3*)&d0);
0134:     if(D3DXVec3Dot(&c, (D3DXVECTOR3 *)&normal)>0)return -INFINTY_DIST;
0135:     d0 = (*p)-this->pos[2];
0136:     d1 = this->pos[0]-this->pos[2];
0137:     D3DXVec3Cross(&c, (D3DXVECTOR3*)&d1, (D3DXVECTOR3*)&d0);
0138:     if(D3DXVec3Dot(&c, (D3DXVECTOR3 *)&normal)>0)return -INFINTY_DIST;
0139:     
0140:     return t;
0141: }
0142: 
0143: 
0144: 
0145: // ---------------------------------------------------------------------------
0146: // ---------------------------------------------------------------------------
0147: // オブジェクト
0148: // ---------------------------------------------------------------------------
0149: // ---------------------------------------------------------------------------
0150: // コンストラクタ
0151: CMesh::CMesh()
0152: {
0153:     m_num = 0;
0154:     m_ppPrim = NULL;
0155: }
0156: // ---------------------------------------------------------------------------
0157: CMesh::~CMesh()
0158: {
0159:     Delete();
0160: }
0161: // ---------------------------------------------------------------------------
0162: void CMesh::Init(OBJ_DATA *pData, int num)
0163: {
0164:     this->m_num = num;
0165:     
0166:     m_ppPrim = new CPrimitive*[num];
0167: 
0168:     for(int i=0;i<num;i++){
0169:         switch(pData[i].type){
0170:         case OBJ_TYPE_SPHERE:
0171:             m_ppPrim[i] = new CSphere();
0172:             ((CSphere*)m_ppPrim[i])->Init(pData+i);
0173:             break;
0174:         case OBJ_TYPE_TRIANGLE:
0175:             m_ppPrim[i] = new CTriangle();
0176:             ((CTriangle*)m_ppPrim[i])->Init(pData+i);
0177:             break;
0178:         }
0179:     }
0180: }
0181: // ---------------------------------------------------------------------------
0182: void CMesh::Delete()
0183: {
0184:     int i;
0185: 
0186:     if(m_ppPrim){
0187:         for(i=0;i<m_num;i++){
0188:             if(m_ppPrim[i]) {delete m_ppPrim[i];m_ppPrim[i]=NULL;}
0189:         }
0190:         delete[] m_ppPrim;
0191:         m_ppPrim = NULL;
0192:     }
0193:     m_num = 0;
0194: }
0195: // ---------------------------------------------------------------------------
0196: float CMesh::IsAcross(float dist, D3DXVECTOR4 *n, D3DXVECTOR4 *p, CPrimitive **dest, const D3DXVECTOR4 *x, const D3DXVECTOR4 *v)
0197: {
0198:     float ttmp;
0199:     D3DXVECTOR4 ntmp, ptmp;
0200: 
0201:     for(int i = 0; i<m_num; i++){
0202:         switch(m_ppPrim[i]->m_type){
0203:         case OBJ_TYPE_SPHERE:
0204:             ttmp = ((CSphere*)m_ppPrim[i])->IsAcross(&ntmp, &ptmp, x, v);
0205:             break;
0206:         case OBJ_TYPE_TRIANGLE:
0207:             ttmp = ((CTriangle*)m_ppPrim[i])->IsAcross(&ntmp, &ptmp, x, v);
0208:             break;
0209:         }
0210:         if(0<=ttmp && ttmp<dist){
0211:             dist = ttmp;
0212:             *n = ntmp;
0213:             *p = ptmp;
0214:             *dest = m_ppPrim[i];
0215:         }
0216:     }
0217: 
0218:     return dist;
0219: }
0220: // ---------------------------------------------------------------------------
0221: bool CMesh::IsAcross(float dist, const D3DXVECTOR4 *x, const D3DXVECTOR4 *v)
0222: {
0223:     D3DXVECTOR4 ntmp, ptmp;
0224: 
0225:     for(int i = 0; i<m_num; i++){
0226:         float d;
0227:         switch(m_ppPrim[i]->m_type){
0228:         case OBJ_TYPE_SPHERE:
0229:             d = ((CSphere*)m_ppPrim[i])->IsAcross(&ntmp, &ptmp, x, v);
0230:             break;
0231:         case OBJ_TYPE_TRIANGLE:
0232:             d = ((CTriangle*)m_ppPrim[i])->IsAcross(&ntmp, &ptmp, x, v);
0233:             break;
0234:         }
0235:         if(0.001*dist<=d && d<0.99f*dist) return TRUE;
0236:     }
0237: 
0238:     return FALSE;
0239: }
0240: 
0241: 
0242: };// namespace Render
0243: