三维小球弹性碰撞

三维小球弹性碰撞

基于webGL的小球弹性碰撞demo

演示地址:http://htmlpreview.github.io/?https://github.com/wisdomofgod/ball_elastic_collision/blob/master/index.html

二维小球地址: https://github.com/wisdomofgod/ball_elastic_collision/tree/2d

小球弹性碰撞

  • 小球设置 :小球位置,速度,角度由random函数生成,其中角度由x,y, z轴速度控制, 所有小球等大小,显示的大小由距离屏幕远近决定,近大远小,;
  • 小球颜色 :小球颜色由小球所在位置计算得出,色值 = 小球位置 * 0.5, 同时增加由圆心向外的渐变效果;
  • 小球碰撞 :小球碰撞有小球撞击墙壁与撞击其他小球两种情况,有两个撞击的弹性参数决定反弹力。
  •  
  •  

片段着色器

在顶点着色器中,设置v_color = gl_Position * 0.5; 在片段着色器中,首先因为我们要画圆球,所以判断一下当前插值的点跟球心的距离,插值的时候,是按方形进行插值的,我们只对距离小于等于半径的点进行着色, 如果距离小于半径,则设置颜色色值为 v_color + d - 0.2;(为了实现从圆心到边缘的颜色渐变)

代码块

<script id="2d-fragment-shader" type="x-shader/x-fragment">
        precision mediump float;
        varying vec4 v_color;

        void main() {
            gl_FragColor = v_color;

            float d = distance(gl_PointCoord, vec2(0.5,0.5));
            if (d < 0.5) {
                vec4 color = v_color + d - 0.2;
                gl_FragColor = color;
            } else { 
                discard;
            }
        }
    </script>

小球撞击墙体

小球撞击墙壁,在move函数中进行判断,如果撞击墙壁,则将撞击方向的速度 v * bounce (撞击墙壁弹性)

代码块

this.balls.forEach(a => {
        a.x += a.vx;
        a.y += a.vy;
        if (a.x > this.R) {
            a.x = this.R;
            a.vx *= this.bounce;
        }
        if (a.x < this.L) {
            a.x = this.L;
            a.vx *= this.bounce;
        }
        if (a.y > this.T) {
            a.y = this.T;
            a.vy *= this.bounce;
        }
        if (a.y < this.B) {
            a.y = this.B;
            a.vy *= this.bounce;
        }
        if (a.z < this.F) {
            a.z = this.F;
            a.vz *= this.bounce;
        }
        if (a.z > this.BACK) {
            a.z = this.BACK;
            a.vz *= this.bounce;
        }
    });

小球之间碰撞

