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