Processing Project

Processing项目实践——水雾成像(1)

实现

  1. Box2D物理库的boundary设置轮廓
  2. Particle System 模拟流体质感
  3. 群集算法做流体的运动特效

Part One;Box2D物理引擎

关于Box2D物理库

​ box2D对像素是屏蔽的,在processing中将像素转换为box2D的实体

基本要素

world:Box2D的运行环境。在setup里构建。world是经典的笛卡尔坐标系,角度而这恰好相反,

**body:**相当于p5中的图形,自带location,velocity,accelerate等物理特性,无形状特征。(inner attribution)

shape:几何属性,形状可以自绘制,原理和processing中的beginShape类似,

​ shape的作用不单单是外表呈现,也是碰撞检测的计算关键

​ 这里一个实践技巧是逆时针将vertex存在数组中。(outside attribution)

**fixture:**固定器,用来将shape适配于相对的body

**joint:**关节,用用来构建body之间的连接关系,常用于骨骼系统的构建(attraction,repel等),其joint方式有三种:

​ 同样的,利用joint的特性,可以拼凑形状, 也可以物理特性(如弹簧,旋转)

**vec2:**相当于PVector,用法一样,个别语法不同,多用于像素世界和物理世界的标定和追踪

​ 1)语法区别:

Vec2 a=new PVector(1,2);
Vec2 b=new PVector(2,3);
//1.static add
a.add(b);
//2.dynamic add
a.addLocal(b); //⚠️
//3 mag==>length
//4 mult==>multLocal

​ 2) coorPixelsToWorld(x,y) 函数来标定坐标

代码框架

import shiffman.box2d.*;
import org.jbox2d.collision.shapes.*;
import org.jbox2d.common.*;
import org.jbox2d.dynamics.*;
import org.jbox2d.dynamics.joints.*;
import org.jbox2d.dynamics.contacts.*;

// A declaration to box2d world
Box2DProcessing box2d;

// A list we'll use to track fixed objects
ArrayList<Boundary> boundaries;

ArrayList<Box> boxes;//particle basket

void setup() {
  ....
  //创建世界
  box2d = new Box2DProcessing(this);
  box2d.createWorld();
  
  box2d.setGravity(0, -20);//设置重力库,不设置有默认,-20是重力的映射值垂直向下,因此水平为0,垂直为-;

  // Create ArrayLists	
  boxes = new ArrayList<Box>();
  boundaries = new ArrayList<Boundary>();

  // Add a bunch of fixed boundaries
  boundaries.add(new Boundary(width/4,height-5,width/2-50,10));//
	...
}

void draw() {
 ...
  box2d.step();//step is very very important!!
...
 
}

Implementation

1)不同环境的坐标转换–》World changes!!

​ 格式:What-Who-To-Who

​ What:coord 坐标

​ scalar尺寸

​ Who:Pixels:画图的时候专程pixels坐标,在draw中转

​ World:在物理仿真的时候转world ,在setup中转

eg:

void setup(){
  ....
  
  Vec worldloc=box2d.coorPixelsToWorld(mouseX,mouseY);
  ....
}

​ 在setup中正常创建像素对象和变量,并将位置长度等信息转换为world坐标

​ 在draw中,要将物理坐标再转成像素坐标再去画图

  1. create an entity in box2D

在Box2D中,entity=body (fixture[+])shape ,其实质是先创建元素,再组合作用

  • 每个元素的创建流程是相同的
  1. 定义whatDef()

  2. 配置定义体的参数Whatname.attribute.set();

  3. 设置类型

  4. 创建 createWhat(),注意创建的时候是Body 对象

  5. 对象的初始化,可以设置对象的一些基本参数如速度,等objectName.setAttribution();

    其中第一部分是对定义体的定义,相当于对家族的定义

    第4部分是对具体对象的创建,和各个对象的参数设置,这个机制使得一个家族可以创建多个对象,注意其参数配置的语法区别;


  BodyDef bd=new BodyDef();//Def和create是两个声明
	bd.type=BodyType.DYNNAMIC;
	bd.position.set(center);//center 必须是经过坐标系转换的一个向量
	
	Body body=box2d.createBody(bd);
	body.setLinearVelocity(new Vec2(2,3));
	

Body issues

  • 属性的设置包括:

​ position:position.set

​ rotation: fixedRotation

