Skip to content
This repository has been archived by the owner on Dec 8, 2022. It is now read-only.

Commit

Permalink
experiment
Browse files Browse the repository at this point in the history
  • Loading branch information
bowling233 committed Jul 13, 2021
1 parent 12d905c commit 3efbd47
Show file tree
Hide file tree
Showing 12 changed files with 176 additions and 213 deletions.
55 changes: 41 additions & 14 deletions OpenGLProject/Collision.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,23 +78,32 @@ void CollisionSystem::run(const float t)
{
for (auto j = i + 1; j != balls.cend(); j++)
{
sumexam++;
//sumexam++;
if ((**i).examine(**j))
{
//std::cout << "log:###ball bounce\t当前系统时间" << currentTime <<"\ndetail:\t" << (**i).num() << '\t' << (**j).num() << std::endl;//<debug>
(**i).bounce(**j);
sumbounce++;
//sumbounce++;
}
}
if (!walls.empty())
for (auto j = walls.cbegin(); j != walls.cend(); j++)
{
sumexam++;
//sumexam++;
if ((**i).examine(**j))
{
std::cout << "log:###wall bounce\t当前系统时间" << currentTime << "\ndetail:\t" << (**i).num() << '\t' << (**j).num() << std::endl; //<debug>
(**i).bounce(**j);
sumbounce++;
//sumbounce++;
}
}
if(!containers.empty())
for (auto j = containers.cbegin(); j != containers.cend(); j++)
{
//sumexam++;
if ((**i).examine(**j))
{
(**i).bounce(**j);
//sumbounce++;
}
}
}
Expand All @@ -112,9 +121,9 @@ void CollisionSystem::run(const float t)
}//逻辑:第一次进入必定有效,不检测。循环尾清除后必定有效,不检测。因此这个模块可以删除<delete>*/
//std::cout << "log:事件队列处理前" << eventQueue;//<debug>
move(eventQueue.top().t() - currentTime); //有效,跳转到事件发生时间
Event tempEvent = eventQueue.top(); //提出放置,因为需要检测对应物体
tempEvent = eventQueue.top(); //提出放置,因为需要检测对应物体
eventQueue.pop();
sumbounce++; //<info>
//sumbounce++; //<info>
//std::cout << "当前系统时间:" << currentTime << std::endl;//<debug>
tempEvent.handle(); //处理事件,处理时小球自动递增计数器

Expand All @@ -125,11 +134,11 @@ void CollisionSystem::run(const float t)
if (!hidden_balls.empty())
for (auto const &i : hidden_balls)
if ((temp = tempEvent.ball->predict(*i)) >= 0) //predict内置防重复
eventQueue.push(Event(tempEvent.ball, i, temp + currentTime));
eventQueue.push(Event(tempEvent.ball, i, temp + currentTime));/*
if (!walls.empty())
for (auto const &i : walls)
if ((temp = tempEvent.ball->predict(*i)) >= 0) //平面无需防重复
eventQueue.push(Event(tempEvent.ball, i, temp + currentTime));
eventQueue.push(Event(tempEvent.ball, i, temp + currentTime));/**/
if (!containers.empty())
for (auto const &i : containers)
if ((temp = tempEvent.ball->predict(*i)) >= 0) //容器无需防重复
Expand All @@ -145,11 +154,11 @@ void CollisionSystem::run(const float t)
if (!hidden_balls.empty())
for (auto const &i : hidden_balls)
if ((temp = tempball->predict(*i)) >= 0) //predict内置防重复
eventQueue.push(Event(tempball, i, temp + currentTime));
eventQueue.push(Event(tempball, i, temp + currentTime));/*/
if (!walls.empty())
for (auto const &i : walls)
if ((temp = tempball->predict(*i)) >= 0)
eventQueue.push(Event(tempball, i, temp + currentTime));
eventQueue.push(Event(tempball, i, temp + currentTime));//*/
if (!containers.empty())
for (auto const &i : containers)
if ((temp = tempball->predict(*i)) >= 0)
Expand All @@ -168,6 +177,7 @@ void CollisionSystem::run(const float t)
flag = -1;
}*/
#endif
//std::cout << "当前系统时间:" << currentTime << std::endl;//<debug>
}

