bool ZCharacterObject::GetHistory(rvector *pos, rvector *direction, float fTime) { if(GetVisualMesh() == NULL) return false; if(m_BasicHistory.size()>1) { ZBasicInfoHistory::iterator hi; hi=m_BasicHistory.end(); // ½Ã°£¼øÀ¸·Î bi < fTime < binext µÇµµ·Ï µÎ°³ÀÇ µÎ ¾ÆÀÌÅÛÀ» ¼±Åà ZBasicInfoItem *bi=NULL,*binext=NULL; do { hi--; binext=bi; bi=*hi; } while(hi!=m_BasicHistory.begin() && bi->fSendTime>fTime); if(fTime<bi->fSendTime) // ¿ª»ç°¡ ±â·ÏµÈ ÀÌÀüÀÇ µ¥ÀÌÅ͸¦ ¿ä±¸Çϸé Á¿Ä¡¾Ê´Ù return false; ZBasicInfoItem *pnext,next; if(!binext) { if(fTime>=ZGetGame()->GetTime()) // ¹Ì·¡ÀÇ À§Ä¡´Â ¾Ë¼ö¾ø´Ù. ÇöÀçÀÇ À§Ä¡¸¦ ¸®ÅÏÇÑ´Ù { *pos=GetPosition(); *direction = m_Direction; // *headpos=GetVisualMesh()->GetHeadPosition(); // if(direction_low) *direction_low = m_DirectionLower; return true; } next.fSendTime=ZGetGame()->GetTime(); next.info.position=GetPosition(); next.info.direction=m_Direction; // next.info.lowerstate=m_AniState_Lower; pnext=&next; } else pnext=binext; float t=(fTime-bi->fSendTime)/(pnext->fSendTime-bi->fSendTime); *pos = bi->info.position *(1-t) + pnext->info.position*t; // *headpos = bi->info.headpos*(1-t) + pnext->headpos*t; // *headpos=GetVisualMesh()->GetHeadPosition(); *direction = InterpolatedVector(bi->info.direction,pnext->info.direction,t); // if(direction_low) *direction_low = InterpolatedVector(bi->info.direction_low,pnext->direction_low,t); return true; } else { // ¾Æ¸¶µµ ÀÎÇü ? *pos=GetPosition(); *direction=m_Direction; // if(direction_low) *direction_low=m_DirectionLower; // *headpos=GetVisualMesh()->GetHeadPosition(); return true; } return false; }
v3 GetNormal(const RCONVEXPOLYGONINFO *poly, const rvector &position, int au, int av) { int nSelPolygon = -1, nSelEdge = -1; float fMinDist = FLT_MAX; if (poly->nVertices == 3) nSelPolygon = 0; else { rvector pnormal(poly->plane.a, poly->plane.b, poly->plane.c); for (int i = 0; i < poly->nVertices - 2; i++) { const auto& a = poly->pVertices[0]; const auto& b = poly->pVertices[i + 1]; const auto& c = poly->pVertices[i + 2]; if (IntersectTriangle(a, b, c, position + pnormal, -pnormal, nullptr)) { nSelPolygon = i; nSelEdge = -1; break; } else { float dist = GetDistance(position, a, b); if (dist < fMinDist) { fMinDist = dist; nSelPolygon = i; nSelEdge = 0; } dist = GetDistance(position, b, c); if (dist < fMinDist) { fMinDist = dist; nSelPolygon = i; nSelEdge = 1; } dist = GetDistance(position, c, a); if (dist < fMinDist) { fMinDist = dist; nSelPolygon = i; nSelEdge = 2; } } } } auto& v0 = poly->pVertices[0]; auto& v1 = poly->pVertices[nSelPolygon + 1]; auto& v2 = poly->pVertices[nSelPolygon + 2]; auto& n0 = poly->pNormals[0]; auto& n1 = poly->pNormals[nSelPolygon + 1]; auto& n2 = poly->pNormals[nSelPolygon + 2]; v3 pos; if (nSelEdge != -1) { auto& e0 = nSelEdge == 0 ? v0 : nSelEdge == 1 ? v1 : v2; auto& e1 = nSelEdge == 0 ? v1 : nSelEdge == 1 ? v2 : v0; auto dir = Normalized(e1 - e0); pos = e0 + DotProduct(dir, position - e0) * dir; } else pos = position; auto a = v1 - v0; auto b = v2 - v1; auto x = pos - v0; float f = b[au] * x[av] - b[av] * x[au]; if (IS_ZERO(f)) return n0; float t = (a[av] * x[au] - a[au] * x[av]) / f; auto tem = InterpolatedVector(n1, n2, t); auto inter = a + t*b; int axisfors; if (fabs(inter.x) > fabs(inter.y) && fabs(inter.x) > fabs(inter.z)) axisfors = 0; else if (fabs(inter.y) > fabs(inter.z)) axisfors = 1; else axisfors = 2; float s = x[axisfors] / inter[axisfors]; return InterpolatedVector(n0, tem, s); }
bool MPathTracer::ProcMove(rvector* pNewPos, rvector* pNewDir, rvector* pNewVelocity, rvector* pDir, rvector& Distance, rvector& RealDistance, bool bSmoothArrival) { //if(Velocity.x==0.0f && Velocity.y==0.0f && Velocity.z==0.0f) return true; // 같은 위치면 도착 float fDistance = Distance.GetMagnitude(); rvector TargetDir2D(m_Dir); if(Distance.x!=0.0f || Distance.y!=0.0f || Distance.z!=0.0f) { TargetDir2D = Distance; TargetDir2D.z = 0; TargetDir2D.Normalize(); } if(pDir!=NULL) { _ASSERT(pDir->z==0.0f); // 방향 설정은 보정된 Distance가 아닌 RealDistance에 의존한다. float fRealDistance = RealDistance.GetMagnitude(); if(fRealDistance<=m_Property.fMaxVelocity*m_fDirectionSettingConstant) { float fDirectionWeightConstant = max(min((1-fRealDistance/(m_Property.fMaxVelocity*m_fDirectionSettingConstant)), 1), 0); TargetDir2D = Normalize(InterpolatedVector(TargetDir2D, Normalize(*pDir), fDirectionWeightConstant)); } } // 회전 //////////////////////////////////////////////////////////// float fDiffAngle = GetAngleOfVectors(TargetDir2D, m_Dir); float fRotateAngle = fDiffAngle; float fRotatePercent = 1.0f; // 회전 가/감속 if(fDiffAngle>0) { m_fAngularVelocity = min(m_Property.fMaxRotationVelocity, m_fAngularVelocity + m_Property.fRotationAcceleration); if(fabs(fDiffAngle)<m_Property.fMaxRotationVelocity*m_nAgularDecelerationConstant) { m_fAngularVelocity = min(m_fAngularVelocity, fDiffAngle/m_nAgularDecelerationConstant); } } else if(fDiffAngle<0) { m_fAngularVelocity = max(-m_Property.fMaxRotationVelocity, m_fAngularVelocity - m_Property.fRotationAcceleration); if(fabs(fDiffAngle)<m_Property.fMaxRotationVelocity*m_nAgularDecelerationConstant) { m_fAngularVelocity = max(m_fAngularVelocity, fDiffAngle/m_nAgularDecelerationConstant); } } if(fDiffAngle!=0.0f) fRotatePercent = m_fAngularVelocity/fDiffAngle; rvector NewDir = Normalize(InterpolatedVector(m_Dir, Normalize(TargetDir2D), fRotatePercent)); // 결과 값 //m_fResultRotatePercent = fRotateAngle / m_Property.fMaxRotationVelocity; m_fResultRotatePercent = GetAngleOfVectors(NewDir, m_Dir) / m_Property.fMaxRotationVelocity; // 버그로 인해 실제 계산값을 입력 bool bArriveAngle = false; if(fRotatePercent==1.0f) bArriveAngle = true; // 가속 & 이동 //////////////////////////////////////////////////////////// // 현재 가능 가속도 계산 rvector Acceleration = Clip(Distance-m_Velocity, m_Property.fAcceleration); //rvector Acceleration = NewDir*m_Property.fAcceleration; float fAcceleration = Acceleration.GetMagnitude(); if(fAcceleration>=0.0f) { if(m_bDirectionSpeed==true) { // 방향에 따른 가감속 fAcceleration -= (fAcceleration*max(min((float)fabs(fDiffAngle)/pi, 1), 0)*m_nDirectionalSpeedContant); Acceleration = Normalize(Acceleration)*fAcceleration; } } // 현재 가능 속도 계산 rvector NewVelocity = m_Velocity + Acceleration; //float fNewVelocity = NewVelocity.GetMagnitude(); Clip(&NewVelocity, m_Property.fMaxVelocity); // Clip bool bArrive = false; // 거리에 따른 속도 조절 float fNewVelocity = NewVelocity.GetMagnitude(); if(bSmoothArrival==true && fDistance<=m_Property.fMaxVelocity*m_nDecelerationConstant) { float t = fDistance/(m_Property.fMaxVelocity*m_nDecelerationConstant); //_ASSERT(m_nDecelerationCurveConstant>=1.0f); fNewVelocity = min(fNewVelocity, m_Property.fMaxVelocity*(float)pow((t), m_nDecelerationCurveConstant)); NewVelocity = Normalize(NewVelocity)*fNewVelocity; if(fNewVelocity<=m_Property.fMaxVelocity*m_fArrivalConstant) bArrive = true; } else if(fNewVelocity>=fDistance) bArrive = true; // New Values *pNewVelocity = NewVelocity; *pNewDir = NewDir; *pNewPos = m_Pos+NewVelocity; return bArrive; }