​ damping阻尼:linearDamping/ angularDamping

​ bullut=true ; //子弹效果适用于快速运动的物体,设置bullet保证物体之间的碰撞检测,而不是直接穿过

  • body类型:

    • STATIC:固定的,一般用于设置场景和Boundary
    • DYNAMIC:运动和碰撞,用的比较多
    • KINEMATIC:适合手动控制的对象,只能碰撞动态物体
  • body属性的获取

    • 坐标获取: box2d.getBodyPixelCoord(body);

    • 角度的获取:body.getAngel();

      ​ 一般获取完坐标后我门直接放进matrix里,以body的坐标为中心进行变化

pushMatrix();
translate(pos.x,pos.y);
rotate(-a);//角度相反;
...//正常画图
popMatrix();//matrix保证了物体的旋转和运动不冲突
  • body的清楚
    • box2D.destroyBody(body);

Shape issues

形状的设置和body略有不同

​ PolygonShape ps=new PolygonShape();//形状类有很多
​ ps.setAsBox(boxw,boxh);//注意boxw和boxh要通过scalarPixelsToWorld转换

shape class

  • PolygonShape,参数为w和h,用setAsBox传
  • CircleShape,参数是半径 ,cs.m_radians(box2d.scalearPixelsToWorld®;
  • ChainShape,chain可以画曲线
    • chain和beginShape类似,可以用vertex数组构造
    • chainshape只能画Convex,如果还concave,用convex拼接
chain.createChain(vertexs,vertexs.length);//vertexs是顶点的逆时针存储数组,注意这里的顶点坐标要求是转化过的物理坐标
  • 多个图形拼接,要设置偏移量否则都会以body的center为中心,offset的函数是m_p.set(offset.x,offset.y);

fixture issues

  • 定义
  • 绑定 (形状)
  • 属性设置(这里的属性都是针对的物理身体,可以不设置)
  • 通过body对象创建固定器(createFixture(ps,1),ps,1是密度值)
FixtureDef fd=new FixtureDef();

fd.shape =ps;// 绑定物理身体

body.createFixture(fd);//body.createFixture(ps,1)

固定器的属性包括:

​ 摩擦系数friction

​ 弹性 restitution

​ 密度 density

joints issues

一般是物体间的运动绑定,绑定的连接点是body的中心,也就是锚点,因此在绑定对象的时候保证在类内创建了body

根据绑定指标,分为三种joints:

  • distance joints:

    • frequencyHz (频率设置的范围是1-5,表示震荡频率)
    • dampingRatio(阻尼的范围是0-1)
  • revolute joints:

    • enablemoter是自动旋转,/boolean
    • motorSpeed= float
    • ​ setMotorTorque= float
    • rjd.enableLimit = true;
    • rjd.lowerAngle = -PI/8;
    • rjd.upperAngle = PI/8;
      最简单的revolute joints 可以联想风车
  • mouse joints

mousejoints比较简单,将转换后的鼠标坐标设置为target即可

MouseJoint.setTarget(box2d.coordPixelsToWorld(mouseX,mouseY));

先定义=》在创建=〉在配置

DistanceJointDef djd = new DistanceJointDef(); //定义
djd.bodyA = p1.body;
djd.bodyB = p2.body; //保证p1和p2这两个实例所对应的对象类内有body构建,.body自动锁定锚点
djd.length = box2d.scalarPixelsToWorld(len); //
djd.frequencyHz = 0; 
//创建joints对象
DistanceJoint dj = (DistanceJoint) box2d.world.createJoint(djd); //这里类型转化符号内参数可换,其他类型的Joints操作相同

Joints不一定需要画出来

Conclude all the steps

  1. Define a body using a BodyDef object (set any properties, such as location). 2. Create the Body object from the body definition.
  2. Define a Shape object using PolygonShape, CircleShape, or any other shape class.
  3. Define a fixture using FixtureDef and assign the fixture a shape (set any properties, such as friction, density, and restitution).
  4. Attach the shape to the body. BodyDef

Box2D和Particle System结合要点

​ 1)在setup中引库和定义

​ 2)在Particle的类的构造函数中进行实体的创建部分

​ 3)类体的display函数转坐标并画图

发布了2 篇原创文章 · 获赞 1 · 访问量 30

猜你喜欢

转载自blog.csdn.net/weixin_41749176/article/details/105128787