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:
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: };
0232: