在 Libgdx 中渲染复杂的物体
Rendering Complex Bodies in Libgdx
我正在尝试使用 ShapeRenderer 渲染我在开源工具中制作的物体。
通过简单地检索顶点并将它们返回给 ShapeRenderer,它似乎适用于像正方形这样的简单形状。然而,当涉及到具有大约 9 个多边形(我正在尝试渲染的那个)的复杂物体时,我已经尝试一个一个地渲染多边形,但看起来它一遍又一遍地给我相同的多边形,无论我如何初始化或遍历我的 Vector2[] 列表。我已经坚持了一段时间,任何见解都会有所帮助。 (我正在使用 BodyEditorLoader class 来获取顶点)
BodyEditorLoader Class 我从中获取顶点。 (来自开源库)
public class BodyEditorLoader {
// Model
private final Model model;
// Reusable stuff
private final List<Vector2> vectorPool = new ArrayList<Vector2>();
private final PolygonShape polygonShape = new PolygonShape();
private final CircleShape circleShape = new CircleShape();
private final Vector2 vec = new Vector2();
//My stuff
public Vector2[] shapeVertices;
public ArrayList<Vector2[]> polygonModelList = new ArrayList<>();
public List<PolygonModel> polygonModels = new ArrayList<>();
// -------------------------------------------------------------------------
// Ctors
// -------------------------------------------------------------------------
public BodyEditorLoader(FileHandle file) {
if (file == null) throw new NullPointerException("file is null");
model = readJson(file.readString());
}
public BodyEditorLoader(String str) {
if (str == null) throw new NullPointerException("str is null");
model = readJson(str);
}
public void attachFixture(Body body, String name, FixtureDef fd, float
scale,Object data) {
RigidBodyModel rbModel = model.rigidBodies.get(name);
polygonModels = rbModel.polygons;
if (rbModel == null) throw new RuntimeException("Name '" + name + "' was not found.");
Vector2 origin = vec.set(rbModel.origin).scl(scale);
for (int i=0, n=rbModel.polygons.size(); i<n; i++) {
PolygonModel polygon = rbModel.polygons.get(i);
Vector2[] vertices = polygon.buffer;
//Here is were i'm putting the new vertices into an array
polygonModelList.add(vertices);
for (int ii=0, nn=vertices.length; ii<nn; ii++) {
vertices[ii] = newVec().set(polygon.vertices.get(ii)).scl(scale);
vertices[ii].sub(origin);
}
polygonShape.set(vertices);
shapeVertices = vertices;
fd.shape = polygonShape;
Fixture fixture =body.createFixture(fd);
fixture.setUserData(data);
fixture.getBody();
for (int ii=0, nn=vertices.length; ii<nn; ii++) {
free(vertices[ii]);
}
}
System.out.println(rbModel.polygons.size());
for (int i=0, n=rbModel.circles.size(); i<n; i++) {
CircleModel circle = rbModel.circles.get(i);
Vector2 center = newVec().set(circle.center).scl(scale);
float radius = circle.radius * scale;
circleShape.setPosition(center);
circleShape.setRadius(radius);
fd.shape = circleShape;
Fixture fixture = body.createFixture(fd);
fixture.setUserData(data);
free(center);
}
}
//PolygonModel class
public static class PolygonModel {
public final List<Vector2> vertices = new ArrayList<Vector2>();
public Vector2[] buffer; // used to avoid allocation in attachFixture()
}
上面的代码不是完整的class(只是因为我认为它有很多行)如果你想在这里查看它:https://github.com/MovingBlocks/box2d-editor/tree/develop/loader-libgdx/src/aurelienribon/bodyeditor
我的结构class
public class Structure {
BodyDef bd;
Body body;
FixtureDef fd;
float x;
float y;
Vector2[] originalShapeVertices;
Vector2[] scaledShapeVertices;
ArrayList<Vector2[]> polygonList = new ArrayList<>();
List<BodyEditorLoader.PolygonModel> polygonModels = new ArrayList<>();
public Structure(float x, float y,World world, BodyEditorLoader bodyEditorLoader)
{
this.x = x;
this.y = y;
bd = new BodyDef();
bd.type = BodyDef.BodyType.StaticBody;
bd.position.set(x,y);
body = world.createBody(bd);
body.setUserData(this);
fd = new FixtureDef();
fd.density = 1;
fd.friction = 1;
fd.restitution = 1;
bodyEditorLoader.attachFixture(body,"Structure",fd,500f,this);
//System.out.println(Arrays.toString(bodyEditorLoader.shapeVertices));
polygonModels = bodyEditorLoader.polygonModels;
initVerticesFromModel();
}
public void initVerticesFromModel()
{
for (BodyEditorLoader.PolygonModel model : polygonModels) {
polygonList.add(model.buffer);
}
}
public float[] getPolygonVectors(Vector2 [] vertices)
{
float[] copiedVertices = new float[vertices.length * 2];
for (int i=0, j=0; i<copiedVertices.length; i+=2,j++)
{
copiedVertices[i] = vertices[j].x;
copiedVertices[i+1] = vertices[j].y;
}
return copiedVertices;
}
public Vector2[] getScaledShapeVertices(Vector2[] originalShapeVertices)
{
Vector2[] scaledShapeVertices = new Vector2[originalShapeVertices.length];
for (int i=0; i<scaledShapeVertices.length; i++)
{
Vector2 newVertex = new Vector2(originalShapeVertices[i].x+body.getPosition().x,originalShapeVertices[i].y+body.getPosition().y);
scaledShapeVertices[i] = newVertex;
}
return scaledShapeVertices;
}
public Line2D.Float[] getBodySegments()
{
Vector2[] vertices = scaledShapeVertices;
Line2D.Float[] segments = new Line2D.Float[vertices.length];
for (int i =0; i<segments.length; i++)
{
int nextPoint = i+1;
if (nextPoint >= segments.length)
{
nextPoint = segments.length-1;
segments[i] = new Line2D.Float(vertices[nextPoint].x,vertices[nextPoint].y,vertices[0].x,vertices[0].y);
}
else {
segments[i] = new Line2D.Float(vertices[i].x, vertices[i].y, vertices[nextPoint].x, vertices[nextPoint].y);
}
}
return segments;
}
}
最后我如何使用 ShapeRenderer 渲染它
Structure demo = new Structure(200,100,world,structureLoader);
@public void render()
{
shapeRenderer.setProjectionMatrix(camera.combined);
shapeRenderer.begin(ShapeRenderer.ShapeType.Line);
for(int i =0; i<9; i++) {
float[]polygon =
demo.getPolygonVectors(demo.getScaledShapeVertices(demo.polygonList.get(i)));
shapeRenderer.polygon(polygon);
}
shapeRenderer.end();
}
对于任何想做同样尝试的人,错误来自于我复制了错误的向量列表。而不是复制:
polygon.buffer
您必须复制
List<Vector2> vertices
位于多边形模型中。最后,通过向其中添加每个列表来创建各种列表的列表。
List<List<Vector2>> copiedPolygons = new ArrayList<>();
for(PolygonModel polygon : rbModel.polygons)
{
copiedPolygons.add(polygon.vertices);
}
我正在尝试使用 ShapeRenderer 渲染我在开源工具中制作的物体。 通过简单地检索顶点并将它们返回给 ShapeRenderer,它似乎适用于像正方形这样的简单形状。然而,当涉及到具有大约 9 个多边形(我正在尝试渲染的那个)的复杂物体时,我已经尝试一个一个地渲染多边形,但看起来它一遍又一遍地给我相同的多边形,无论我如何初始化或遍历我的 Vector2[] 列表。我已经坚持了一段时间,任何见解都会有所帮助。 (我正在使用 BodyEditorLoader class 来获取顶点)
BodyEditorLoader Class 我从中获取顶点。 (来自开源库)
public class BodyEditorLoader {
// Model
private final Model model;
// Reusable stuff
private final List<Vector2> vectorPool = new ArrayList<Vector2>();
private final PolygonShape polygonShape = new PolygonShape();
private final CircleShape circleShape = new CircleShape();
private final Vector2 vec = new Vector2();
//My stuff
public Vector2[] shapeVertices;
public ArrayList<Vector2[]> polygonModelList = new ArrayList<>();
public List<PolygonModel> polygonModels = new ArrayList<>();
// -------------------------------------------------------------------------
// Ctors
// -------------------------------------------------------------------------
public BodyEditorLoader(FileHandle file) {
if (file == null) throw new NullPointerException("file is null");
model = readJson(file.readString());
}
public BodyEditorLoader(String str) {
if (str == null) throw new NullPointerException("str is null");
model = readJson(str);
}
public void attachFixture(Body body, String name, FixtureDef fd, float
scale,Object data) {
RigidBodyModel rbModel = model.rigidBodies.get(name);
polygonModels = rbModel.polygons;
if (rbModel == null) throw new RuntimeException("Name '" + name + "' was not found.");
Vector2 origin = vec.set(rbModel.origin).scl(scale);
for (int i=0, n=rbModel.polygons.size(); i<n; i++) {
PolygonModel polygon = rbModel.polygons.get(i);
Vector2[] vertices = polygon.buffer;
//Here is were i'm putting the new vertices into an array
polygonModelList.add(vertices);
for (int ii=0, nn=vertices.length; ii<nn; ii++) {
vertices[ii] = newVec().set(polygon.vertices.get(ii)).scl(scale);
vertices[ii].sub(origin);
}
polygonShape.set(vertices);
shapeVertices = vertices;
fd.shape = polygonShape;
Fixture fixture =body.createFixture(fd);
fixture.setUserData(data);
fixture.getBody();
for (int ii=0, nn=vertices.length; ii<nn; ii++) {
free(vertices[ii]);
}
}
System.out.println(rbModel.polygons.size());
for (int i=0, n=rbModel.circles.size(); i<n; i++) {
CircleModel circle = rbModel.circles.get(i);
Vector2 center = newVec().set(circle.center).scl(scale);
float radius = circle.radius * scale;
circleShape.setPosition(center);
circleShape.setRadius(radius);
fd.shape = circleShape;
Fixture fixture = body.createFixture(fd);
fixture.setUserData(data);
free(center);
}
}
//PolygonModel class
public static class PolygonModel {
public final List<Vector2> vertices = new ArrayList<Vector2>();
public Vector2[] buffer; // used to avoid allocation in attachFixture()
}
上面的代码不是完整的class(只是因为我认为它有很多行)如果你想在这里查看它:https://github.com/MovingBlocks/box2d-editor/tree/develop/loader-libgdx/src/aurelienribon/bodyeditor
我的结构class
public class Structure {
BodyDef bd;
Body body;
FixtureDef fd;
float x;
float y;
Vector2[] originalShapeVertices;
Vector2[] scaledShapeVertices;
ArrayList<Vector2[]> polygonList = new ArrayList<>();
List<BodyEditorLoader.PolygonModel> polygonModels = new ArrayList<>();
public Structure(float x, float y,World world, BodyEditorLoader bodyEditorLoader)
{
this.x = x;
this.y = y;
bd = new BodyDef();
bd.type = BodyDef.BodyType.StaticBody;
bd.position.set(x,y);
body = world.createBody(bd);
body.setUserData(this);
fd = new FixtureDef();
fd.density = 1;
fd.friction = 1;
fd.restitution = 1;
bodyEditorLoader.attachFixture(body,"Structure",fd,500f,this);
//System.out.println(Arrays.toString(bodyEditorLoader.shapeVertices));
polygonModels = bodyEditorLoader.polygonModels;
initVerticesFromModel();
}
public void initVerticesFromModel()
{
for (BodyEditorLoader.PolygonModel model : polygonModels) {
polygonList.add(model.buffer);
}
}
public float[] getPolygonVectors(Vector2 [] vertices)
{
float[] copiedVertices = new float[vertices.length * 2];
for (int i=0, j=0; i<copiedVertices.length; i+=2,j++)
{
copiedVertices[i] = vertices[j].x;
copiedVertices[i+1] = vertices[j].y;
}
return copiedVertices;
}
public Vector2[] getScaledShapeVertices(Vector2[] originalShapeVertices)
{
Vector2[] scaledShapeVertices = new Vector2[originalShapeVertices.length];
for (int i=0; i<scaledShapeVertices.length; i++)
{
Vector2 newVertex = new Vector2(originalShapeVertices[i].x+body.getPosition().x,originalShapeVertices[i].y+body.getPosition().y);
scaledShapeVertices[i] = newVertex;
}
return scaledShapeVertices;
}
public Line2D.Float[] getBodySegments()
{
Vector2[] vertices = scaledShapeVertices;
Line2D.Float[] segments = new Line2D.Float[vertices.length];
for (int i =0; i<segments.length; i++)
{
int nextPoint = i+1;
if (nextPoint >= segments.length)
{
nextPoint = segments.length-1;
segments[i] = new Line2D.Float(vertices[nextPoint].x,vertices[nextPoint].y,vertices[0].x,vertices[0].y);
}
else {
segments[i] = new Line2D.Float(vertices[i].x, vertices[i].y, vertices[nextPoint].x, vertices[nextPoint].y);
}
}
return segments;
}
}
最后我如何使用 ShapeRenderer 渲染它
Structure demo = new Structure(200,100,world,structureLoader);
@public void render()
{
shapeRenderer.setProjectionMatrix(camera.combined);
shapeRenderer.begin(ShapeRenderer.ShapeType.Line);
for(int i =0; i<9; i++) {
float[]polygon =
demo.getPolygonVectors(demo.getScaledShapeVertices(demo.polygonList.get(i)));
shapeRenderer.polygon(polygon);
}
shapeRenderer.end();
}
对于任何想做同样尝试的人,错误来自于我复制了错误的向量列表。而不是复制:
polygon.buffer
您必须复制
List<Vector2> vertices
位于多边形模型中。最后,通过向其中添加每个列表来创建各种列表的列表。
List<List<Vector2>> copiedPolygons = new ArrayList<>();
for(PolygonModel polygon : rbModel.polygons)
{
copiedPolygons.add(polygon.vertices);
}