int MoveBlock(int Direction) { switch(Direction) { case LEFT: if(DetectCollision(LEFT)) return 1; DisplayBlock(--BlockX, BlockY); break; case RIGHT: if(DetectCollision(RIGHT)) return 1; DisplayBlock(++BlockX, BlockY); break; case DOWN: if(DetectCollision(DOWN)) { GetNextBlock(); //Generate new block on screen return 1; } DisplayBlock(BlockX, ++BlockY); break; case REFRESH: DisplayBlock(BlockX, BlockY); break; } return 0; }
void Physics::IterateCollisions() { for( int I = 0; I < Iterations; I++ ) { //Repeat this a few times to give more exact results //A small 'hack' that keeps the vertices inside the screen. You could of course implement static objects and create //four to serve as screen boundaries, but the max/min method is faster for( int T = 0; T < VertexCount; T++ ) { Vec2& Pos = Vertices[ T ]->Position; Pos.X = MAX( MIN( Pos.X, (float)GWidth ), 0.0f ); Pos.Y = MAX( MIN( Pos.Y, (float)GHeight ), 0.0f ); } UpdateEdges(); //Edge correction step for( int I = 0; I < BodyCount; I++ ) { Bodies[ I ]->CalculateCenter(); //Recalculate the center } for( int B1 = 0; B1 < BodyCount; B1++ ) { //Iterate trough all bodies for( int B2 = 0; B2 < BodyCount; B2++ ) { if( B1 != B2 ) if( BodiesOverlap( Bodies[ B1 ], Bodies[ B2 ] ) ) //Test the bounding boxes if( DetectCollision( Bodies[ B1 ], Bodies[ B2 ] ) ) //If there is a collision, respond to it ProcessCollision(); } } } }
/* * Animate() handles the animation and the redrawing of the * graphics window contents. */ static void Animate(void) { // Clear the redering window glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear the current matrix (Modelview) glLoadIdentity(); // Back off eight units to be able to view from the origin. glTranslatef ( 0.0, 0.0, 0.0); // Rotate the plane of the elliptic // (rotate the model's plane about the x axis by fifteen degrees) glRotatef( 0.0, 0.0, 0.0, 0.0 ); DrawBox(); DetectCollision(); DrawParticles(); // Flush the pipeline, and swap the buffers glFlush(); glutSwapBuffers(); if ( singleStep ) { spinMode = GL_FALSE; } glutPostRedisplay(); // Request a re-draw for animation purposes }
bool Ball::HandleFakeCollision(float & t, glm::vec3 & pos, glm::vec3 & endpos, glm::vec3 & d, float dist) { std::vector<Mesh*> *fakeWalls = _tile->FakeWalls(); unsigned int numNeighbors = fakeWalls->size(); for (unsigned int n = 0; n < numNeighbors; ++n) { Mesh *m = fakeWalls->at(n); if (m) { float timeElapsed = DetectCollision(pos, endpos, m, dist); if (timeElapsed > 0.f) { // we collided, find the new tile to move to, and update the position, and velocity _tile = _tile->Neighbor(n); endpos = *_transform->Position() + (((timeElapsed + 0.005f) * _speed) * d); t -= (timeElapsed + 0.005f); //endpos = *_transform->Position() + (((t - 0.01f) * _speed) * _tile->Normal()); return true; } } } // no collision was found return false; }
bool Ball::HandleCollision(float & t, glm::vec3 & pos, glm::vec3 & endpos, glm::vec3 & d, float dist) { std::vector<Renderable*> *walls = _tile->RealWalls(); unsigned int numNeighbors = walls->size(); for (unsigned int n = 0; n < numNeighbors; ++n) { if (walls->at(n)) { Mesh *m = walls->at(n)->GetMesh(); float timeElapsed = DetectCollision(pos, endpos, m, dist); if (timeElapsed > 0.f) { glm::vec3 w = glm::proj(-d, m->NormalData().at(0)); d = (2.f * w) + d; d = ComputeSurfaceDirection(*_velocity, glm::vec3(0.f, 1.f, 0.f), _tile->Normal()); t -= (timeElapsed + 0.005f); if (t < 0.f) t = 0.01f; endpos = *_transform->Position() + (((t - 0.01f) * _speed) * d); return true; } } } // no collision was found return false; }
/* Right click - get info about the object. */ HRESULT INTERACTIVE::RightClick(const int x, const int y) { Gdiplus::PointF hit_position(x - static_cast<Gdiplus::REAL>(video_position.left), y - static_cast<Gdiplus::REAL>(video_position.top)); int i = DetectCollision(hit_position); if(i){ // Play audio hr = audio_media_control->Stop(); std::string source = objects[i-1].caption_sound_path; hr = audio_graph->RenderFile(string2wstring(source).c_str(), NULL); HRLog("IGraphBuilder.RenderFile() - additional audio", hr, false); hr = audio_media_control->Run(); if(hr){ OAFilterState filter_state; hr = video_media_control->GetState(INFINITE, &filter_state); HRLog("IMediaControl.GetState - additional audio play", hr, false); } // Display the caption caption_displayed = true; BMP_mix->Clear(key_color); // Bitmap for video mixing DrawString(hit_position, objects[i-1].caption.c_str()); } DrawOutlines(); BlendText(); return hr; }
void CW::PhysicsEngine::Iterate(void) { for(int i = 0; i < m_Iterations; ++i) { // Apply edge constraints UpdateEdges(); for (PhysicsBody* b : m_Bodies) { b->CalculateCenter(); } for (PhysicsBody* b1 : m_Bodies) { for(PhysicsBody* b2 : m_Bodies) { if(b1 != b2) { if (BoundingBox::CheckIntersection(&(b1->BoundingBox), &(b2->BoundingBox))) { if (DetectCollision(b1, b2)) { // Process collision info with CollisionInfo data ProcessCollision(); } } } } } } }
//Moves any other square one position down //Called by the squares in the vector void Game::FallSquare(Square *square, GameBoard *board) { CollisionPosition cpS = DetectCollision(square, board); if (cpS.Down) square->state = SquareState::fixed; else square->SetY(square->GetY() + this->SquareSize); }
void CLine::Tick(DWORD fElapsedTime) { if (IsGone()) return; if (m_nLastTime) m_fIntensity += fElapsedTime/m_nLastTime*(m_bFadeIn?1.f:-1.f); if (m_bFaded) return; m_vPos += m_vDir*(fElapsedTime*m_fSpeed); DetectCollision(); Update(); }
/* Mouse move - detection of the collision with the option. */ HRESULT DIALOGUE::MouseMove(const int x, const int y){ Gdiplus::PointF hit_position(x - static_cast<Gdiplus::REAL>(video_position.left), y - static_cast<Gdiplus::REAL>(video_position.top)); int i = DetectCollision(hit_position); if(i != highlited_option){ // Mouse moved to the new option or out highlited_option = i; DrawOptions(); } return S_OK; }
void WSL::Singleton::Cycle() { engine->renders.clear(); engine->scanAreas.Array.clear(); input->refrence = engine; input->Update( camera ); input->Frame(); LevelCycle(); soundManager->Update(); DetectCollision(); Draw(); }
/* Left click - acivates the object clicked on. */ HRESULT INTERACTIVE::LeftClick(const int x, const int y) { Gdiplus::PointF hit_position(x - static_cast<Gdiplus::REAL>(video_position.left), y - static_cast<Gdiplus::REAL>(video_position.top)); int i = DetectCollision(hit_position); if(i){ // Play audio hr = audio_media_control->Stop(); std::string source = objects[i-1].sound_path; hr = audio_graph->RenderFile(string2wstring(source).c_str(), NULL); HRLog("IGraphBuilder.RenderFile() - additional audio", hr, false); hr = audio_media_control->Run(); if(hr){ OAFilterState filter_state; hr = video_media_control->GetState(INFINITE, &filter_state); HRLog("IMediaControl.GetState - additional audio play", hr, false); } } return hr; }
void RotateBlock() { int TempBlockMatrix[4][4]; for(int i=0; i<4; i++) for(int j=0; j<4; j++) TempBlockMatrix[i][j] = BlockMatrix[i][j]; switch(CurrentShape) { case SHAPE_O: //in case O no change return; case SHAPE_L: //Changes 8 pos around (1,1) point case SHAPE_L2: case SHAPE_S: case SHAPE_S2: case SHAPE_T: BlockMatrix[0][0] = TempBlockMatrix[2][0]; BlockMatrix[0][2] = TempBlockMatrix[0][0]; BlockMatrix[2][2] = TempBlockMatrix[0][2]; BlockMatrix[2][0] = TempBlockMatrix[2][2]; BlockMatrix[0][1] = TempBlockMatrix[1][0]; BlockMatrix[1][2] = TempBlockMatrix[0][1]; BlockMatrix[2][1] = TempBlockMatrix[1][2]; BlockMatrix[1][0] = TempBlockMatrix[2][1]; break; case SHAPE_I: BlockMatrix[0][1] = TempBlockMatrix[1][0]; //Changes only 3 position BlockMatrix[1][0] = TempBlockMatrix[0][1]; BlockMatrix[1][2] = TempBlockMatrix[2][1]; BlockMatrix[2][1] = TempBlockMatrix[1][2]; BlockMatrix[1][3] = TempBlockMatrix[3][1]; BlockMatrix[3][1] = TempBlockMatrix[1][3]; break; } if(DetectCollision(REFRESH)) { for(int i=0; i<4; i++) for(int j=0; j<4; j++) BlockMatrix[i][j] = TempBlockMatrix[i][j]; return; } MoveBlock(REFRESH); }
// Iterative collision detection void CIterativeSheetSimulator::DetectCollisions( void ) { for ( int i = 0; i < m_CollisionCount; ++i ) { if (m_InitialPass) { InitPosition( m_CurrentCollisionPt ); } else { float flOffset = COLLISION_PLANE_OFFSET * ( (float)(m_SimulationSteps - 1) / (float)(m_TotalSteps - 1) ); DetectCollision( m_CurrentCollisionPt, flOffset ); } if (++m_CurrentCollisionPt >= NumParticles()) { m_CurrentCollisionPt = -1; m_InitialPass = false; break; } } }
/* Response to the move of the cursor - if there is a object hit, object is captioned. */ HRESULT INTERACTIVE::MouseMove(const int x,const int y) { Gdiplus::PointF hit_position(x - static_cast<Gdiplus::REAL>(video_position.left), y - static_cast<Gdiplus::REAL>(video_position.top)); last_point.X = hit_position.X; last_point.Y = hit_position.Y; int i = DetectCollision(hit_position); if(i != 0 && i != last_active_object){ last_active_object = i; caption_displayed = false; BMP_mix->Clear(key_color); DrawString(hit_position, objects[i-1].name.c_str()); DrawOutlines(); BlendText(); } else if (last_active_object != 0 && i == 0 && caption_displayed != true){ BMP_mix->Clear(key_color); last_active_object = 0; DrawOutlines(); BlendText(); } return S_OK; }
//Move squares that falls after deletion of an other squares. //These squares are added into a list of lists (squares) by a GameBoard object after deleting a square. //If the first square of each list hits something, the complete list is added to the gameboard and deleted from squares void Game::moveOtherSquares(GameBoard *board) { int pos = 0; std::vector<int> delvec; if (!this->squares->empty()) { //Move the square one position down for (auto list = this->squares->begin(); list != this->squares->end(); list++) { Square *fall = (*list)->at(0); //If collision then add to the gameboard and delete it from the vector if (DetectCollision(fall, board).Down) { delvec.push_back(pos); for (auto i = (*list)->begin(); i != (*list)->end(); i++) { board->addToBoard(*i); } } else { for (auto i = (*list)->begin(); i != (*list)->end(); i++) { Square *s = *i; s->SetY(s->GetY() + s->GetSize()); } } pos++; } //Delete the once added to the board for (auto i = delvec.rbegin(); i != delvec.rend(); i++) { this->squares->erase(this->squares->begin() + *i); } } }
void SgObjectManager::DetectCollisions() { for(int i=0; i<m_dwMaxObjects; i++) { if(m_ppObject[i]!=NULL) { for(int j=i+1; j<m_dwMaxObjects; j++) { if( NULL == m_ppObject[j] )continue; //here overloaded function should do //appropriate action depending on type //of collision. switch(DetectCollision(m_ppObject[i], m_ppObject[j])) { case CT_STDCLSN: OnCollision( m_ppObject[i] , m_ppObject[j] ); break; default: break; } } } } }
bool CPlayer::TickFSM(float fElapsedTime) { // Gravity if (m_tiles[m_iRowFoot][m_iCol] > EBT_BlockMin || m_tiles[m_iRowFoot][m_iCol+1] > EBT_BlockMin) SubtractActorState(EAS_Fall); else AddActorState(EAS_Fall); if (m_bUp) { if (m_tiles[m_iRow][m_iCol] & EBT_Door || m_tiles[m_iRow+1][m_iCol] & EBT_Door) { return true; } else if (m_tiles[m_iRow][m_iCol] & EBT_Ladder || m_tiles[m_iRow+1][m_iCol] & EBT_Ladder) { AddActorState(EAS_Climb); } } bool bIgnore(false); while (true) { if (m_eCurState & EAS_Death) { bIgnore = true; break; } if (m_eCurState & EAS_Hurt) { m_vecVel.y -= m_fDefSpe; SubtractActorState(EAS_Hurt); AddActorState(EAS_Fall); } if (m_eCurState & EAS_Climb) { if (m_tiles[m_iRowFoot][m_iColMid] & EBT_Ladder) { m_vecAcc.y = 0.f; } else { SubtractActorState(EAS_Climb); AddActorState(EAS_Fall); } if (m_eCurState & EAS_Walk) m_vecVel.x = m_fDefSpe * (m_bMirror?-1:1); else m_vecVel.x = 0.f; if (m_bUp) m_vecVel.y = -m_fDefSpe; else if (m_eCurState & EAS_Duck) m_vecVel.y = m_fDefSpe; else m_vecVel.y = 0.f; break; } if (m_eCurState & EAS_Swim) { } if (m_eCurState & EAS_Jump) { if (m_vecVel.y == 0.f) { m_vecVel.y = -m_fJumpHeight; } else { if (m_vecVel.y > 0.f) { SubtractActorState(EAS_Jump); /* Toggle flappy bird mode XD -->* m_bJump = true; /**/ AddActorState(EAS_Fall); } } } if (m_eCurState & EAS_Fall) { if (m_tiles[m_iRow+1][m_iCol] & EBT_Water || m_tiles[m_iRow+1][m_iCol+1] & EBT_Water) m_vecAcc.y = m_fGravityWater; else m_vecAcc.y = m_fGravity; } if (m_eCurState & EAS_Walk) { if (abs(m_vecVel.x) < m_fDefSpe) m_vecAcc.x = m_fDefAcc * (m_bMirror?-1:1); else m_vecAcc.x = 0.f; } if (m_eCurState & EAS_Stand) { if (abs(m_vecVel.x) > 1.f) m_vecAcc.x = m_fDefAcc * (m_vecVel.x>0.f?-1:1); else { m_vecAcc.x = 0.f; m_vecVel.x = 0.f; } } break; } m_vecVel += m_vecAcc * fElapsedTime; m_vecPos += m_vecVel * fElapsedTime; if (m_vecPos.x < 0.f) m_vecPos.x = 0.f; else if (m_vecPos.x > m_fMaxCol) m_vecPos.x = m_fMaxCol; if (m_vecPos.y < 0.f) m_vecPos.y = 0.f; if (!bIgnore) DetectCollision(fElapsedTime); return m_vecPos.y > BG_HEIGHT; }
void Update(float lastFrameTicks, Matrix &modelMatrix, ShaderProgram program) { int collisionTest = 0; if(keys[SDL_SCANCODE_W]) { p1Paddle.yVelocity = 1.0f; p1Paddle.yPosition += elapsed * (p1Paddle.speed * p1Paddle.yVelocity); if(p1Paddle.yPosition > (MaxYPos-(p1Paddle.height))) { p1Paddle.speed = 0.0f; } else { p1Paddle.speed = 2.4f; } } else if(keys[SDL_SCANCODE_S]) { p1Paddle.yVelocity = -1.0f; p1Paddle.yPosition += elapsed * (p1Paddle.speed * p1Paddle.yVelocity); if(p1Paddle.yPosition < ((-MaxYPos)+(p1Paddle.height))) { p1Paddle.speed = 0.0f; } else { p1Paddle.speed = 2.4f; } } pongBall.xPosition += elapsed * (pongBall.speed * pongBall.xVelocity); pongBall.yPosition += elapsed * (pongBall.speed * pongBall.yVelocity); if(pongBall.xPosition > MaxXPos-pongBall.width) { p1ScoreCount++; glClearColor(0.0f, 255.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT); pongBall.xVelocity = 0.0f; pongBall.xPosition = 0.0f; pongBall.yPosition = 0.0f; pongBall.yVelocity = 0.0f; } if(pongBall.xPosition < (-MaxXPos)+pongBall.width) { p2ScoreCount++; glClearColor(255.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT); pongBall.xVelocity = 0.0f; pongBall.xPosition = 0.0f; pongBall.yPosition = 0.0f; pongBall.yVelocity = 0.0f; } if(pongBall.yPosition > MaxYPos-pongBall.height || pongBall.yPosition < (-MaxYPos)+pongBall.height) { pongBall.yVelocity = -pongBall.yVelocity; if(pongBall.yPosition > 0) { pongBall.yPosition -= 0.1f; } else { pongBall.yPosition += 0.1f; } } //collisionTest = DetectCollision(p1Paddle, pongBall); //if collision tests positive, OR pongBall hits the right wall: // || pongBall.xPosition > MaxXPos-pongBall.width) if((collisionTest = DetectCollision(p1Paddle, pongBall))) { pongBall.speed += 0.35; std::cout << collisionTest << std::endl; //switch xVelocity of ball (happens no matter what) pongBall.xVelocity = -pongBall.xVelocity; //now the collision tests is testing for where on the paddle //the ball is hitting (top 3rd, middle 3rd, bottom 3rd) (changes y Trajectory //based off of where it hits) //(TOP THIRD) if(collisionTest == 3) { pongBall.yVelocity = (sqrtf(2.0)/2.0f); pongBall.xVelocity = (sqrtf(2.0)/2.0f); if(pongBall.yVelocity < 0.0f) { pongBall.yVelocity = -pongBall.yVelocity; } } //(BOT THIRD) else if(collisionTest == 2) { pongBall.yVelocity = (sqrtf(2.0)/2.0f); pongBall.xVelocity = (sqrtf(2.0)/2.0f); if(pongBall.yVelocity > 0.0f) { pongBall.yVelocity = -pongBall.yVelocity; } } //(MIDDLE THIRD) else { pongBall.xVelocity = 1.0f; pongBall.yVelocity = 0.0f; } } if ((collisionTest = DetectCollision(p2Paddle, pongBall))) { pongBall.speed += 0.35; std::cout << collisionTest << std::endl; //switch xVelocity of ball (happens no matter what) pongBall.xVelocity = -pongBall.xVelocity; //now the collision tests is testing for where on the paddle //the ball is hitting (top 3rd, middle 3rd, bottom 3rd) (changes y Trajectory //based off of where it hits) //(TOP THIRD) if(collisionTest == 3) { pongBall.yVelocity = -(sqrtf(2.0)/2.0f); pongBall.xVelocity = -(sqrtf(2.0)/2.0f); if(pongBall.yVelocity < 0.0f) { pongBall.yVelocity = -pongBall.yVelocity; } } //(BOT THIRD) else if(collisionTest == 2) { pongBall.yVelocity = -(sqrtf(2.0)/2.0f); pongBall.xVelocity = -(sqrtf(2.0)/2.0f); if(pongBall.yVelocity > 0.0f) { pongBall.yVelocity = -pongBall.yVelocity; } } //(MIDDLE THIRD) else { pongBall.xVelocity = -1.0f; pongBall.yVelocity = 0.0f; } } if(pongBall.xPosition > MaxXPos-pongBall.width) { pongBall.xVelocity = -pongBall.xVelocity; } if(keys[SDL_SCANCODE_UP]) { p2Paddle.yVelocity = 1.0f; p2Paddle.yPosition += elapsed * (p2Paddle.speed * p2Paddle.yVelocity); if(p2Paddle.yPosition > (MaxYPos-(p2Paddle.height))) { p2Paddle.speed = 0.0f; } else { p2Paddle.speed = 2.4f; } } else if(keys[SDL_SCANCODE_DOWN]) { p2Paddle.yVelocity = -1.0f; p2Paddle.yPosition += elapsed * (p2Paddle.speed * p2Paddle.yVelocity); if(p2Paddle.yPosition < ((-MaxYPos)+(p2Paddle.height))) { p2Paddle.speed = 0.0f; } else { p2Paddle.speed = 2.4f; } } //std::cout << p1ScoreCount << std::endl; }
//Moves and rotate S1 and S2 every tipe a valid user input is made. void Game::moveSquare(Direction dir, GameBoard *board) { CollisionPosition cS1 = DetectCollision(this->s1, board); CollisionPosition cS2 = DetectCollision(this->s2, board); //Move the Square to the right if (dir == Direction::MoveLeft) { if (!cS1.Left && !cS2.Left) { this->s1->SetX(this->s1->GetX() - this->SquareSize); this->s2->SetX(this->s2->GetX() - this->SquareSize); } } //Move the Square to the right if (dir == Direction::MoveRight) { if (!cS1.Rigt && !cS2.Rigt) { this->s1->SetX(this->s1->GetX() + this->SquareSize); this->s2->SetX(this->s2->GetX() + this->SquareSize); } } //Rotates the Square if (dir == Direction::RotateLeft || dir == Direction::RotateRight) { //Variable that tells where to rotate the square: //0 = up, 1=right, 2=down, 3=left byte rotate; //Clockwise direction if (dir == Direction::RotateRight) { //Move up or down if (this->s1->GetY() == this->s2->GetY()) { if (this->s1->GetX() < this->s2->GetX()) rotate = 0; else rotate = 2; } //Move left or right else { if (this->s1->GetY() < this->s2->GetY()) rotate = 3; else rotate = 1; } } //Non-clockwise else if (dir == Direction::RotateLeft) { //Move up or down if (this->s1->GetY() == this->s2->GetY()) { if (this->s1->GetX() < this->s2->GetX()) rotate = 2; else rotate = 0; } //Move left or right else { if (this->s1->GetY() < this->s2->GetY()) rotate = 1; else rotate = 3; } } switch (rotate) { //UP case 0: this->s1->SetX(this->s2->GetX()); this->s1->SetY(this->s2->GetY() + this->SquareSize); break; //RIGHT case 1: this->s1->SetX(this->s2->GetX() + this->SquareSize); this->s1->SetY(this->s2->GetY()); break; //DOWN case 2: this->s1->SetX(this->s2->GetX()); this->s1->SetY(this->s2->GetY() - this->SquareSize); break; //LEFT case 3: this->s1->SetX(this->s2->GetX() - this->SquareSize); this->s1->SetY(this->s2->GetY()); break; } } }
void SphereManager::RunCollision(std::vector<Sphere> &NewSpheres) { // Ãæµ¹ ó¸® // º¹ÀâÇÑ »óȲÀ» ó¸®ÇÏÁö ¸øÇÔ; ÄÚµùÀÌ ÇÊ¿äÇÔ if (m_Spheres.size() < 2) return; std::vector<std::shared_ptr<CollisionInfo> > collisions; // pair.first -> Ãæµ¹Á¤º¸ // pair.second -> `true`À̸é negative - i¿Í j¸¦ ¹Ý´ë·Î! typedef std::multimap<int, std::pair<std::shared_ptr<CollisionInfo>, bool> > col_map_t; col_map_t col_map; // Ãæµ¹ °¨Áö //#pragma omp parallel for for (int i = 0; static_cast<size_t>(i) < m_Spheres.size() - 1; i++) { #pragma omp parallel for for (int j = i + 1; static_cast<size_t>(j) < m_Spheres.size(); j++) { auto ptr = DetectCollision(NewSpheres, i, j, LOGICAL_TIME_SPAN); if (!ptr) continue; #pragma omp critical { collisions.push_back(std::move(ptr)); } } } std::unordered_map<int, double> map_time; // ¸Ç ¸ÕÀú ÀÏ¾î³ Ãæµ¹µéÀ» col_map¿¡ ±â·Ï for (auto &ptr : collisions) { int arkey[2] = { ptr->i, ptr->j }; bool key_is_j = false; for (int key : arkey) { auto it = col_map.find(key); if (it == col_map.end()) { col_map.emplace(key, std::make_pair(ptr, key_is_j)); } else { if (abs(it->second.first->t - ptr->t) < EPSILON) { // Ãæµ¹ÀÌ µ¿½Ã¿¡ ÀϾ col_map.emplace(key, std::make_pair(ptr, key_is_j)); } else if (it->second.first->t > ptr->t) { // `ptr`ÀÇ Ãæµ¹ÀÌ `it->second.first`º¸´Ù ¸ÕÀú ÀϾ it->second.first = ptr; } else { goto cont; } } map_time[key] = ptr->t; cont: key_is_j = true; } } // Ãæ°Ý·®/°¢Ãæ°Ý·®ÀÇ ÃÑÇÕÀ» °è»êÇØ map¿¡ ±â·Ï std::unordered_map<int, std::array<double, 3> > map_sum_I, map_sum_A; std::pair<col_map_t::iterator, col_map_t::iterator> eq_rg; for (int idx = 0; ; ) { eq_rg = col_map.equal_range(idx); if (eq_rg.first != eq_rg.second) { auto i_sum_I = map_sum_I.emplace(idx, std::array<double, 3>{ { 0.0, 0.0, 0.0 } }).first; auto i_sum_A = map_sum_A.emplace(idx, std::array<double, 3>{ { 0.0, 0.0, 0.0 } }).first; std::for_each(eq_rg.first, eq_rg.second, [&NewSpheres, &map_sum_I, &map_sum_A, i_sum_I, i_sum_A, idx] (col_map_t::value_type &pr) { auto &ptr = pr.second.first; if (!ptr->bProcessed) { if (pr.second.second) // j¹ø sphere ±âÁØÀ¸·Î ó¸®ÇØ¾ß ÇÑ´Ù¸é { // j¹ø sphereÀÇ ÁÂÇ¥°è·Î ¹Ù²Þ std::swap(ptr->i, ptr->j); negativen(ptr->p); negativen(ptr->v); } // docs.md#Ãæ°Ý·® ÂüÁ¶ // ÁøÇà ¹æÇâ°ú Ãæ°Ý·®ÀÇ ¹æÇâÀÌ ÆòÇàÇÏÁö ¾ÊÀº °æ¿ì // DetectCollision() ÇÔ¼ö¿¡¼ ÀÌ¹Ì Ã³¸®Ç߱⠶§¹®¿¡ À־ ¾È‰Î. assert(!(ptr->p_dot_v > EPSILON)); auto j_sum_I = map_sum_I.emplace(ptr->j, std::array<double, 3> { { 0.0, 0.0, 0.0 } }).first; auto j_sum_A = map_sum_A.emplace(ptr->j, std::array<double, 3> { { 0.0, 0.0, 0.0 } }).first; double v_length = sqrt(ptr->v_length_2); double cos_theta_2 = square(ptr->p_dot_v) / ptr->p_length_2 / ptr->v_length_2; double sin_theta_2 = 1 - cos_theta_2; double sum_inverse_mass = (1 / NewSpheres[ptr->i].mass) + (1 / NewSpheres[ptr->j].mass); double sum_inverse_moment = (1 / (NewSpheres[ptr->i].mass * 2 / 5)) + (1 / (NewSpheres[ptr->i].mass * 2 / 5)); double J_length = (2 * v_length * cos_theta_2) / (sum_inverse_mass * cos_theta_2 + sum_inverse_moment * sin_theta_2); std::array<double, 3> J = ptr->v; J[0] *= J_length / v_length; J[1] *= J_length / v_length; J[2] *= J_length / v_length; double I_length = J_length * sqrt(cos_theta_2); std::array<double, 3> i_I, j_I; std::array<double, 3> i_moment_arm; std::array<double, 3> j_moment_arm; double p_length = sqrt(ptr->p_length_2); i_moment_arm = ptr->p; i_moment_arm[0] /= p_length; i_moment_arm[1] /= p_length; i_moment_arm[2] /= p_length; j_moment_arm = i_moment_arm; i_I = i_moment_arm; j_I = i_moment_arm; i_I[0] *= I_length; i_I[1] *= I_length; i_I[2] *= I_length; j_I[0] *= -I_length; j_I[1] *= -I_length; j_I[2] *= -I_length; i_moment_arm[0] *= NewSpheres[ptr->i].radius; i_moment_arm[1] *= NewSpheres[ptr->i].radius; i_moment_arm[2] *= NewSpheres[ptr->i].radius; j_moment_arm[0] *= -NewSpheres[ptr->j].radius; j_moment_arm[1] *= -NewSpheres[ptr->j].radius; j_moment_arm[2] *= -NewSpheres[ptr->j].radius; std::array<double, 3> i_A, j_A; cross_product(i_A, i_moment_arm, J); // i_A = i_r x i_J cross_product(j_A, J, j_moment_arm); // j_A = j_r x j_J = j_r x (-i_J) = -(j_r x i_J) = i_J x j_r i_sum_I->second[0] += i_I[0]; i_sum_I->second[1] += i_I[1]; i_sum_I->second[2] += i_I[2]; i_sum_A->second[0] += i_A[0]; i_sum_A->second[1] += i_A[1]; i_sum_A->second[2] += i_A[2]; j_sum_I->second[0] += j_I[0]; j_sum_I->second[1] += j_I[1]; j_sum_I->second[2] += j_I[2]; j_sum_A->second[0] += j_A[0]; j_sum_A->second[1] += j_A[1]; j_sum_A->second[2] += j_A[2]; ptr->bProcessed = true; } }); } if (eq_rg.second == col_map.end()) break; idx = eq_rg.second->first; } // Ãæ°Ý·®/°¢Ãæ°Ý·®À» Åä´ë·Î ÃÖÁ¾ À§Ä¡/¼Óµµ/°¢¼Óµµ °è»ê auto it_sum_I = map_sum_I.begin(); auto it_sum_A = map_sum_A.begin(); for (; it_sum_I != map_sum_I.end(); ++it_sum_I, ++it_sum_A) { int i = it_sum_I->first; const Sphere &oldsp = m_Spheres[i]; Sphere &newsp = NewSpheres[i]; const std::array<double, 3> &pr_I = it_sum_I->second; const std::array<double, 3> &pr_A = it_sum_A->second; std::array<double, 3> dv = { pr_I[0] / oldsp.mass, pr_I[1] / oldsp.mass, pr_I[2] / oldsp.mass }; double moment_of_inerita = 2 * oldsp.mass * square(oldsp.radius) / 5; std::array<double, 3> dw = { pr_A[0] / moment_of_inerita, pr_A[1] / moment_of_inerita, pr_A[2] / moment_of_inerita }; double before_time = map_time[i]; double after_time = LOGICAL_TIME_SPAN - before_time; // Ãæµ¹ ÁöÁ¡±îÁö °è»ê // v = (v0 + v1)/2 // RunForce() ÂüÁ¶ std::array<double, 3> old_v = { (oldsp.velocity[0] + newsp.velocity[0]) / 2, (oldsp.velocity[1] + newsp.velocity[1]) / 2, (oldsp.velocity[2] + newsp.velocity[2]) / 2, }; newsp.coord[0] = oldsp.coord[0] + old_v[0] * before_time; newsp.coord[1] = oldsp.coord[1] + old_v[1] * before_time; newsp.coord[2] = oldsp.coord[2] + old_v[2] * before_time; // ¼Óµµ¸¦ º¯È½ÃŲ ÈÄ ³²Àº ½Ã°£À» µ¿¾È ´Ù½Ã ¿òÁ÷ÀÓ newsp.velocity[0] += dv[0]; newsp.velocity[1] += dv[1]; newsp.velocity[2] += dv[2]; newsp.coord[0] += newsp.velocity[0] * after_time; newsp.coord[1] += newsp.velocity[1] * after_time; newsp.coord[2] += newsp.velocity[2] * after_time; // °¢¼Óµµ¿¡ ´ëÇؼµµ µ¿ÀÏÇÑ Ã³¸® std::array<double, 3> old_w = { (oldsp.AngularVelocity[0] + newsp.AngularVelocity[0]) / 2, (oldsp.AngularVelocity[1] + newsp.AngularVelocity[1]) / 2, (oldsp.AngularVelocity[2] + newsp.AngularVelocity[2]) / 2, }; newsp.angle[0] = oldsp.angle[0] + old_w[0] * before_time; newsp.angle[1] = oldsp.angle[1] + old_w[1] * before_time; newsp.angle[2] = oldsp.angle[2] + old_w[2] * before_time; newsp.AngularVelocity[0] += dw[0]; newsp.AngularVelocity[1] += dw[1]; newsp.AngularVelocity[2] += dw[2]; newsp.angle[0] += newsp.AngularVelocity[0] * after_time; newsp.angle[1] += newsp.AngularVelocity[1] * after_time; newsp.angle[2] += newsp.AngularVelocity[2] * after_time; } }