void CollisionSystem::reverse()
Expand Down Expand Up @@ -203,18 +213,35 @@ void CollisionSystem::init()
eventQueue.push(Event(*i, *j, temp + currentTime));
}
if (!hidden_balls.empty())
for (auto const &j : hidden_balls)
for (auto const& j : hidden_balls)
if ((temp = (**i).predict(*j)) >= 0)
eventQueue.push(Event(*i, j, temp + currentTime));
if (!walls.empty())
for (auto const &j : walls)
for (auto const& j : walls)
if ((temp = (**i).predict(*j)) >= 0)
eventQueue.push(Event(*i, j, temp + currentTime));
if (!containers.empty())
for (auto const &j : containers)
for (auto const& j : containers)
if ((temp = (**i).predict(*j)) >= 0)
eventQueue.push(Event(*i, j, temp + currentTime));
}
if(!hidden_balls.empty())
for (auto i = hidden_balls.cbegin(); i != hidden_balls.cend(); i++)
{
for (auto j = i + 1; j != hidden_balls.cend(); j++)
{
if (((temp = (**i).predict(**j)) >= 0))
eventQueue.push(Event(*i, *j, temp + currentTime));
}
if (!walls.empty())
for (auto const& j : walls)
if ((temp = (**i).predict(*j)) >= 0)
eventQueue.push(Event(*i, j, temp + currentTime));
if (!containers.empty())
for (auto const& j : containers)
if ((temp = (**i).predict(*j)) >= 0)
eventQueue.push(Event(*i, j, temp + currentTime));
}
std::cout << "log:当前使用事件驱动方式:" << eventQueue.size() << std::endl;
//std::cout << eventQueue << std::endl;
#endif
Expand Down
8 changes: 6 additions & 2 deletions OpenGLProject/Collision.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ extern int sumbounce;
extern int sumexam;

#ifdef TIME_DRIVEN
constexpr auto DELTATIME = 1.0f / 360.0f; //时间驱动专用
constexpr auto DELTATIME = 1.0f / 120.0f; //时间驱动专用
#endif

#ifdef EVENT_DRIVEN
Expand Down Expand Up @@ -42,6 +42,7 @@ class Event
public:
//construct
Event(std::shared_ptr<Ball> b, std::shared_ptr<Object> o, const float t) : ball(b), object(o), time(t), countBall(b->cnt()), countObject(o->cnt()) {}
Event() = default;

//copy move destruct
Event(const Event &) = default;
Expand Down Expand Up @@ -97,14 +98,17 @@ class CollisionSystem
std::vector<std::shared_ptr<Ball>> &hb() { return hidden_balls; }
std::vector<std::shared_ptr<Wall>> &w() { return walls; }
std::vector<std::shared_ptr<Container>> &c() { return containers; }
std::priority_queue<Event, std::vector<Event>> &e() { return eventQueue; }
#ifdef EVENT_DRIVEN
std::priority_queue<Event, std::vector<Event>>& e() { return eventQueue; }
#endif // EVENT_DRIVEN

private:
void move(float);
void init();

#ifdef EVENT_DRIVEN
std::shared_ptr<Ball> tempball; //temp:副小球检测
Event tempEvent;
#endif
std::vector<std::shared_ptr<Ball>> balls, hidden_balls;
std::vector<std::shared_ptr<Wall>> walls;
Expand Down
77 changes: 35 additions & 42 deletions OpenGLProject/Object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,15 @@
#include <memory>

//definition

unsigned int Wall::sum = 0;
unsigned int Ball::sum = 0;
unsigned int Container::sum = 0;

//temp
glm::vec3 dp, dv;
float p_n, v_n, a, b, c, delta, x1, x2, temp;
float v10, v20, v1, v2;

