//============================================================================== // プレイヤー判定スキップ //============================================================================== void CGame::PushBackBattleArea(void) { // 判定 CPlayer* pPlayerCurrent = nullptr; // 対象オブジェクト for (int cntPlayer = 0; cntPlayer < PLAYER_MAX; ++cntPlayer) { // 対象オブジェクトを取得 pPlayerCurrent = Player[cntPlayer]; // 対象のステートを確認 if (NeedsSkipPlayer(pPlayerCurrent)) { continue; } // 押し戻し VECTOR3 vectorPlayerToCenter = Ground->Pos() - pPlayerCurrent->Pos(); vectorPlayerToCenter.y = 0.0f; float distanceFromCenter = vectorPlayerToCenter.x * vectorPlayerToCenter.x + vectorPlayerToCenter.y * vectorPlayerToCenter.y + vectorPlayerToCenter.z * vectorPlayerToCenter.z; if (distanceFromCenter > (RADIUS_AREA_BATTLE - RADIUS_PUSH_CHARACTER) * (RADIUS_AREA_BATTLE - RADIUS_PUSH_CHARACTER)) { float distancePushBack = sqrtf(distanceFromCenter) - (RADIUS_AREA_BATTLE - RADIUS_PUSH_CHARACTER); vectorPlayerToCenter.Normalize(); pPlayerCurrent->AddPos(vectorPlayerToCenter * distancePushBack); pPlayerCurrent->AddDestPos(vectorPlayerToCenter * distancePushBack); } } }
/// Computes the angular velocity of a body given the current quaternion orientation and the quaternion velocity VECTOR3 QUAT::to_omega(const QUAT& q, const QUAT& qd) { VECTOR3 omega; omega.x() = 2 * (-q.x * qd.w + q.w * qd.x - q.z * qd.y + q.y * qd.z); omega.y() = 2 * (-q.y * qd.w + q.z * qd.x + q.w * qd.y - q.x * qd.z); omega.z() = 2 * (-q.z * qd.w - q.y * qd.x + q.x * qd.y + q.w * qd.z); return omega; }
//============================================================================== // 着弾地点判定 //============================================================================== void CGame::HitBulletToField(void) { VECTOR3 nor; float height; CBillboard* mark; VECTOR3 markPos; CBallistic* ballistic = Player[CManager::netData.charNum]->GetBallistic(); CPolygon3D* landing = ballistic->GetLanding(); for(int cnt = 0; cnt < MARK_MAX; ++cnt) { // 初期化 nor = VECTOR3(0.0f,0.0f,0.0f); height = 0.0f; // マーク情報 mark = ballistic->GetMark(cnt); markPos = mark->Pos(); // 高さ判定 height = Ground->GetHeight(markPos - VECTOR3(0.0f, BULLET_SIZE * 0.5f, 0.0f), &nor); if(height >= markPos.y) { // 回転を求める VECTOR3 vectorUp(0.0f, 1.0f, 0.0f); // 上方向ベクトル VECTOR3 vectorAxisRotation; // 回転軸 float rotation = 0.0f; // 回転量 VECTOR3::Cross(&vectorAxisRotation, nor, vectorUp); if (vectorAxisRotation.x < FLT_EPSILON && vectorAxisRotation.x > -FLT_EPSILON) { if (vectorAxisRotation.z < FLT_EPSILON && vectorAxisRotation.z > -FLT_EPSILON) { if (vectorAxisRotation.y < FLT_EPSILON && vectorAxisRotation.y > -FLT_EPSILON) { vectorAxisRotation.y = 1.0f; } } } vectorAxisRotation.Normalize(); rotation = VECTOR3::Dot(nor, vectorUp); if (rotation <= 1.0f && rotation >= -1.0f) { rotation = RAD_TO_DEG * acosf(rotation); } else { rotation = 0.0f; } // 着弾マークに設定する landing->SetPos(VECTOR3(markPos.x, height + 0.5f, markPos.z)); landing->SetAxisRotation(vectorAxisRotation); landing->SetRotationAxis(rotation); break; } } }
float FieldData::getFieldMag(float point[3]) { VECTOR3 pos(point[0],point[1],point[2]); VECTOR3 vel; int rc = pField->getFieldValue( pos, (float)timeStep, vel); if (rc < 0) return -1.f; return vel.GetMag(); }
/** * This matrix is used in the relationships omega' = 2*L*qd and * alpha' = 2*L*qdd, where omega'/alpha' are the angular velocity/acceleration * of a rigid body in the body's frame and qd/qdd are the first/second time * derivatives of the Euler (unit quaternion) parameters. * * The matrix L is defined as: * -e1 e0 e3 -e2 * -e2 -e3 e0 e1 * -e3 e2 -e1 e0 */ VECTOR3 QUAT::L_mult(REAL qx, REAL qy, REAL qz, REAL qw) const { const double& e0 = w; const double& e1 = x; const double& e2 = y; const double& e3 = z; VECTOR3 v; v.x() = -e1*qw + e0*qx + e3*qy - e2*qz; v.y() = -e2*qw - e3*qx + e0*qy + e1*qz; v.z() = -e3*qw + e2*qx - e1*qy + e0*qz; return v; }
/** * This matrix is used in the relationships omega = 2*G*qd and * alpha = 2*G*qdd, where omega/alpha are the angular velocity/acceleration * of a rigid body in the game frame and qd/qdd are the first/second time * derivatives of the Euler (unit quaternion) parameters. */ VECTOR3 QUAT::G_mult(REAL qx, REAL qy, REAL qz, REAL qw) const { const double e0 = qw; const double e1 = qx; const double e2 = qy; const double e3 = qz; VECTOR3 r; r.x() = -x*e0 + w*e1 - z*e2 + y*e3; r.y() = -y*e0 + z*e1 + w*e2 - x*e3; r.z() = -z*e0 - y*e1 + x*e2 + w*e3; return r; }
/** * The local axis for this joint does not take the orientation of the * inboard link into account; thus, if the orientation of the inboard link * changes, then the local axis remains constant. * \param axis a unit vector * \sa get_axis_global() * \sa set_axis_global() */ void PRISMATICJOINT::set_axis(const VECTOR3& axis) { // check that axis is ok if (std::fabs(axis.norm() - (REAL) 1.0) > EPS) throw UndefinedAxisException(); // normalize the axis, in case caller did not VECTOR3 naxis = VECTOR3::normalize(axis); // transform axis to joint frame _u = POSE3::transform_vector(get_pose(), naxis); // setup v1i and v1j VECTOR3::determine_orthonormal_basis(_u, _v1i, _v1j); // set _ui VECTOR3 outboard_origin(0.0, 0.0, 0.0, _Fb); _ui = POSE3::transform_point(_F, outboard_origin); // set _uj _uj = POSE3::transform_vector(_Fb, _v1i); // set the joint axis in the inner link frame update_spatial_axes(); }
void get_color_entropy(float& r,float& g,float& b,float& a,VECTOR3 p,int* grid_res) { if(!entropies) return; int x=p.x(); int y=p.y(); int z=p.z(); int idx=x+y*grid_res[0]+z*grid_res[0]*grid_res[1]; float val=entropies[idx]; r=val; if(val<0.5) g=2*val; else g=2-2*val; b=1-val; a=val; }
////////////////////////////////////////////////////////////////////////// // get value of node id at time step t // input // id: node Id // t: time step in check // output // nodeData: vector value at this node // return // 1: operation successful // -1: invalid id ////////////////////////////////////////////////////////////////////////// int Solution::GetValue(int id, float t, VECTOR3& nodeData) { float adjusted_t = t - m_MinT; if((id < 0) || (id >= m_nNodeNum) || (adjusted_t < 0.0) || (adjusted_t > (float)(m_nTimeSteps-1))) return -1; if(!isTimeVarying()) nodeData = m_pDataArray[(int)adjusted_t][id]; else { int lowT, highT; float ratio; lowT = (int)floor(adjusted_t); ratio = adjusted_t - (float)floor(adjusted_t); highT = lowT + 1; if(lowT >= (m_nTimeSteps-1)) { highT = lowT; ratio = 0.0; } nodeData.Set(Lerp(m_pDataArray[lowT][id][0], m_pDataArray[highT][id][0], ratio), Lerp(m_pDataArray[lowT][id][1], m_pDataArray[highT][id][1], ratio), Lerp(m_pDataArray[lowT][id][2], m_pDataArray[highT][id][2], ratio)); } return 1; }
// get the min and max value for all time steps int Solution::GetMinMaxValueAll(VECTOR3& minVal, VECTOR3& maxVal) { minVal = m_pMinValue[0]; maxVal = m_pMaxValue[0]; for(int tFor = 1; tFor < m_nTimeSteps; tFor++) { if(minVal.GetMag() > m_pMinValue[tFor].GetMag()) minVal = m_pMinValue[tFor]; if(maxVal.GetMag() < m_pMaxValue[tFor].GetMag()) maxVal = m_pMaxValue[tFor]; } return 1; }
void IMainGame::mFunction_GameOverAnimationInit(BOOL hasPlayerWon) { static std::default_random_engine rndEngine; static std::uniform_real_distribution<float> unitDist(-1.0f, 1.0f); if (hasPlayerWon) { mMainGameState = GameState::MainGame::GS_DeathExplode; //clear bullets mBulletMgr.KillAllBullet(); //player WIN mIsPlayerVictorious = TRUE; //set camera to look at chicken gCamera.SetLookAt(mChickenBoss.GetPosition()); //..explode fireworks for (int i = 0;i < 2000;++i) { //shoot direction (add some random offset) VECTOR3 dir = { unitDist(rndEngine),unitDist(rndEngine) ,unitDist(rndEngine) }; //Y direction offset ( a whole column of bullets) dir.Normalize(); mBulletMgr.SpawnBullet(mChickenBoss.GetPosition(), dir, VECTOR3(1, 0,0)); } } else { mMainGameState = GameState::MainGame::GS_DeathExplode; //clear bullets mBulletMgr.KillAllBullet(); //player LOSE mIsPlayerVictorious = FALSE; //..explode fireworks for (int i = 0;i < 2000;++i) { //shoot direction (add some random offset) VECTOR3 dir = { unitDist(rndEngine),unitDist(rndEngine) ,unitDist(rndEngine) }; //Y direction offset ( a whole column of bullets) dir.Normalize(); mBulletMgr.SpawnBullet(mPlayer.GetPosition(), dir, VECTOR3(1, 0, 0)); } //move to another position to watch the explosion gCamera.SetPosition(mPlayer.GetPosition() + VECTOR3(300.0f,300.0f,300.0f)); gCamera.SetLookAt(mPlayer.GetPosition()); } }
//============================================================================== // オブジェクトの地形による押し戻し //============================================================================== void CGame::PushBackObjectByField(CObject* pObject, float offsetY) { // 地形とのあたり判定 VECTOR3 NormalGround; // 地形の法線 float HeightGround; // 地形の高さ HeightGround = Ground->GetHeight(pObject->Pos(), &NormalGround) + offsetY; //******************************************************** // 2015_02_12 姿勢制御用の処理を追加 ここから //******************************************************** // 回転を求める VECTOR3 vectorUp(0.0f, 1.0f, 0.0f); // 上方向ベクトル VECTOR3 vectorAxisRotation; // 回転軸 float rotation = 0.0f; // 回転量 VECTOR3::Cross(&vectorAxisRotation, NormalGround, vectorUp); if (vectorAxisRotation.x < FLT_EPSILON && vectorAxisRotation.x > -FLT_EPSILON) { if (vectorAxisRotation.z < FLT_EPSILON && vectorAxisRotation.z > -FLT_EPSILON) { if (vectorAxisRotation.y < FLT_EPSILON && vectorAxisRotation.y > -FLT_EPSILON) { vectorAxisRotation.y = 1.0f; } } } vectorAxisRotation.Normalize(); rotation = VECTOR3::Dot(NormalGround, vectorUp); if (rotation <= 1.0f && rotation >= -1.0f) { rotation = RAD_TO_DEG * acosf(rotation); } else { rotation = 0.0f; } // キャラクターに設定する pObject->SetPosY(HeightGround); pObject->SetDestPosY(HeightGround); pObject->SetAxisRotation(vectorAxisRotation); pObject->SetRotationAxis(rotation); //******************************************************** // 2015_02_12 姿勢制御用の処理を追加 ここまで //******************************************************** }
TRIANGLE::TRIANGLE(VECTOR3 v1, VECTOR3 v2, VECTOR3 v3, VECTOR3 norm, COLOR col) { vertex[0] = v1; vertex[1] = v2; vertex[2] = v3; if(norm.isNull()) computeNormal(); else normal = norm; color = col; }
int GetListOrder() { register int order=0; glPushMatrix(); glLoadIdentity(); object.trackball.apply_inverse_transform(); GLdouble m[16]; glGetDoublev(GL_MODELVIEW_MATRIX, m); matrix4f tm(m[0], m[4], m[8], m[12], m[1], m[5], m[9], m[13], m[2], m[6], m[10], m[14], m[3], m[7], m[11], m[15]); tm = tm.inverse(); tm = tm.transpose(); vec3f splat_normal(0, 0, 1); tm.mult_matrix_vec(splat_normal); splat_normal.normalize(); float max = -1; float dm; for (int i=0; i<SORTED_LIST_NUM; i++){ VECTOR3 s(splat_normal[0], splat_normal[1], splat_normal[2]); VECTOR3 t = viewer.eyes[i]; t.Normalize(); dm = dot(t, s); if (dm>max){ order = i; max = dm; } } glPopMatrix(); return order; }
int vtCStreamLine::AdvectOneStep(TIME_DIR time_dir, INTEG_ORD integ_ord, TIME_DEP time_dep, PointInfo& seedInfo, VECTOR3& finalP) { int istat; PointInfo thisParticle; VECTOR3 vel; float curTime = m_fCurrentTime; float dt = m_fInitialStepSize; finalP.Set(-1, -1, -1); thisParticle = seedInfo; // the first point istat = m_pField->at_phys(seedInfo.fromCell, seedInfo.phyCoord, seedInfo, m_fCurrentTime, vel); if(istat == OUT_OF_BOUND) return OUT_OF_BOUND; if((fabs(vel[0]) < m_fStationaryCutoff) && (fabs(vel[1]) < m_fStationaryCutoff) && (fabs(vel[2]) < m_fStationaryCutoff)) return CRITICAL_POINT; float error; if(integ_ord == SECOND) istat = runge_kutta2(time_dir, time_dep, thisParticle, &curTime, dt); else if(integ_ord == FOURTH) istat = runge_kutta4(time_dir, time_dep, thisParticle, &curTime, dt); else if(integ_ord == RK45) istat = runge_kutta45(time_dir, time_dep, thisParticle, &curTime, dt, &error); else return OUT_OF_BOUND; if(istat == OUT_OF_BOUND) // out of boundary return OUT_OF_BOUND; m_pField->at_phys(thisParticle.fromCell, thisParticle.phyCoord, thisParticle, m_fCurrentTime, vel); if((fabs(vel[0]) < m_fStationaryCutoff) && (fabs(vel[1]) < m_fStationaryCutoff) && (fabs(vel[2]) < m_fStationaryCutoff)) return CRITICAL_POINT; else finalP = thisParticle.phyCoord; return OKAY; }
//load seeds float* get_grid_vec_data(int* grid_res)//get vec data at each grid point { osuflow->GetFlowField()->getDimension(grid_res[0],grid_res[1],grid_res[2]); float * vectors=new float[grid_res[0]*grid_res[1]*grid_res[2]*3]; for(int k=0; k<grid_res[2];k++) { for(int j=0; j<grid_res[1];j++) { for(int i=0; i<grid_res[0];i++) { VECTOR3 data; osuflow->GetFlowField()->at_vert(i,j,k,0,data);//t=0, static data int idx=i+j*grid_res[0]+k*grid_res[0]*grid_res[1]; data.Normalize(); vectors[idx*3+0]=data.x(); vectors[idx*3+1]=data.y(); vectors[idx*3+2]=data.z(); } } } return vectors; }
bool TRIANGLE::intersect(POINT origin, VECTOR3 direction, double &depth) const { //algorithm used: http://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm //QVector3D d = direction; VECTOR3 e1 = vertex[1] - vertex[0]; VECTOR3 e2 = vertex[2] - vertex[0]; VECTOR3 p = direction.cross(e2);// QVector3D::crossProduct(d, e2); double det = e1.dot(p);// QVector3D::dotProduct(e1, p); if(det > -EPSILON && det < EPSILON) return false; double inv_det = 1.f / det; VECTOR3 t = VECTOR3(origin) - vertex[0]; double u = (t.dot(p) * inv_det); // QVector3D::dotProduct(t, p) * inv_det); if(u < 0.f || u > 1.f) return false; //QVector3D q = QVector3D::crossProduct(t, e1); VECTOR3 q = t.cross(e1); double v = direction.dot(q) * inv_det; // (QVector3D::dotProduct(d, q) * inv_det); if(v < 0.f || (u + v) > 1.f) return false; double dist = e2.dot(q) * inv_det; // QVector3D::dotProduct(e2, q) * inv_det; if(dist > EPSILON) { //DEBUG PRINT //std::cout << "getRayIntersection - Treffer: " << dist << std::endl; depth = dist; return true; } return false; }
/** * Note that the derivative is not generally a unit quaternion. * \param q the current orientation * \param w the angular velocity (in the global frame) * Uses the matrix: * | -q.x +q.w -q.z +q.y | * G = | -q.y +q.z +q.w -q.x | * | -q.z -q.y +q.x +q.w | */ QUAT QUAT::deriv(const QUAT& q, const VECTOR3& w) { QUAT qd; qd.w = .5 * (-q.x * w.x() - q.y * w.y() - q.z * w.z()); qd.x = .5 * (+q.w * w.x() + q.z * w.y() - q.y * w.z()); qd.y = .5 * (-q.z * w.x() + q.w * w.y() + q.x * w.z()); qd.z = .5 * (+q.y * w.x() - q.x * w.y() + q.w * w.z()); return qd; }
////////////////////////////////////////////////////////////////////////// // get the physical coordinate of the vertex // // input: // verIdx: index of vertex // output: // pos: physical coordinate of vertex ////////////////////////////////////////////////////////////////////////// ReturnStatus CurvilinearGrid::at_vertex(int verIdx, VECTOR3& pos) { int totalVer = xdim() * ydim() * zdim(); if ((verIdx < 0) || (verIdx >= totalVer)) return OUT_OF_BOUND; /* zidx = verIdx / (xdim() * ydim()); yidx = verIdx % (xdim() * ydim()); yidx = verIdx / xdim(); xidx = verIdx - zidx * xdim() * ydim() - yidx * xdim(); */ float xpos = m_pVertex[verIdx][0]; float ypos = m_pVertex[verIdx][1]; float zpos = m_pVertex[verIdx][2]; // pos.set((float)xidx, (float)yidx, (float)zidx); pos.set(xpos, ypos, zpos); return SUCCESS; }
/** * This matrix is used in the relationships qd = 1/2*L^T*omega and * qdd = 1/2*L^T*alpha' - 1/4*omega'^2*q, where omega'/alpha' are the angular * velocity/acceleration of a rigid body in the body frame and qd/qdd are the * first/second time derivatives of the Euler (unit quaternion) parameters. * * The matrix L is defined as: * -e1 e0 e3 -e2 * -e2 -e3 e0 e1 * -e3 e2 -e1 e0 */ QUAT QUAT::L_transpose_mult(const VECTOR3& v) const { double de0 = -x*v.x() - y*v.y() - z*v.z(); double de1 = +w*v.x() - z*v.y() + y*v.z(); double de2 = +z*v.x() + w*v.y() - x*v.z(); double de3 = -y*v.x() + x*v.y() + w*v.z(); QUAT q; q.w = de0; q.x = de1; q.y = de2; q.z = de3; return q; }
// Compute orientation of e with respect to quadrilateral abcd // by treating abcd as two triangles: abc and acd. // // Let there be a viewer who sees abcd counter-clockwise (e.g. from // a position inside a 3-cell). Return: // // 1 if e on same side of quadrilateral abcd as viewer // -1 if e on opposite side of quadrilateral abcd with respect to viewer // 0 if e is coplanar with abcd // // The result is computed by doing two orientation tests, one for e // with respect to abc, and one for e with respect to acd. // If these two tests agree, we're done, if they don't, then we // do more work to figure out what case we're in. // int FEL_orient(const VECTOR3& a, const VECTOR3& b, const VECTOR3& c, const VECTOR3& d, const VECTOR3& e) { const int verbosity = 0; VECTOR3 ba = (b - a); VECTOR3 ca = (c - a); VECTOR3 da = (d - a); VECTOR3 ea = (e - a); int abc_orient = sign(dot(ea, cross(ba, ca))); int acd_orient = sign(dot(ea, cross(ca, da))); if (abc_orient == acd_orient) return abc_orient; // now the fun begins ... // find shortest edge in each triangle double ba_length = ba.getMag(); double ca_length = ca.getMag(); double da_length = da.getMag(); VECTOR3 bc = b - c; VECTOR3 cd = c - d; double bc_length = bc.getMag(); double cd_length = cd.getMag(); double ea_length = ea.getMag(); double shortest_abc_edge_length = min(ba_length, min(ca_length, bc_length)); double shortest_acd_edge_length = min(ca_length, min(da_length, cd_length)); // // If point e is much further from a triangle than the shortest edge // of the triangle, assume we cannot compute a meaningful orientation // result in floating-point. // // Note that it is still possible that a triangle is not usable // for orientation even if the following tests conclude that it is // (the three vertices can be colinear yet not close together). // We ignore that case. // double relative_distance_threshold = 1e6; bool abc_usable_for_orientation = (shortest_abc_edge_length > 0.0) && (ea_length / shortest_abc_edge_length < relative_distance_threshold); bool acd_usable_for_orientation = (shortest_acd_edge_length > 0.0) && (ea_length / shortest_acd_edge_length < relative_distance_threshold); // if (!abc_usable_for_orientation && !acd_usable_for_orientation) { if (!abc_usable_for_orientation && !acd_usable_for_orientation) return 0; if (!abc_usable_for_orientation) return acd_orient; if (!acd_usable_for_orientation) return abc_orient; int res; // // determine whether edge ac of abcd is a ridge or a valley with // respect to viewer (who sees abcd counter-clockwise); ridge_valley is: // -1 if ridge, i.e. edge ac protrudes towards viewer // 1 if valley, i.e. edge ac protrudes away from viewer // 0 abcd is planar // int ridge_valley = sign(dot(da, cross(ba, ca))); // If ridge_valley == 0, abc and acd are coplanar, so // abc_orient and acd_orient should have agreed above. // In this case choose triangle with the normal with the biggest // magnitude as the triangle to use for orientation. if (ridge_valley == 0) { VECTOR3 abc = cross(ba, ca); VECTOR3 acd = cross(ca, da); double abc_normal_magnitude = abc.getMag(); double acd_normal_magnitude = acd.getMag(); if (abc_normal_magnitude > acd_normal_magnitude) res = abc_orient; else res = acd_orient; return res; } // both triangles assumed non-degenerate, quadrilateral is non-planar, // do the case analysis switch (((abc_orient + 1) << 4) + ((acd_orient + 1) << 2) + (ridge_valley + 1)) { // abc acd r_v case ((-1 + 1) << 4) + ((0 + 1) << 2) + (-1 + 1) : res = 0; break; case ((-1 + 1) << 4) + ((0 + 1) << 2) + (1 + 1) : res = -1; break; case ((-1 + 1) << 4) + ((1 + 1) << 2) + (-1 + 1) : res = 1; break; case ((-1 + 1) << 4) + ((1 + 1) << 2) + (1 + 1) : res = -1; break; case ((0 + 1) << 4) + ((-1 + 1) << 2) + (-1 + 1) : res = 0; break; case ((0 + 1) << 4) + ((-1 + 1) << 2) + (1 + 1) : res = -1; break; case ((0 + 1) << 4) + ((1 + 1) << 2) + (-1 + 1) : res = 1; break; case ((0 + 1) << 4) + ((1 + 1) << 2) + (1 + 1) : res = 0; break; case ((1 + 1) << 4) + ((-1 + 1) << 2) + (-1 + 1) : res = 1; break; case ((1 + 1) << 4) + ((-1 + 1) << 2) + (1 + 1) : res = -1; break; case ((1 + 1) << 4) + ((0 + 1) << 2) + (-1 + 1) : res = 1; break; case ((1 + 1) << 4) + ((0 + 1) << 2) + (1 + 1) : res = 0; break; default: res = 0; abort(); } return res; }
int vtCStreamLine::computeFieldLine(TIME_DIR time_dir, TIME_DEP time_dep, vtListSeedTrace& seedTrace, list<float>& stepList, PointInfo& seedInfo) { int istat; PointInfo thisParticle; double dt, cell_vol, mag; double curTime; VECTOR3 vel; float totalStepsize = 0.0; bool onAdaptive = true; int nSetAdaptiveCount = 0; // the first particle thisParticle = seedInfo; seedTrace.push_back(new VECTOR3(seedInfo.phyCoord)); curTime = (double)m_fCurrentTime; istat = m_pField->getFieldValue(seedInfo.phyCoord, m_fCurrentTime, vel); if(istat == OUT_OF_BOUND) return OUT_OF_BOUND; // the advection is out of boundary if(istat == MISSING_VALUE ||((abs(vel[0]) < m_fStationaryCutoff) && (abs(vel[1]) < m_fStationaryCutoff) && (abs(vel[2]) < m_fStationaryCutoff))) return CRITICAL_POINT; // this is critical point // get the initial step size cell_vol = m_pField->GetMinCellVolume(); mag = vel.GetDMag(); dt = m_fInitStepSize * cell_vol / mag; //Determine the value of mag*dt to project 10 times init size. double maxMagDt = 10.*dt*mag; int rollbackCount = 0; // start to advect while(totalStepsize < (float)((m_nMaxsize-1)*m_fSamplingRate)) { bool doingRetrace = false; int retrace = true; while(retrace) { retrace = false; for(int magTry = 0; magTry < 40; magTry++) { istat = runge_kutta4(time_dir, time_dep, thisParticle, &curTime, dt, maxMagDt); if (istat != FIELD_TOO_BIG) break; //Shrink dt by factor of 10. dt = 0.1*dt; } assert (istat != FIELD_TOO_BIG); seedTrace.push_back(new VECTOR3(thisParticle.phyCoord)); stepList.push_back(dt); if(istat == OUT_OF_BOUND) // out of boundary return OUT_OF_BOUND; m_pField->getFieldValue(thisParticle.phyCoord, m_fCurrentTime, vel); if((abs(vel[0]) < m_fStationaryCutoff) && (abs(vel[1]) < m_fStationaryCutoff) && (abs(vel[2]) < m_fStationaryCutoff)) return CRITICAL_POINT; totalStepsize += dt; // accumulation of step size nSetAdaptiveCount++; if((nSetAdaptiveCount == 2) && (onAdaptive == false)) onAdaptive = true; // just generate valid new point if(((int)seedTrace.size() > 2)&&(onAdaptive)) { double minStepsize, maxStepsize; VECTOR3 thisPhy, prevPhy, second_prevPhy; list<VECTOR3*>::iterator pIter = seedTrace.end(); pIter--; thisPhy = **pIter; pIter--; prevPhy = **pIter; pIter--; second_prevPhy = **pIter; mag = vel.GetDMag(); minStepsize = m_fInitStepSize * cell_vol / mag; maxStepsize = m_fMaxStepSize * cell_vol / mag; retrace = adapt_step(second_prevPhy, prevPhy, thisPhy, minStepsize, maxStepsize, &dt, onAdaptive); if(onAdaptive == false) nSetAdaptiveCount = 0; assert (rollbackCount < 10000);//If we got here, it's surely an infinite loop! // roll back and retrace //the doingRetrace flag is to stop double retracing (which results in infinite loop!) //Note a slightly different approach is in VTTimeVaryingFieldLine.cpp if(retrace && !doingRetrace) { seedTrace.pop_back(); seedTrace.pop_back(); thisParticle.Set(*(seedTrace.back())); totalStepsize -= stepList.back(); stepList.pop_back(); totalStepsize -= stepList.back(); stepList.pop_back(); rollbackCount++; doingRetrace = true; } else doingRetrace = false; } }// end of retrace //What was the distance advected? }// end of advection return (OKAY); }
// streamline advects as far as possible till the boundary or terminates at // critical points. only two cases will happen: OUT_OF_BOUND & CRITICAL_POINT int vtCStreamLine::executeInfiniteAdvection(TIME_DIR time_dir, TIME_DEP time_dep, vtListSeedTrace& seedTrace, float& totalStepsize, vector<float>* vStepsize) { int istat; vtParticleInfo* thisSeed; PointInfo thisParticle, prevParticle, second_prevParticle, seedInfo; vtListParticleIter sIter; float dt, dt_estimate, cell_volume, mag, curTime; VECTOR3 vel; INTEG_ORD integ_ord; // initialize integ_ord = m_integrationOrder; sIter = m_lSeeds.begin(); thisSeed = *sIter; seedInfo = thisSeed->m_pointInfo; seedTrace.clear(); totalStepsize = 0.0; // the first point seedTrace.push_back(new VECTOR3(seedInfo.phyCoord)); istat = m_pField->at_phys(seedInfo.fromCell, seedInfo.phyCoord, seedInfo, m_fCurrentTime, vel); if((fabs(vel[0]) < m_fStationaryCutoff) && (fabs(vel[1]) < m_fStationaryCutoff) && (fabs(vel[2]) < m_fStationaryCutoff)) return CRITICAL_POINT; thisParticle = seedInfo; curTime = m_fCurrentTime; // get the initial stepsize cell_volume = m_pField->volume_of_cell(seedInfo.inCell); mag = vel.GetMag(); if(fabs(mag) < 1.0e-6f) dt_estimate = 1.0e-5f; else dt_estimate = pow(cell_volume, (float)0.3333333f) / mag; dt = m_fInitialStepSize * dt_estimate; #ifdef DEBUG fprintf(fDebugOut, "****************new particle*****************\n"); fprintf(fDebugOut, "seed: %f, %f, %f with step size %f\n", seedInfo.phyCoord[0],seedInfo.phyCoord[1],seedInfo.phyCoord[2],dt); #endif // start to advect while(true) { second_prevParticle = prevParticle; prevParticle = thisParticle; // take a proper step, also calculates a new step size for the next step if(integ_ord == SECOND || integ_ord == FOURTH) istat = oneStepGeometric(integ_ord, time_dir, time_dep, thisParticle, prevParticle, second_prevParticle, &curTime, &dt, seedTrace.size()); else if(integ_ord == RK45) istat = oneStepEmbedded(integ_ord, time_dir, time_dep, thisParticle, &curTime, &dt); else return OUT_OF_BOUND; if(istat == OUT_OF_BOUND) // out of boundary { // find the boundary intersection point VECTOR3 intersectP, startP, endP; float oldStepsize, stepSize; oldStepsize = stepSize = dt; startP = prevParticle.phyCoord; endP = thisParticle.phyCoord; m_pField->BoundaryIntersection(intersectP, startP, endP, &stepSize, oldStepsize); totalStepsize += stepSize; seedTrace.push_back(new VECTOR3(intersectP)); if(vStepsize != NULL) vStepsize->push_back(stepSize); return OUT_OF_BOUND; } // find the loop list<VECTOR3*>::iterator searchIter; searchIter = seedTrace.end(); searchIter--; for(; searchIter != seedTrace.begin(); searchIter--) { if(thisParticle.phyCoord == **searchIter) // loop return CRITICAL_POINT; } m_pField->at_phys(thisParticle.fromCell, thisParticle.phyCoord, thisParticle, m_fCurrentTime, vel); seedTrace.push_back(new VECTOR3(thisParticle.phyCoord)); if(vStepsize != NULL) vStepsize->push_back(dt); totalStepsize += dt; #ifdef DEBUG fprintf(fDebugOut, "***************advected particle***************\n"); fprintf(fDebugOut, "pos = (%f, %f, %f), vel = (%f, %f, %f) with step size %f, total step size %f\n", thisParticle.phyCoord[0], thisParticle.phyCoord[1], thisParticle.phyCoord[2], vel[0], vel[1], vel[2], dt, totalStepsize); #endif if(totalStepsize > 4000.0) { printf("curl\n"); vel.Set(0.0, 0.0, 0.0); } if((fabs(vel[0]) < m_fStationaryCutoff) && (fabs(vel[1]) < m_fStationaryCutoff) && (fabs(vel[2]) < m_fStationaryCutoff)) return CRITICAL_POINT; if((int)seedTrace.size() > 2) adapt_step(second_prevParticle.phyCoord, prevParticle.phyCoord, thisParticle.phyCoord, &dt); } return OUT_OF_BOUND; }
int vtCStreamLine::computeFieldLine(TIME_DIR time_dir, INTEG_ORD integ_ord, TIME_DEP time_dep, vtListSeedTrace& seedTrace, PointInfo& seedInfo) { int count = 0, istat; PointInfo thisParticle, prevParticle, second_prevParticle; PointInfo third_prevParticle; float dt, dt_estimate, dt_attempt, mag, curTime, prevCurTime; VECTOR3 vel; float cell_volume; // the first point istat = m_pField->at_phys(seedInfo.fromCell, seedInfo.phyCoord, seedInfo, m_fCurrentTime, vel); if(istat == OUT_OF_BOUND) { return OUT_OF_BOUND; } if((fabs(vel[0]) < m_fStationaryCutoff) && (fabs(vel[1]) < m_fStationaryCutoff) && (fabs(vel[2]) < m_fStationaryCutoff)) { return CRITICAL_POINT; } thisParticle = seedInfo; seedTrace.push_back(new VECTOR3(seedInfo.phyCoord)); curTime = m_fCurrentTime; count++; // get the initial stepsize // this method was taken from the paper "Interactive Time-Dependent // Particle Tracing Using Tetrahedral Decomposition", by Kenwright and Lane dt = m_fInitialStepSize; if(m_adaptStepSize) { cell_volume = m_pField->volume_of_cell(seedInfo.inCell); mag = vel.GetMag(); if(fabs(mag) < 1.0e-6f) dt_estimate = 1.0e-5f; else dt_estimate = pow(cell_volume, (float)0.3333333f) / mag; dt = m_fInitialStepSize * dt_estimate; } #ifdef DEBUG fprintf(fDebugOut, "****************new particle*****************\n"); fprintf(fDebugOut, "seed: %f, %f, %f with step size %f\n", seedInfo.phyCoord[0],seedInfo.phyCoord[1],seedInfo.phyCoord[2],dt); #endif // start to advect while(count < m_nMaxsize) { third_prevParticle = second_prevParticle; second_prevParticle = prevParticle; prevParticle = thisParticle; prevCurTime = curTime; dt_attempt = dt; // take a proper step, also calculates a new step size for the next step if(integ_ord == SECOND || integ_ord == FOURTH) istat = oneStepGeometric(integ_ord, time_dir, time_dep, thisParticle, prevParticle, second_prevParticle, &curTime, &dt, count); else if(integ_ord == RK45) istat = oneStepEmbedded(integ_ord, time_dir, time_dep, thisParticle, &curTime, &dt); #ifdef DEBUG fprintf(fDebugOut, "point: %f, %f, %f with step size %f\n", thisParticle.phyCoord[0], thisParticle.phyCoord[1], thisParticle.phyCoord[2], dt); #endif // check if the step failed if(istat == FAIL) { if(!m_adaptStepSize) { // can't change the step size, so advection just ends return OKAY; } else if(dt_attempt == m_fMinStepSize) { // tried to take a step with the min step size, // can't go any further return OKAY; } else { // try to retake the step with a smaller step size dt = dt_attempt*0.1; if(dt < m_fMinStepSize) dt = m_fMinStepSize; thisParticle = prevParticle; prevParticle = second_prevParticle; second_prevParticle = third_prevParticle; curTime = prevCurTime; continue; } } seedTrace.push_back(new VECTOR3(thisParticle.phyCoord)); count++; if(!m_adaptStepSize) { // change step size to prevously used, since the oneStep methods // will change the value of dt dt = dt_attempt; } // check if point is outside real bounds // (bounds not counting ghost cells) if(!m_pField->IsInRealBoundaries(thisParticle)) { return OUT_OF_BOUND; } // check if point is at critical point m_pField->at_phys(thisParticle.fromCell, thisParticle.phyCoord, thisParticle, m_fCurrentTime, vel); if((fabs(vel[0]) < m_fStationaryCutoff) && (fabs(vel[1]) < m_fStationaryCutoff) && (fabs(vel[2]) < m_fStationaryCutoff)) { return CRITICAL_POINT; } } return OKAY; }
////////////////////////////////////////////////////////////////////////// // Compute streamlines. // output // listSeedTraces: For each seed, return a list keeping the trace it // advects ////////////////////////////////////////////////////////////////////////// //New version, uses FlowLineData instead of points array to write results of advection. void vtCStreamLine::computeStreamLine(float curTime, FlowLineData* container){ m_fCurrentTime = curTime; vtListParticleIter sIter; int istat; int seedNum = 0; for(sIter = m_lSeeds.begin(); sIter != m_lSeeds.end(); ++sIter) { vtParticleInfo* thisSeed = *sIter; if(thisSeed->itsValidFlag == 1) // valid seed { if(m_itsTraceDir & BACKWARD_DIR) { vtListSeedTrace* backTrace; list<float>* stepList; backTrace = new vtListSeedTrace; stepList = new list<float>; istat = computeFieldLine(BACKWARD, STEADY, *backTrace, *stepList, thisSeed->m_pointInfo); SampleFieldline(container, seedNum, BACKWARD, backTrace, stepList, true, istat ); delete backTrace; delete stepList; } else { //must be pure forward, set start point container->setFlowStart(seedNum, 0); } if(m_itsTraceDir & FORWARD_DIR) { vtListSeedTrace* forwardTrace; list<float>* stepList; forwardTrace = new vtListSeedTrace; stepList = new list<float>; istat = computeFieldLine(FORWARD,STEADY, *forwardTrace, *stepList, thisSeed->m_pointInfo); SampleFieldline(container, seedNum, FORWARD, forwardTrace, stepList, true, istat); delete forwardTrace; delete stepList; } else { //Must be pure backward, establish end of flowline: container->setFlowEnd(seedNum, 0); } } else // out of data region. Just mark seed as end, don't advect. { float x = thisSeed->m_pointInfo.phyCoord.x(); float y = thisSeed->m_pointInfo.phyCoord.y(); float z = thisSeed->m_pointInfo.phyCoord.z(); container->setFlowPoint(seedNum, 0, x,y,z); if(container->getMaxLength(BACKWARD) > 0) container->setFlowPoint(seedNum, -1, END_FLOW_FLAG,0.f,0.f); if(container->getMaxLength(FORWARD) > 0) container->setFlowPoint(seedNum, 1, END_FLOW_FLAG,0.f,0.f); if (container->doSpeeds()){ PointInfo pointInfo; VECTOR3 nodeData; float t = m_pField->GetStartTime(); pointInfo.phyCoord.Set(x,y,z); m_pField->getFieldValue(pointInfo.phyCoord, t, nodeData); container->setSpeed(seedNum, 0, nodeData.GetMag()/m_pField->getTimeScaleFactor()); } container->setFlowStart(seedNum, 0); container->setFlowEnd(seedNum, 0); } seedNum++; } }
VECTOR4 IRenderPipeline3D::mFunction_VertexLighting(const VECTOR3& vPosW, const VECTOR3& vNormalW) { //---------For Each Vertex, Perform Gouraud Shading------------ VECTOR4 outColor = { 0.0f,0.0f,0.0f,1.0f }; //traverse every lights for (UINT i = 0;i < c_maxLightCount;++i) { if (mDirLight[i].mIsEnabled == TRUE) { //normalized light vector VECTOR3 unitIncomingLightVec = mDirLight[i].mDirection; unitIncomingLightVec.Normalize(); //vector from current vertex to Camera(Eye),used when compute specular VECTOR3 toEye = mCameraPos - vPosW; toEye.Normalize(); //unit vertex normal VECTOR3 unitNormal = vNormalW; unitNormal.Normalize(); //Ambient Color VECTOR3 currentAmbient = mMaterial.ambient* mDirLight[i].mAmbientColor * mMaterial.diffuse; //diffuse Factor (first make sure that angle <normal,light> is less than PI/2 VECTOR3 currentDiffuse = { 0,0,0 }; VECTOR3 currentSpecular = { 0,0,0 }; float diffuseFactor = mDirLight[i].mDiffuseIntensity*Math::Vec3_Dot((-1)*unitIncomingLightVec, unitNormal); if (diffuseFactor > 0.0f) { //diffuse color (eye pos independent) currentDiffuse = diffuseFactor * mDirLight[i].mDiffuseColor; //if Texture Mapping is disabled, then use pure diffuse color of material if (m_pTexture == nullptr) { //component-wise currentDiffuse = currentDiffuse* mMaterial.diffuse; } //else the color will be passed down to pixel shader to multiply by //per-pixel sample diffuse color //Specular color - eye position dependent /*VECTOR3 unitOutgoingLightVec = Vec3_Reflect(unitIncomingLightVec, unitNormal); float specFactor = mDirLight[i].mSpecularIntensity * pow(max(Vec3_Dot(unitOutgoingLightVec, toEye), 0.0f), mMaterial.specularSmoothLevel); //Vector3 * vector3 means component-wise mult , return vec3(x1*x2,y1*y2,z1*z2) currentSpecular = specFactor* mMaterial.specular * mDirLight[i].mSpecularColor;*/ } VECTOR3 outColor3 = currentAmbient+currentDiffuse+currentSpecular; outColor += VECTOR4(outColor3.x, outColor3.y, outColor3.z, 0.0f); } } return outColor; }
/** * \note alpha and omega are acceleration and velocity vectors in the global * frame */ QUAT QUAT::dderiv(const QUAT& q, const VECTOR3& omega, const VECTOR3& alpha) { QUAT qdd = QUAT::deriv(q, alpha) - (REAL) 0.25 * omega.norm_sq() * q; return qdd; }
void ColliderSphereSphere::collide(std::vector<Contact> &vContacts) { const Real contactTolerance = 0.00005; VECTOR3 &vel1 = body0_->velocity_; VECTOR3 &pos1 = body0_->com_; Sphere<Real> *pSphere = dynamic_cast<Sphere<Real>* >(body0_->shape_); Real rad1 = pSphere->getRadius(); VECTOR3 &vel2 = body1_->velocity_; VECTOR3 &pos2 = body1_->com_; pSphere = dynamic_cast<Sphere<Real>* >(body1_->shape_); Real rad2 = pSphere->getRadius(); Real dist = std::numeric_limits<Real>::max(); //calc distance and relative orientation //we first need to calculate the relative velocity and //the velocity along the normal VECTOR3 vn = pos1 - pos2; vn.Normalize(); //calculate the relative velocity VECTOR3 v12 = vel1 - vel2; //calculate the velocity along the normal Real velalongnormal = vn * v12; //calculate the distance dist = (pos2-pos1).mag() - rad1 - rad2; Real dist1 = fabs(vn*vel1); Real dist2 = fabs(vn*vel2); Real distpertime = (dist1+dist2)*world_->timeControl_->GetDeltaT(); if(velalongnormal < -0.005 && distpertime >= dist) //if(relativeNormalVelocity < -0.005) { Contact contact; contact.m_dDistance = dist; contact.m_vNormal = vn; contact.m_vPosition0 = pos1; contact.m_vPosition1 = pos2; contact.m_pBody0 = body0_; contact.m_pBody1 = body1_; contact.id0 = contact.m_pBody0->iID_; contact.id1 = contact.m_pBody1->iID_; contact.vn = velalongnormal; contact.m_dPenetrationDepth = std::min(0.0,dist); contact.m_iState = CollisionInfo::TOUCHING; //std::cout<<"Pre-contact normal velocity: "<<velalongnormal<<" colliding contact"<<std::endl; //std::cout<<"Pre-contact angular velocity0: "<<contact.m_pBody0->GetAngVel(); //std::cout<<"Pre-contact angular velocity1: "<<contact.m_pBody1->GetAngVel(); //std::cout<<"Pre-contact velocity0: "<<contact.m_pBody0->m_vVelocity; //std::cout<<"Pre-contact velocity1: "<<contact.m_pBody1->m_vVelocity; vContacts.push_back(contact); } else if(velalongnormal < 0.00001 && dist < contactTolerance) { Contact contact; contact.m_dDistance = dist; contact.m_vNormal = vn; contact.m_vPosition0 = pos1; contact.m_vPosition1 = pos2; contact.m_pBody0 = body0_; contact.m_pBody1 = body1_; contact.id0 = contact.m_pBody0->iID_; contact.id1 = contact.m_pBody1->iID_; contact.vn = velalongnormal; contact.m_iState = CollisionInfo::TOUCHING; vContacts.push_back(contact); } else if(dist < 0.1*rad1) { Contact contact; contact.m_dDistance = dist; contact.m_vNormal = vn; contact.m_vPosition0 = pos1; contact.m_vPosition1 = pos2; contact.m_pBody0 = body0_; contact.m_pBody1 = body1_; contact.id0 = contact.m_pBody0->iID_; contact.id1 = contact.m_pBody1->iID_; contact.vn = velalongnormal; contact.m_iState = CollisionInfo::TOUCHING; vContacts.push_back(contact); } else { return; Contact contact; contact.m_dDistance = dist; contact.m_vNormal = vn; contact.m_vPosition0 = pos1; contact.m_vPosition1 = pos2; contact.m_pBody0 = body0_; contact.m_pBody1 = body1_; contact.id0 = contact.m_pBody0->iID_; contact.id1 = contact.m_pBody1->iID_; contact.vn = velalongnormal; contact.m_iState = CollisionInfo::VANISHING_CLOSEPROXIMITY; vContacts.push_back(contact); } }
void IPlayer::mFunction_UpdateMovement(float timeElapsed) { //--------------------------keyboard------------------------------ VECTOR3 moveVector = { 0,0,0 }; if (IS_KEY_DOWN('A')) { moveVector.x -= 1.0f; } if (IS_KEY_DOWN('D')) { moveVector.x += 1.0f; } if (IS_KEY_DOWN('W')) { moveVector.z += 1.0f; } if (IS_KEY_DOWN('S')) { moveVector.z -= 1.0f; } if (IS_KEY_DOWN(VK_LCONTROL)) { moveVector.y -= 1.0f; } if (IS_KEY_DOWN(VK_SPACE)) { moveVector.y += 1.0f; } //in case that camera moves faster if 3 directions has projection of speed moveVector.Normalize(); moveVector *= (0.2f*timeElapsed); gCamera.fps_MoveRight(moveVector.x); gCamera.fps_MoveForward(moveVector.z); gCamera.fps_MoveUp(moveVector.y); //restrict player movement to a Box VECTOR3 camPos = gCamera.GetPosition(); /*camPos = { Clamp(camPos.x,-c_halfMovementRestrictBoxWidth,c_halfMovementRestrictBoxWidth), Clamp(camPos.y,-c_halfMovementRestrictBoxWidth,c_halfMovementRestrictBoxWidth), Clamp(camPos.z,-c_halfMovementRestrictBoxWidth,c_halfMovementRestrictBoxWidth) }; gCamera.SetPosition(camPos);*/ //update Position mLastPos = mCurrentPos; mCurrentPos = camPos; //-------------------------------cursor movement---------------------------------- static POINT lastCursorPos = { 0,0 }; static POINT currentCursorPos = { 0,0 }; static const int scrWidth = ::GetSystemMetrics(SM_CXSCREEN); static const int scrHeight = ::GetSystemMetrics(SM_CYSCREEN); lastCursorPos = currentCursorPos; ::GetCursorPos(¤tCursorPos); //if cursor reach the boundary, go to another side if (currentCursorPos.x == scrWidth - 1) { ::SetCursorPos(0, currentCursorPos.y); lastCursorPos = { 0,currentCursorPos.y }; currentCursorPos = lastCursorPos; } else { if (currentCursorPos.x == 0) { ::SetCursorPos(scrWidth - 1, currentCursorPos.y); lastCursorPos = { scrWidth - 1,currentCursorPos.y }; currentCursorPos = lastCursorPos; } } if (currentCursorPos.y == scrHeight - 1) { ::SetCursorPos(currentCursorPos.x, 0); lastCursorPos = { currentCursorPos.x,0 }; currentCursorPos = lastCursorPos; } else { if (currentCursorPos.y == 0) { ::SetCursorPos(currentCursorPos.x, scrHeight - 1); lastCursorPos = { currentCursorPos.x,scrHeight - 1 }; currentCursorPos = lastCursorPos; } } //camera rotation int cursorDeltaX = currentCursorPos.x - lastCursorPos.x; int cursorDeltaY = (currentCursorPos.y - lastCursorPos.y); gCamera.RotateY_Yaw(0.0002f * cursorDeltaX*timeElapsed); gCamera.RotateX_Pitch(0.0002f* cursorDeltaY*timeElapsed); }
void CPointRendererSplat::_TraversePoints_Splat() { printf( "Rendering particles with splatting ... \n" ); // Initialize local variables const list<vtListSeedTrace*>* sl_list = (const list<vtListSeedTrace*>*)this->pDataSource; int iT=0; int bincount = 20; float *z = new float[2]; int *offsetToBins = new int[bincount]; int *pcountOfBins = new int[bincount]; for(int i=0; i<bincount; i++) { offsetToBins[i] = 0; pcountOfBins[i] = 0; } // Get total number of particles to begin maxT = 0; particlecount = _CountParticles( &maxT, &numT ); printf("Total number of particles: %d\n", particlecount); printf("Max Lifetime of a particle: %d\n", maxT ); // Allocate memory for rendering quads if( triangleArray != NULL ) delete [] triangleArray; if( colorArray != NULL ) delete [] colorArray; if( normalArray != NULL ) delete [] normalArray; triangleArray = new float[particlecount * 3 * 3]; colorArray = new float[particlecount * 3 * 3]; normalArray = new float[particlecount * 3 * 3]; int binid = -1; float binlength = 0; if( sortEnabled == 1 ) { // Get current modelview matrix _CurrentModelview(); // Compute min-max z values in world space _ZMinMaxEyeSpace( z ); printf("Z-range: [%f %f]\n", z[0], z[1]); // Compute width of each bin binlength = (z[1] - z[0]) / (float)bincount; } // Scan through all points and asssign bins to them iT = 0; int offset = 0; for(list<vtListSeedTrace*>::const_iterator pIter = sl_list->begin(); pIter!=sl_list->end(); pIter++, iT++) { // Get next trace const vtListSeedTrace *trace = *pIter; int l = trace->size(); int iP = 0; VECTOR3 p, nextp; for(list<VECTOR3*>::const_iterator pnIter = trace->begin(); pnIter!= trace->end(); pnIter++, iP++) { // Get next particle p = **pnIter; // If this is not the last point of the trace, // Get subsequent particle if(iP != (l-1)) { list<VECTOR3*>::const_iterator tmpIter = pnIter; tmpIter++; nextp = **tmpIter; } else { nextp.Set( p(0), p(1), p(2) ); } //printf( "P:%f, %f, %f\n", p(0), p(1), p(2) ); //printf( "nextP:%f, %f, %f\n", nextp(0), nextp(1), nextp(2) ); // Get World Space Coordinates of the particle VECTOR4 p4( p ); p4 = modelview * p4; if( sortEnabled == 1 ) { // Compute bin id binid = (int)floor( p4(2) - z[0]) / binlength; if( binid<0 ) binid = 0; if( binid>=bincount ) binid = bincount - 1; // Compute array offset for this particle offset = (offsetToBins[binid] + pcountOfBins[binid]); // Shift array int nParticlesToShift = 0; for(int i=binid+1; i<bincount; i++) nParticlesToShift += pcountOfBins[i]; memmove( (triangleArray+offset*9+9), (triangleArray+offset*9), nParticlesToShift * 9 * sizeof(float) ); memmove( (colorArray+offset*9+9), (colorArray+offset*9), nParticlesToShift * 9 * sizeof(float) ); } VECTOR3 dir = nextp - p; //dir.Normalize(); float frac = 0.5f; float highx = p(0) + dir(0)*frac;//*g; float highy = p(1) + dir(1)*frac;//*g; float highz = p(2) + dir(2)*frac;//*g; //printf( "P:%f, %f, %f\n", p(0), p(1), p(2) ); //printf( "nextP:%f, %f, %f\n", nextp(0), nextp(1), nextp(2) ); //printf( "high:%f, %f, %f\n", highx, highy, highz ); triangleArray[offset*9] = p(0); triangleArray[offset*9+1] = p(1)+0.1f; triangleArray[offset*9+2] = p(2); triangleArray[offset*9+3] = p(0); triangleArray[offset*9+4] = p(1)-0.1f; triangleArray[offset*9+5] = p(2); triangleArray[offset*9+6] = highx; triangleArray[offset*9+7] = highy; triangleArray[offset*9+8] = highz; // Calculate Normals if( lightEnabled == 1 ) { VECTOR3 e1( triangleArray[offset*9+3]-triangleArray[offset*9], triangleArray[offset*9+4]-triangleArray[offset*9+1], triangleArray[offset*9+5]-triangleArray[offset*9+2] ); VECTOR3 e2( triangleArray[offset*9+6]-triangleArray[offset*9+3], triangleArray[offset*9+7]-triangleArray[offset*9+4], triangleArray[offset*9+8]-triangleArray[offset*9+5] ); VECTOR3 e3( triangleArray[offset*9]-triangleArray[offset*9+6], triangleArray[offset*9+1]-triangleArray[offset*9+7], triangleArray[offset*9+2]-triangleArray[offset*9+8] ); e1.Normalize(); e2.Normalize(); e3.Normalize(); VECTOR3 norm( e3(1)*e1(2) - e3(2)*e1(1), e3(2)*e1(0) - e3(0)*e1(2), e3(0)*e1(1) - e3(1)*e1(0) ); norm.Normalize(); normalArray[offset*9] = norm(0); normalArray[offset*9+1] = norm(1); normalArray[offset*9+2] = norm(2); norm.Set( e1(1)*e2(2) - e1(2)*e2(1), e1(2)*e2(0) - e1(0)*e2(2), e1(0)*e2(1) - e1(1)*e2(0) ); norm.Normalize(); normalArray[offset*9+3] = norm(0); normalArray[offset*9+4] = norm(1); normalArray[offset*9+5] = norm(2); norm.Set( e2(1)*e2(2) - e3(2)*e2(1), e2(2)*e2(0) - e3(0)*e2(2), e2(0)*e2(1) - e3(1)*e2(0) ); norm.Normalize(); normalArray[offset*9+6] = norm(0); normalArray[offset*9+7] = norm(1); normalArray[offset*9+8] = norm(2); //VECTOR3 norm( (e1(0) + e2(0)) / 2.0f, (e1(1) + e2(1)) / 2.0f, (e1(2) + e2(2)) / 2.0f ); //norm.Normalize(); } if( sortEnabled == 1 ) { // Update bin frequency pcountOfBins[binid] += 1; // Update bin offsets for(int i=binid+1; i<bincount; i++) offsetToBins[i] += 1; } if( currentColorScheme == 0 ) { // Assign color based on time float f = (float)iP / (float)maxT; float f1 = (float)(iP+1) / (float)maxT; f = 0.2f + 0.8f * f; f1 = 0.2f + 0.8f * f1; colorArray[offset*9] = f; colorArray[offset*9+1] = 0.4f; colorArray[offset*9+2] = 1-f; colorArray[offset*9+3] = f; colorArray[offset*9+4] = 0.4f; colorArray[offset*9+5] = 1-f; colorArray[offset*9+6] = f1; colorArray[offset*9+7] = 0.4f; colorArray[offset*9+8] = 1-f1; } else if( currentColorScheme == 1 ) { // Assign color based on Glyph direction dir.Normalize(); dir[0] = 0.2f + 0.8f * dir(0); dir[1] = 0.2f + 0.8f * dir(1); dir[2] = 0.2f + 0.8f * dir(2); colorArray[offset*9] = dir(0); colorArray[offset*9+1] = dir(1); colorArray[offset*9+2] = dir(2); colorArray[offset*9+3] = dir(0); colorArray[offset*9+4] = dir(1); colorArray[offset*9+5] = dir(2); colorArray[offset*9+6] = dir(0); colorArray[offset*9+7] = dir(1); colorArray[offset*9+8] = dir(2); } // Increment offset, if no sorting if( sortEnabled == 0 ) offset ++; }// end inner for: for each trace }// end outer for delete [] z; delete [] offsetToBins; delete [] pcountOfBins; }