首先通过两个小球之间的距离,如果距离小于等于小球直径,则两小球叠加 小球发生叠加时,计算三个平面上投影夹角。 首先是两个小球之间的连线在x0z上的投影, 投影的线段长度为 dx * dx + dz * dz 的开平方 (投影上的线段点在x轴、z轴上的投影差值是,坐标系中,两点的x, z轴坐标差值 有了投影线段长后, 我们可以通过反余弦函数acos计算出x,z轴与投影线段的夹角 同时,做投影线段与真实线段的平面,投影点与真实点的高度差是两点坐标的y坐标差值 由此可以计算出投影的夹角 有了这三个夹角,我们就可以计算出,要将两小球分开的最短距离, 这一距离乘以小球间的弹性,得到小球分开的反向加速度。 将反向加速度加上小球的原有x, y, z轴速度。 由于速度值大于反向加速度值,所以小球将继续往里挤压直到速度方向与加速度方向一致后,加速分离。因此可以产生挤压弹开效果。

代码块

if (dist <= this.misDist) {
        //碰撞
        var angle, tx, ty, ax, ay;
        var long = Math.sqrt(dx * dx + dz * dz);
        var angle = Math.acos(dx / long);
        var angle2 = Math.acos(dz / long);
        var angle3 = Math.atan2(dy, long);
        long = Math.cos(angle3) * this.misDist;
        var wy = Math.sin(angle3) * this.misDist;
        var wx = Math.cos(angle) * long;
        var wz = Math.cos(angle2) * long;
        tx = ballA.x + wx;
        ty = ballA.y + wy;
        tz = ballA.z + wz;
        ax = (tx - ballB.x) * this.spring;
        ay = (ty - ballB.y) * this.spring;
        az = (tz - ballB.z) * this.spring;
        ballA.vx -= ax;
        ballA.vy -= ay;
        ballA.vz -= az;
        ballB.vx += ax;
        ballB.vy += ay;
        ballB.vz += az;
    }

转载于:https://my.oschina.net/wisdomofgod/blog/1626957

要进行三维空间小球弹性碰撞的仿真,可以使用MATLAB中的Simulink模块,结合SimMechanics工具箱进行建模和仿真。以下是一个简单的示例模型,演示了两个小球弹性碰撞过程: 1. 首先,在Simulink中创建一个新模型,添加SimMechanics工具箱。 2. 在模型中添加两个Sphere模块,分别代表两个小球。设置小球的质量、半径、初始位置和初始速度等属性。 3. 添加一个Rigid Transform模块,代表小球之间的碰撞。设置碰撞的几何形状和碰撞后的弹性变形等属性。 4. 添加一个Solver Configuration模块,设置仿真的时间步长和仿真时间范围等属性。 5. 连接各个模块,并运行仿真。 以下是示例模型的MATLAB代码: ```matlab clear all; clc; %% 定义小球的属性 m1 = 0.1; % 质量 r1 = 0.05; % 半径 p1_0 = [0;0;0]; % 初始位置 v1_0 = [0;0;0]; % 初始速度 m2 = 0.2; r2 = 0.1; p2_0 = [0.2;0;0]; v2_0 = [-1;0;0]; %% 建立仿真模型 model = 'ball_collision_sim'; open_system(model); set_param(model,'StopTime','1'); % 创建Sphere1模块 add_block('simmechanics/Sources/Sphere','ball_collision_sim/Sphere1'); set_param('ball_collision_sim/Sphere1','radius',num2str(r1)); set_param('ball_collision_sim/Sphere1','mass',num2str(m1)); set_param('ball_collision_sim/Sphere1','initialposition',mat2str(p1_0)); set_param('ball_collision_sim/Sphere1','initialvelocity',mat2str(v1_0)); % 创建Sphere2模块 add_block('simmechanics/Sources/Sphere','ball_collision_sim/Sphere2'); set_param('ball_collision_sim/Sphere2','radius',num2str(r2)); set_param('ball_collision_sim/Sphere2','mass',num2str(m2)); set_param('ball_collision_sim/Sphere2','initialposition',mat2str(p2_0)); set_param('ball_collision_sim/Sphere2','initialvelocity',mat2str(v2_0)); % 创建Rigid Transform模块 add_block('simmechanics/Blocks/Rigid Transform','ball_collision_sim/Rigid Transform'); set_param('ball_collision_sim/Rigid Transform','CollisionType','Ellipsoid'); set_param('ball_collision_sim/Rigid Transform','EllipsoidSize',mat2str([r1*2 r1*2 r1*2])); set_param('ball_collision_sim/Rigid Transform','CoefRestitution','0.8'); % 连接模块 add_line('ball_collision_sim','Sphere1/P1','Rigid Transform/P1'); add_line('ball_collision_sim','Sphere2/P1','Rigid Transform/P2'); % 设置仿真参数 set_param(model,'Solver','ode45','FixedStep','0.001'); %% 运行仿真 sim(model); ``` 运行该代码后,可以在Simulink模型中观察两个小球弹性碰撞过程,并可以通过绘图工具查看小球三维空间中的运动轨迹。你可以根据自己的需求修改小球的属性和碰撞的几何形状,进行更加复杂的模拟。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值