//tools---------------------------------------------------------------------------------------------
std::ostream &operator<<(std::ostream &os, const glm::vec3 &v)
{
Expand All @@ -32,7 +36,7 @@ std::istream &operator>>(std::istream &is, glm::vec3 &v)

float positive_min(float a, float b, float c)
{
float temp = INFINITY;
temp = INFINITY;
if ((a > 0) && (a < temp))
temp = a;
if ((b > 0) && (b < temp))
Expand Down Expand Up @@ -86,25 +90,15 @@ Ball::Ball(std::istream &is) : Ball()

float Ball::predict(const Wall &wall) //tochk
{
std::cout << "predict:墙体" << this->number << "|" << wall.num() << std::endl; //<debug>
glm::vec3 p = location - wall.loc();
float p_n = glm::dot(p, wall.norm()); //球到平面的垂直距离
float v_n = glm::dot(velocity, wall.norm()); //速度在平面法向量方向上的分量
//std::cout << "predict:墙体" << this->number << "|" << wall.num() << std::endl; //<debug>
dp = location - wall.loc();
p_n = glm::dot(dp, wall.norm()); //球到平面的垂直距离
v_n = glm::dot(velocity, wall.norm()); //速度在平面法向量方向上的分量

if (v_n * p_n >= 0)
return -1.0f;
std::cout << "pass" << std::endl;
//std::cout << "pass" << std::endl;
return -p_n / v_n;
//another solution
/*
glm::vec3 r = location - wall.loc();
glm::vec3 chk_nor = (glm::dot(r, wall.norm())) > 0 ? wall.norm() : -wall.norm(); //选择一个背向球的法向量
float v_l = glm::dot(velocity, chk_nor);//速度在平面法向量方向上的分量
if (v_1 < 0)
return -1.0f; //背向运动
float r_l = glm::dot(r, chk_nor); //球到平面的垂直距离
return r_l / v_l;
/*/
}

float Ball::predict(const Ball &ball) //tochk
Expand All @@ -114,24 +108,24 @@ float Ball::predict(const Ball &ball) //tochk
if (number == ball.number) //防止自预测
return -1.0f;

glm::vec3 dp = location - ball.location, //以ball为中心
dv = velocity - ball.velocity;

if (this->back(ball))
return -1.0;

dp = location - ball.location; //以ball为中心
dv = velocity - ball.velocity;

//std::cout << "predict:计算信息 dv dp r1 r2\n" << dv << dp << this->radius << '\t' << ball.radius << std::endl;//<debug>

float a = square(glm::length(dv));
float b = 2.0 * glm::dot(dv, dp);
float c = square(glm::length(dp)) - square(radius + ball.radius);
float delta = square(b) - 4.0 * a * c;
a = square(glm::length(dv));
b = 2.0f * glm::dot(dv, dp);
c = square(glm::length(dp)) - square(radius + ball.radius);
delta = square(b) - 4.0f * a * c;

if (delta < 0.0)
return -1.0;

float x1 = ((-b + std::sqrt(delta)) / (2.0 * a));
float x2 = ((-b - std::sqrt(delta)) / (2.0 * a));
x1 = ((-b + std::sqrt(delta)) / (2.0f * a));
x2 = ((-b - std::sqrt(delta)) / (2.0f * a));

if (x2 < 0 || x1 < 0) //事实上,这里小球已经相交
return -1.0;
Expand Down Expand Up @@ -220,18 +214,16 @@ void Ball::bounce(Ball &ball)
//if (this->back(ball))
// return;

glm::vec3 r = glm::normalize(location - ball.location);
dp = glm::normalize(location - ball.location);

float v10 = glm::dot(r, velocity),
v20 = glm::dot(r, ball.velocity),
m1 = mass,
m2 = ball.mass;
v10 = glm::dot(dp, velocity);
v20 = glm::dot(dp, ball.velocity);

float v1 = ((m1 - m2) * v10 + 2 * m2 * v20) / (m1 + m2),
v2 = ((m2 - m1) * v20 + 2 * m1 * v10) / (m1 + m2);
v1 = ((mass - ball.mass) * v10 + 2 * ball.mass * v20) / (mass + ball.mass);
v2 = ((ball.mass - mass) * v20 + 2 * mass * v10) / (mass + ball.mass);

velocity += (v1 - v10) * r;
ball.velocity += (v2 - v20) * r;
velocity += (v1 - v10) * dp;
ball.velocity += (v2 - v20) * dp;
count++;
ball.count++;
//std::cout << "info:碰撞处理后\n主小球:\t" << *this << "\n副小球:\t" << ball << std::endl;//<debug>
Expand Down Expand Up @@ -308,17 +300,18 @@ bool Ball::examine(const Wall &wall)

bool Ball::examine(const Container &container) //tochk
{
return ((location.x + radius < container.x_p()) && (location.x - radius > container.x_n())) && ((location.y + radius < container.y_p()) && (location.y - radius > container.y_n())) && ((location.z + radius < container.z_p()) && (location.z - radius > container.z_n()));
return ((location.x + radius > container.x_p())
|| (location.x - radius < container.x_n()))
|| ((location.y + radius > container.y_p())
|| (location.y - radius < container.y_n()))
|| ((location.z + radius > container.z_p())
|| (location.z - radius < container.z_n()));
}

bool Ball::back(const Ball &ball)
{
if ((glm::dot(-(location - ball.location), velocity) < 0) && (glm::dot(location - ball.location, ball.velocity) < 0))
{
//std::cout << "error:背向运动" << std::endl;
return true;
}
return false;
return ((glm::dot(-(location - ball.location), velocity) < 0)
&& (glm::dot(location - ball.location, ball.velocity) < 0));
}

//io------------------------------------------------------------------------------------------------------------
Expand Down
7 changes: 5 additions & 2 deletions OpenGLProject/Object.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ enum class Object_type
std::ostream &operator<<(std::ostream &, const glm::vec3 &);
std::istream &operator>>(std::istream &, glm::vec3 &);



class Object //protected:location
{
public:
Expand Down Expand Up @@ -101,8 +103,8 @@ class Ball final : public Object //velocity,mass
~Ball() = default;

//information
glm::vec3 v() const { return velocity; }
float r() const { return radius; }
glm::vec3 vel() const { return velocity; }
float m() const { return mass; }
float ek() const { return 0.5f * mass * square(glm::length(velocity)); }
unsigned int cnt() const { return count; }
Expand All @@ -128,9 +130,10 @@ class Ball final : public Object //velocity,mass
bool examine(const Wall &);
bool examine(const Ball &);
bool examine(const Container &);
bool back(const Ball &);


private:
bool back(const Ball&);
glm::vec3 velocity;
float mass, radius;
static unsigned int sum; //extern
Expand Down
18 changes: 1 addition & 17 deletions OpenGLProject/OpenGLProject.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -20,29 +20,13 @@
</ItemGroup>
<ItemGroup>
<ClCompile Include="Collision.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="main_test.cpp" />
<ClCompile Include="Object.cpp" />
<ClCompile Include="Sphere.cpp" />
<ClCompile Include="Utils.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="Collision.h" />
<ClInclude Include="Object.h" />
</ItemGroup>
<ItemGroup>
<Text Include="in.txt" />
</ItemGroup>
<ItemGroup>
<None Include="fs_coord.glsl" />
<None Include="fs_plane.glsl" />
<None Include="fs_sphere.glsl" />
<None Include="tcs_plane.glsl" />
<None Include="tes_plane.glsl" />
<None Include="vs_container.glsl" />
<None Include="vs_coord.glsl" />
<None Include="vs_plane.glsl" />
<None Include="vs_sphere.glsl" />
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
Expand Down
Loading

0 comments on commit 3efbd47

Please sign in to comment.