private void setVertex(int index, MeshPartBuilder.VertexInfo info) { index *= stride; if(posPos >= 0) { vertices[index + posPos + 0] = info.position.x; vertices[index + posPos + 1] = info.position.y; vertices[index + posPos + 2] = info.position.z; } if(uvPos >= 0) { vertices[index + uvPos + 0] = info.uv.x; vertices[index + uvPos + 1] = info.uv.y; } if(norPos >= 0) { vertices[index + norPos + 0] = info.normal.x; vertices[index + norPos + 1] = info.normal.y; vertices[index + norPos + 2] = info.normal.z; } }
private MeshPartBuilder.VertexInfo calculateNormalAt(MeshPartBuilder.VertexInfo out, int x, int z) { // handle edges of terrain int xP1 = (x+1 >= vertexResolution) ? vertexResolution -1 : x+1; int yP1 = (z+1 >= vertexResolution) ? vertexResolution -1 : z+1; int xM1 = (x-1 < 0) ? 0 : x-1; int yM1 = (z-1 < 0) ? 0 : z-1; float hL = heightData[z * vertexResolution + xM1]; float hR = heightData[z * vertexResolution + xP1]; float hD = heightData[yM1 * vertexResolution + x]; float hU = heightData[yP1 * vertexResolution + x]; out.normal.x = hL - hR; out.normal.y = 2; out.normal.z = hD - hU; out.normal.nor(); return out; }
public void constructCells() { builder.begin(); int vertAttrs = Position | Normal | TextureCoordinates; for(int x = 0; x < cells.length; x++) { for (int z = 0; z < cells[x].length; z++) { MeshPartBuilder partBuilder = builder.part("cell"+x+","+z, GL30.GL_TRIANGLES, vertAttrs, Reference.Defaults.Models.material()); partBuilder.rect(getPoint("D", x, z), getPoint("C", x, z), getPoint("B", x, z), getPoint("A", x, z), Vector3.Y); cells[x][z].setCellPart(partBuilder.getMeshPart()); cells[x][z].init(); } } model = builder.end(); instance = new ModelInstance(model); }
private void setVertex(int index, MeshPartBuilder.VertexInfo info) { index *= stride; if (posPos >= 0) { vertices[index + posPos] = info.position.x; vertices[index + posPos + 1] = info.position.y; vertices[index + posPos + 2] = info.position.z; } if (uvPos >= 0) { vertices[index + uvPos] = info.uv.x; vertices[index + uvPos + 1] = info.uv.y; } if (norPos >= 0) { vertices[index + norPos] = info.normal.x; vertices[index + norPos + 1] = info.normal.y; vertices[index + norPos + 2] = info.normal.z; } }
public static Model createAxes() { final float GRID_MIN = -10f; final float GRID_MAX = 10f; final float GRID_STEP = 1f; ModelBuilder modelBuilder = new ModelBuilder(); modelBuilder.begin(); MeshPartBuilder builder = modelBuilder.part("grid", GL20.GL_LINES, VertexAttributes.Usage.Position | VertexAttributes.Usage.ColorUnpacked, new Material()); builder.setColor(Color.LIGHT_GRAY); for (float t = GRID_MIN; t <= GRID_MAX; t += GRID_STEP) { builder.line(t, 0, GRID_MIN, t, 0, GRID_MAX); builder.line(GRID_MIN, 0, t, GRID_MAX, 0, t); } builder = modelBuilder.part("axes", GL20.GL_LINES, VertexAttributes.Usage.Position | VertexAttributes.Usage.ColorUnpacked, new Material()); builder.setColor(Color.RED); builder.line(0, 0, 0, 100, 0, 0); builder.setColor(Color.GREEN); builder.line(0, 0, 0, 0, 100, 0); builder.setColor(Color.BLUE); builder.line(0, 0, 0, 0, 0, 100); return modelBuilder.end(); }
@Override public boolean mouseMoved(int screenX, int screenY) { if (this.model == null || modelInstance == null) return false; final ProjectContext context = getProjectManager().current(); final Ray ray = getProjectManager().current().currScene.viewport.getPickRay(screenX, screenY); if (context.currScene.terrains.size > 0 && modelInstance != null) { MeshPartBuilder.VertexInfo vi = TerrainUtils.getRayIntersectionAndUp(context.currScene.terrains, ray); if (vi != null) { if (shouldRespectTerrainSlope) { modelInstance.transform.setToLookAt(DEFAULT_ORIENTATION, vi.normal); } modelInstance.transform.setTranslation(vi.position); } } else { tempV3.set(getProjectManager().current().currScene.cam.position); tempV3.add(ray.direction.nor().scl(200)); modelInstance.transform.setTranslation(tempV3); } return false; }
public static Model buildPlaneModel(final float width, final float height, final Material material, final float u1, final float v1, final float u2, final float v2) { ModelBuilder modelBuilder = new ModelBuilder(); modelBuilder.begin(); MeshPartBuilder bPartBuilder = modelBuilder.part("rect", GL20.GL_TRIANGLES, VertexAttributes.Usage.Position | VertexAttributes.Usage.Normal | VertexAttributes.Usage.TextureCoordinates, material); bPartBuilder.setUVRange(u1, v1, u2, v2); bPartBuilder.rect(-(width * 0.5f), -(height * 0.5f), 0, (width * 0.5f), -(height * 0.5f), 0, (width * 0.5f), (height * 0.5f), 0, -(width * 0.5f), (height * 0.5f), 0, 0, 0, -1); return (modelBuilder.end()); }
private void createAxes () { ModelBuilder modelBuilder = new ModelBuilder(); modelBuilder.begin(); MeshPartBuilder builder = modelBuilder.part("grid", GL20.GL_LINES, Usage.Position | Usage.Color, new Material()); builder.setColor(Color.LIGHT_GRAY); for (float t = GRID_MIN; t <= GRID_MAX; t += GRID_STEP) { builder.line(t, 0, GRID_MIN, t, 0, GRID_MAX); builder.line(GRID_MIN, 0, t, GRID_MAX, 0, t); } builder = modelBuilder.part("axes", GL20.GL_LINES, Usage.Position | Usage.Color, new Material()); builder.setColor(Color.RED); builder.line(0, 0, 0, 100, 0, 0); builder.setColor(Color.GREEN); builder.line(0, 0, 0, 0, 100, 0); builder.setColor(Color.BLUE); builder.line(0, 0, 0, 0, 0, 100); axesModel = modelBuilder.end(); axesInstance = new ModelInstance(axesModel); }
public Game3d(){ ship = Asset.loadModelObj("ship");//loads an obj model ship.scale(3f); skydome = Asset.loadModel("skydome"); //loads a g3db model builder = new ModelBuilder(); builder.begin(); MeshPartBuilder part = builder.part("floor", GL20.GL_TRIANGLES, Usage.Position | Usage.TextureCoordinates | Usage.Normal, new Material()); for (float x = -200f; x < 200f; x += 10f) { for (float z = -200f; z < 200f; z += 10f) { part.rect(x, 0, z + 10f, x + 10f, 0, z + 10f, x + 10f, 0, z, x, 0, z, 0, 1, 0); } } floor = new Actor3d(builder.end()); floor.materials.get(0).set(TextureAttribute.createDiffuse(Asset.tex("concrete").getTexture())); knight = Asset.loadModel("knight"); knight.setPosition(-20f, 18f, 0f); knight.setPitch(-90f); addActor3d(floor); addActor3d(skydome); addActor3d(ship); addActor3d(knight); stage3d.getCamera().position.set(knight.getX()+ 13f, knight.getY() + 24f, knight.getZ() + 45f); //Camera3d.followOffset(20f, 20f, -20f); // Camera3d.followActor3d(knight, false); }
public static void createFloor() { ModelBuilder modelBuilder = new ModelBuilder(); modelBuilder.begin(); MeshPartBuilder mpb = modelBuilder.part("parts", GL20.GL_TRIANGLES, Usage.Position | Usage.Normal | Usage.ColorUnpacked, new Material( ColorAttribute.createDiffuse(Color.WHITE))); mpb.setColor(1f, 1f, 1f, 1f); // mpb.box(0, -0.1f, 0, 10, .2f, 10); mpb.rect(-10, 0, -10, -10, 0, 10, 10, 0, 10, 10, 0, -10, 0, 1, 0); floorModel = modelBuilder.end(); floorInstance = new ModelInstance(floorModel); // TODO Set only when FBO is active floorInstance.materials.get(0).set(new BlendingAttribute(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA)); }
private static void createAxes() { ModelBuilder modelBuilder = new ModelBuilder(); modelBuilder.begin(); MeshPartBuilder builder = modelBuilder.part("grid", GL20.GL_LINES, Usage.Position | Usage.ColorUnpacked, new Material()); builder.setColor(Color.LIGHT_GRAY); for (float t = GRID_MIN; t <= GRID_MAX; t+=GRID_STEP) { builder.line(t, 0, GRID_MIN, t, 0, GRID_MAX); builder.line(GRID_MIN, 0, t, GRID_MAX, 0, t); } builder = modelBuilder.part("axes", GL20.GL_LINES, Usage.Position | Usage.ColorUnpacked, new Material()); builder.setColor(Color.RED); builder.line(0, 0, 0, 10, 0, 0); builder.setColor(Color.GREEN); builder.line(0, 0, 0, 0, 10, 0); builder.setColor(Color.BLUE); builder.line(0, 0, 0, 0, 0, 10); axesModel = modelBuilder.end(); axesInstance = new ModelInstance(axesModel); }
private void buildTriangles() { //System.out.printf("chunk: startXZ: %d, %d -- length: %d\n", startX, startZ, length); int count = 0; MeshPartBuilder.VertexInfo right; MeshPartBuilder.VertexInfo down; MeshPartBuilder.VertexInfo downRight; for (int z = 0; z < vertexInfos.length - 1; z++) { for (int x = 0; x < (vertexInfos[0].length - 1); x++) { MeshPartBuilder.VertexInfo vert = vertexInfos[z][x]; right = vertexInfos[z][x+1]; down = vertexInfos[z+1][x]; downRight = vertexInfos[z+1][x+1]; // each z row has two trianagles forming a rect int xIdx = x*2; Triangle top = new Triangle(z, xIdx, vert, down, right); Triangle bottom = new Triangle(z, xIdx+1, downRight, right, down); count += 2; } } System.out.println("built " + count + " triangles"); }
private void setVertexPositions() { // store vertex info for second pass where we calculate vertex normals for per-vertex lighting float[][] pts = heightMap.heights; float blockSize = heightMap.getWidthScale(); float heightScale = heightMap.getHeightScale(); float width = heightMap.getWidthWorld(); float depth = heightMap.getDepthWorld(); for (int z = 0; z < pts.length; z++) { for (int x = 0; x < pts[z].length; x++) { float y = pts[z][x]; MeshPartBuilder.VertexInfo thisVert = new MeshPartBuilder.VertexInfo(); thisVert.setPos(x * blockSize, y * heightScale, z * blockSize); // set texture UV float u = (x * blockSize) / width; float v = (z * blockSize) / depth; float scl = heightScale; scl = 1f; thisVert.setUV(u * scl, v * scl); vertexInfos[z][x] = thisVert; } } }
public Triangle(int triZ, int triX, MeshPartBuilder.VertexInfo a, MeshPartBuilder.VertexInfo b, MeshPartBuilder.VertexInfo c) { zidx = triZ; xidx = triX; try { tris[triZ][triX] = this; } catch (ArrayIndexOutOfBoundsException e) { e.printStackTrace(); Tools.sleep(500); System.out.println("tried ZX: " + triZ + ", " + triX); System.out.println("length ZX: " + tris.length + ", " + tris[0].length); System.exit(5); } this.a = a; this.b = b; this.c = c; this.calculateFaceNormal(); }
public void createBillboardTest() { ModelBuilder mb = new ModelBuilder(); mb.begin(); long attr = Usage.TextureCoordinates | Usage.Position | Usage.Normal; TextureRegion region = Assets.getAtlas().findRegion("sprites/test-guy"); Material mat = new Material(TextureAttribute.createDiffuse(region.getTexture())); boolean blended = true; float opacity = 1f; mat.set(new BlendingAttribute(blended, GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA, opacity)); MeshPartBuilder mpb = mb.part("rect", GL20.GL_TRIANGLES, attr, mat); mpb.setUVRange(region); // the coordinates are offset so that we can easily set the center position to align with the entity's body float sz = 2f; // size float b = -sz/2; // base float max = sz/2; // max Vector3 bl = new Vector3(b, b, 0f); Vector3 br = new Vector3(b, max, 0f); Vector3 tr = new Vector3(max, max, 0f); Vector3 tl = new Vector3(max, b, 0f); Vector3 norm = new Vector3(0f, 0f, 1f); mpb.rect(bl, tl, tr, br, norm); billboardTestModel = mb.end(); }
public ModelInstance createAxes () { ModelBuilder modelBuilder = new ModelBuilder(); modelBuilder.begin(); MeshPartBuilder builder = modelBuilder.part("grid", GL20.GL_LINES, Usage.Position | Usage.Color, new Material()); builder.setColor(Color.LIGHT_GRAY); for (float t = GRID_MIN; t <= GRID_MAX; t += GRID_STEP) { builder.line(t, 0, GRID_MIN, t, 0, GRID_MAX); builder.line(GRID_MIN, 0, t, GRID_MAX, 0, t); } builder = modelBuilder.part("axes", GL20.GL_LINES, Usage.Position | Usage.Color, new Material()); builder.setColor(Color.RED); builder.line(0, 0, 0, 100, 0, 0); builder.setColor(Color.GREEN); builder.line(0, 0, 0, 0, 100, 0); builder.setColor(Color.BLUE); builder.line(0, 0, 0, 0, 0, 100); Model axesModel = modelBuilder.end(); ModelInstance axesInstance = new ModelInstance(axesModel); return axesInstance; }
private MeshPartBuilder.VertexInfo calculateVertexAt(MeshPartBuilder.VertexInfo out, int x, int z) { final float dx = (float)x / (float)(vertexResolution - 1); final float dz = (float)z / (float)(vertexResolution - 1); final float height = heightData[z * vertexResolution + x]; out.position.set(dx * this.terrainWidth, height, dz * this.terrainDepth); out.uv.set(dx, dz).scl(uvScale); return out; }
public static WorldObjectCharacter createDefaultPlayerCharacter(GameWorld.Generic world) { modelBuilder.begin(); MeshPartBuilder builder = modelBuilder.part("player_body", GL30.GL_TRIANGLES, VertexAttributes.Usage.Position | VertexAttributes.Usage.Normal | VertexAttributes.Usage.TextureCoordinates, Reference.Defaults.Models.material()); CapsuleShapeBuilder.build(builder, 75, 500, 64); WorldObject obj = new WorldObject(world, new ModelInstance(modelBuilder.end())); if(world instanceof GameWorld.Physics) { world.addInstance(new BulletEntity<>(world, obj.transform(), obj)); }else{ world.addInstance(obj); } return new WorldObjectCharacter(obj); }
@Override public void renderTop(int atlasIndex, float x1, float z1, float x2, float z2, float y, float lightLevel, PerCornerLightData pcld, MeshBuilder builder) { float u = getU(atlasIndex); float v = getV(atlasIndex); builder.setUVRange(u, v, u, v); MeshPartBuilder.VertexInfo c00 = new MeshPartBuilder.VertexInfo().setPos(x1, y, z1).setNor(0, 1, 0); MeshPartBuilder.VertexInfo c01 = new MeshPartBuilder.VertexInfo().setPos(x1, y, z2).setNor(0, 1, 0); MeshPartBuilder.VertexInfo c10 = new MeshPartBuilder.VertexInfo().setPos(x2, y, z1).setNor(0, 1, 0); MeshPartBuilder.VertexInfo c11 = new MeshPartBuilder.VertexInfo().setPos(x2, y, z2).setNor(0, 1, 0); IChunk chunk = RadixClient.getInstance().getWorld().getChunk((int) x1, (int) z1); Biome biome; if(chunk != null) { biome = chunk.getBiome(); } else { biome = RadixAPI.instance.getBiomeByID(0); } int[] color = biome.getGrassColor((int) y - 1); float r = color[0]/255f; float g = color[1]/255f; float b = color[2]/255f; if(pcld == null) { builder.setColor(r*lightLevel, g*lightLevel, b*lightLevel, 1); } else { c00.setCol(r*pcld.l00, g*pcld.l00, b*pcld.l00, 1); c01.setCol(r*pcld.l01, g*pcld.l01, b*pcld.l01, 1); c10.setCol(r*pcld.l10, g*pcld.l10, b*pcld.l10, 1); c11.setCol(r*pcld.l11, g*pcld.l11, b*pcld.l11, 1); } builder.rect(c01, c11, c10, c00); }
private MeshPartBuilder.VertexInfo calculateVertexAt(MeshPartBuilder.VertexInfo out, int x, int z) { final float dx = (float) x / (float) (vertexResolution - 1); final float dz = (float) z / (float) (vertexResolution - 1); final float height = heightData[z * vertexResolution + x]; out.position.set(dx * this.terrainWidth, height, dz * this.terrainDepth); out.uv.set(dx, dz).scl(uvScale); return out; }
public static Model createArrowStub(Material mat, Vector3 from, Vector3 to) { ModelBuilder modelBuilder = new ModelBuilder(); modelBuilder.begin(); MeshPartBuilder meshBuilder; // line meshBuilder = modelBuilder.part("line", GL20.GL_LINES, VertexAttributes.Usage.Position | VertexAttributes.Usage.ColorUnpacked, mat); meshBuilder.line(from.x, from.y, from.z, to.x, to.y, to.z); // stub Node node = modelBuilder.node(); node.translation.set(to.x, to.y, to.z); meshBuilder = modelBuilder.part("stub", GL20.GL_TRIANGLES, Usage.Position | Usage.Normal, mat); BoxShapeBuilder.build(meshBuilder, 2, 2, 2); return modelBuilder.end(); }
@Override public void create () { texture = new Texture(Gdx.files.internal("data/badlogic.jpg"), true); // Create material attributes. Each material can contain x-number of attributes. textureAttribute = new TextureAttribute(TextureAttribute.Diffuse, texture); colorAttribute = new ColorAttribute(ColorAttribute.Diffuse, Color.ORANGE); blendingAttribute = new BlendingAttribute(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA); ModelBuilder builder = new ModelBuilder(); model = builder.createBox(1, 1, 1, new Material(), Usage.Position | Usage.Normal | Usage.TextureCoordinates); model.manageDisposable(texture); modelInstance = new ModelInstance(model); modelInstance.transform.rotate(Vector3.X, 45); material = modelInstance.materials.get(0); builder.begin(); MeshPartBuilder mpb = builder.part("back", GL20.GL_TRIANGLES, Usage.Position | Usage.TextureCoordinates, new Material( textureAttribute)); mpb.rect(-2, -2, -2, 2, -2, -2, 2, 2, -2, -2, 2, -2, 0, 0, 1); backModel = builder.end(); background = new ModelInstance(backModel); modelBatch = new ModelBatch(); camera = new PerspectiveCamera(45, 4, 4); camera.position.set(0, 0, 3); camera.direction.set(0, 0, -1); camera.update(); Gdx.input.setInputProcessor(this); }
@Override public void create () { modelBatch = new ModelBatch(); environment = new Environment(); environment.set(new ColorAttribute(ColorAttribute.AmbientLight, .4f, .4f, .4f, 1f)); environment.add(new DirectionalLight().set(0.8f, 0.8f, 0.8f, -1f, -0.8f, -0.2f)); environment.add((shadowLight = new DirectionalShadowLight(1024, 1024, 30f, 30f, 1f, 100f)).set(0.8f, 0.8f, 0.8f, -1f, -.8f, -.2f)); environment.shadowMap = shadowLight; cam = new PerspectiveCamera(67, Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); cam.position.set(0f, 7f, 10f); cam.lookAt(0, 0, 0); cam.near = 1f; cam.far = 50f; cam.update(); ModelBuilder modelBuilder = new ModelBuilder(); modelBuilder.begin(); MeshPartBuilder mpb = modelBuilder.part("parts", GL20.GL_TRIANGLES, Usage.Position | Usage.Normal | Usage.Color, new Material(ColorAttribute.createDiffuse(Color.WHITE))); mpb.setColor(1f, 1f, 1f, 1f); mpb.box(0, -1.5f, 0, 10, 1, 10); mpb.setColor(1f, 0f, 1f, 1f); mpb.sphere(2f, 2f, 2f, 10, 10); model = modelBuilder.end(); instance = new ModelInstance(model); shadowBatch = new ModelBatch(new DepthShaderProvider()); Gdx.input.setInputProcessor(camController = new CameraInputController(cam)); }
private void createGround() { if (++timesCreated > 1) { throw new GdxRuntimeException("can't create heightmap more than one time"); } vertexInfos = new MeshPartBuilder.VertexInfo[heightMap.heights.length][heightMap.heights[0].length]; int trisHeight = (heightMap.getWidth() - 1); int trisWidth = (heightMap.getWidth() - 1) * 2; System.out.printf("tris zHeight,xWidth: %d, %d\n", trisHeight, trisWidth); tris = new Triangle[trisHeight][trisWidth]; setVertexPositions(); // iterate through height map points, setting world coordinates buildTriangles(); // abstraction of the triangles that create the mesh // useful for calculating vertex normals, since each triangle stores a face normal // but somewhat wasteful of memory // TODO: optimize calculateVertexNormals(); // calculate vertex normals for per-vertex lighting final int chunkSize = 32; int z = 0; int zRemain = (int) Math.ceil(heightMap.getDepth() / chunkSize); if (zRemain == 0) zRemain = 1; int baseXRemain = (int) Math.ceil(heightMap.getWidth() / chunkSize); if (baseXRemain == 0) baseXRemain = 1; System.out.println("z chunks: " + zRemain + ", x chunks: " + baseXRemain); while (zRemain > 0) { int xRemain = baseXRemain; int x = 0; while (xRemain > 0) { buildGroundModels(x, z, chunkSize); xRemain--; x += chunkSize*2; } zRemain--; z += chunkSize; } }
private void calculateVertexNormals() { int count = 0; for (int z = 0; z < vertexInfos.length; z++) { for (int x = 0; x < vertexInfos[z].length; x++) { MeshPartBuilder.VertexInfo vert = vertexInfos[z][x]; // calculate normals vert.setNor(calculateNormalForVertex(z, x)); } } System.out.print("vertex count: " + count + ", "); }
/** create some boxes to fill the level with some test geometry */ public static void createBoxes(int count) { ModelBuilder main = new ModelBuilder(); ModelBuilder mb = new ModelBuilder(); Material material = new Material(); if (Main.isClient()) { material.set(TextureAttribute.createDiffuse(Assets.manager.get("textures/marble.jpg", Texture.class))); } main.begin(); //float x = GameWorld.WORLD_WIDTH; //float y = GameWorld.WORLD_DEPTH; for (int i = 0; i < count; i++) { //float w = MathUtils.random(minW, maxW); float w = 8f; float d = 8f; float h = (i+1)*5f; tmp.set(10f + (w+2) * i, 0f, 10f + (d+2) * i); if (Main.isClient()) { mb.begin(); MeshPartBuilder mpb = mb.part("part-" + i, GL20.GL_TRIANGLES, Usage.Position | Usage.Normal | Usage.TextureCoordinates, material); mpb.box(w, h, d); Model boxModel = mb.end(); Node node = main.node("box-" + i, boxModel); node.translation.set(tmp); q.idt(); node.rotation.set(q); } //node.translation.set(MathUtils.random(x), 0f, MathUtils.random(y)); //q.set(Vector3.X, -90); mtx.set(q); mtx.setTranslation(tmp); btCollisionObject obj = Physics.inst.createBoxObject(tmp.set(w/2, h/2, d/2)); obj.setWorldTransform(mtx); Physics.applyStaticGeometryCollisionFlags(obj); Physics.inst.addStaticGeometryToWorld(obj); } Model finalModel = main.end(); instance = new ModelInstance(finalModel); }
public static String fmt(MeshPartBuilder.VertexInfo vi, String name) { if (name == null) name = ""; StringBuilder sb = new StringBuilder(); sb.append("VertexInfo: ").append(name).append("\n"); sb.append("\t").append(fmt(vi.position, "position")).append("\n"); sb.append("\t").append(fmt(vi.color)).append("\n"); sb.append("\t").append(fmt(vi.normal, "normal")); return sb.toString(); }
private static void addBoxShape(MeshPartBuilder partBuilder, float ax, float ay, float az, float bx, float by, float bz) { // TODO: for some reason, ModelBuilder's createBox() creates a box model in a way that BaseModelTileMesh // collects the vertices from it incorrectly. for now, we just manually create a box's vertices/indices ourself partBuilder.vertex(ax, by, bz); partBuilder.vertex(bx, by, bz); partBuilder.vertex(ax, by, az); partBuilder.vertex(bx, by, az); partBuilder.vertex(bx, ay, bz); partBuilder.vertex(ax, ay, bz); partBuilder.vertex(bx, ay, az); partBuilder.vertex(ax, ay, az); // top partBuilder.index((short)0, (short)1, (short)2); partBuilder.index((short)1, (short)3, (short)2); // bottom partBuilder.index((short)4, (short)5, (short)6); partBuilder.index((short)5, (short)7, (short)6); // front partBuilder.index((short)6, (short)7, (short)3); partBuilder.index((short)7, (short)2, (short)3); // back partBuilder.index((short)5, (short)4, (short)0); partBuilder.index((short)4, (short)1, (short)0); // left partBuilder.index((short)7, (short)5, (short)2); partBuilder.index((short)5, (short)0, (short)2); // right partBuilder.index((short)4, (short)6, (short)1); partBuilder.index((short)6, (short)3, (short)1); }
private static void addRampShape(MeshPartBuilder partBuilder, float ax, float ay, float az, float bx, float by, float bz) { partBuilder.vertex(ax, by, az); partBuilder.vertex(bx, by, az); partBuilder.vertex(bx, ay, bz); partBuilder.vertex(ax, ay, bz); partBuilder.vertex(bx, ay, az); partBuilder.vertex(ax, ay, az); // top (ramp) partBuilder.index((short)3, (short)2, (short)0); partBuilder.index((short)2, (short)1, (short)0); // bottom partBuilder.index((short)2, (short)3, (short)4); partBuilder.index((short)3, (short)5, (short)4); // front partBuilder.index((short)4, (short)5, (short)1); partBuilder.index((short)5, (short)0, (short)1); // left partBuilder.index((short)5, (short)3, (short)0); // right partBuilder.index((short)4, (short)1, (short)2); }
public void getVertex(int index, MeshPartBuilder.VertexInfo out) { if (hasPosition) getPos(index, out.position); if (hasTexCoord) getUV(index, out.uv); if (hasNormal) getNor(index, out.normal); if (hasColor) getCol(index, out.color); out.hasPosition = hasPosition; out.hasUV = hasTexCoord; out.hasNormal = hasNormal; out.hasColor = hasColor; }
private ModelInstance createSkybox() { if(skyboxModel != null) { skyboxModel.dispose(); } if(skyboxTexture == null) { skyboxTexture = new Texture(Gdx.files.internal("textures/world/skybox.png")); } MeshBuilder builder = new MeshBuilder(); builder.begin(VertexAttributes.Usage.Position | VertexAttributes.Usage.TextureCoordinates, GL20.GL_TRIANGLES); int x1 = -256; int y1 = -256; int z1 = -256; int x2 = 256; int y2 = 256; int z2 = 256; float sideU1 = 0; float sideU2 = 1/3f; float sideV1 = 0; float sideV2 = 1; float topU1 = sideU2; float topU2 = topU1+sideU2; float bottomU1 = topU2+sideU2; float bottomU2 = bottomU1+sideU2; float topV1 = 0; float topV2 = 1; float bottomV1 = 0; float bottomV2 = 1; MeshPartBuilder.VertexInfo bottomLeftBack = new MeshPartBuilder.VertexInfo().setPos(x1, y1, z1).setUV(sideU1, sideV2); MeshPartBuilder.VertexInfo bottomRightBack = new MeshPartBuilder.VertexInfo().setPos(x2, y1, z1).setUV(sideU2, sideV2); MeshPartBuilder.VertexInfo bottomRightFront = new MeshPartBuilder.VertexInfo().setPos(x2, y1, z2).setUV(sideU1, sideV2); MeshPartBuilder.VertexInfo bottomLeftFront = new MeshPartBuilder.VertexInfo().setPos(x1, y1, z2).setUV(sideU2, sideV2); MeshPartBuilder.VertexInfo topLeftBack = new MeshPartBuilder.VertexInfo().setPos(x1, y2, z1).setUV(sideU1, sideV1); MeshPartBuilder.VertexInfo topRightBack = new MeshPartBuilder.VertexInfo().setPos(x2, y2, z1).setUV(sideU2, sideV1); MeshPartBuilder.VertexInfo topRightFront = new MeshPartBuilder.VertexInfo().setPos(x2, y2, z2).setUV(sideU1, sideV1); MeshPartBuilder.VertexInfo topLeftFront = new MeshPartBuilder.VertexInfo().setPos(x1, y2, z2).setUV(sideU2, sideV1); // Negative Z builder.rect(bottomLeftBack, bottomRightBack, topRightBack, topLeftBack); // Positive Z builder.rect(topLeftFront, topRightFront, bottomRightFront, bottomLeftFront); // Negative X builder.rect(bottomLeftBack, topLeftBack, topLeftFront, bottomLeftFront); // Positive X builder.rect(bottomRightFront, topRightFront, topRightBack, bottomRightBack); // Positive Y builder.rect(topLeftBack.setUV(topU1, topV1), topRightBack.setUV(topU2, topV1), topRightFront.setUV(topU2, topV2), topLeftFront.setUV(topU1, topV2)); // Negative Y builder.rect(bottomLeftFront.setUV(bottomU1, bottomV2), bottomRightFront.setUV(bottomU2, bottomV2), bottomRightBack.setUV(bottomU2, bottomV1), bottomLeftBack.setUV(bottomU1, bottomV1)); Mesh skybox = builder.end(); ModelBuilder modelBuilder = new ModelBuilder(); modelBuilder.begin(); modelBuilder.part("skybox", skybox, GL20.GL_TRIANGLES, new Material( TextureAttribute.createDiffuse(skyboxTexture))); return new ModelInstance(skyboxModel = modelBuilder.end()); }
/** * Calculates normal of a vertex at x,y based on the verticesOnZ of the * surrounding vertices */ private MeshPartBuilder.VertexInfo calculateNormalAt(MeshPartBuilder.VertexInfo out, int x, int y) { out.normal.set(getNormalAt(x, y)); return out; }
public static Model torus(Material mat, float width, float height, int divisionsU, int divisionsV) { ModelBuilder modelBuilder = new ModelBuilder(); modelBuilder.begin(); MeshPartBuilder builder = modelBuilder.part("torus", GL20.GL_TRIANGLES, VertexAttributes.Usage.Position, mat); // builder.setColor(Color.LIGHT_GRAY); MeshPartBuilder.VertexInfo curr1 = v0.set(null, null, null, null); curr1.hasUV = curr1.hasNormal = false; curr1.hasPosition = true; MeshPartBuilder.VertexInfo curr2 = v1.set(null, null, null, null); curr2.hasUV = curr2.hasNormal = false; curr2.hasPosition = true; short i1, i2, i3 = 0, i4 = 0; int i, j, k; double s, t, twopi; twopi = 2 * Math.PI; for (i = 0; i < divisionsV; i++) { for (j = 0; j <= divisionsU; j++) { for (k = 1; k >= 0; k--) { s = (i + k) % divisionsV + 0.5; t = j % divisionsU; curr1.position.set( (float) ((width + height * Math.cos(s * twopi / divisionsV)) * Math.cos(t * twopi / divisionsU)), (float) ((width + height * Math.cos(s * twopi / divisionsV)) * Math.sin(t * twopi / divisionsU)), (float) (height * Math.sin(s * twopi / divisionsV))); k--; s = (i + k) % divisionsV + 0.5; curr2.position.set( (float) ((width + height * Math.cos(s * twopi / divisionsV)) * Math.cos(t * twopi / divisionsU)), (float) ((width + height * Math.cos(s * twopi / divisionsV)) * Math.sin(t * twopi / divisionsU)), (float) (height * Math.sin(s * twopi / divisionsV))); // curr2.uv.set((float) s, 0); i1 = builder.vertex(curr1); i2 = builder.vertex(curr2); builder.rect(i4, i2, i1, i3); i4 = i2; i3 = i1; } } } return modelBuilder.end(); }
@Override public void create () { super.create(); environment = new Environment(); environment.set(new ColorAttribute(ColorAttribute.AmbientLight, 0.4f, 0.4f, 0.4f, 1.f)); environment.add(new DirectionalLight().set(0.8f, 0.8f, 0.8f, -0.5f, -1.0f, -0.8f)); modelsWindow.setVisible(false); Texture texture = new Texture(Gdx.files.internal("data/badlogic.jpg")); Material material = new Material(TextureAttribute.createDiffuse(texture)); ModelBuilder mb = new ModelBuilder(); mb.begin(); mb.manage(texture); mb.node().id = "box"; MeshPartBuilder mpb = mb.part("box", GL20.GL_TRIANGLES, Usage.Position | Usage.Normal | Usage.TextureCoordinates | Usage.ColorPacked, material); mpb.setColor(Color.RED); mpb.box(1f, 1f, 1f); mb.node().id = "sphere"; mpb = mb.part("sphere", GL20.GL_TRIANGLES, Usage.Position | Usage.Normal | Usage.TextureCoordinates | Usage.ColorPacked, material); mpb.sphere(2f, 2f, 2f, 10, 5); mb.node().id = "cone"; mpb = mb.part("cone", GL20.GL_TRIANGLES, Usage.Position | Usage.Normal | Usage.TextureCoordinates | Usage.ColorPacked, material); mpb.setVertexTransform(new Matrix4().rotate(Vector3.X, -45f)); mpb.cone(2f, 3f, 1f, 8); mb.node().id = "cylinder"; mpb = mb.part("cylinder", GL20.GL_TRIANGLES, Usage.Position | Usage.Normal | Usage.TextureCoordinates | Usage.ColorPacked, material); mpb.cylinder(2f, 4f, 3f, 15); model = mb.end(); instances.add(new ModelInstance(model, new Matrix4().trn(-5f, 0f, -5f), "box", true)); instances.add(new ModelInstance(model, new Matrix4().trn(5f, 0f, -5f), "sphere", true)); instances.add(new ModelInstance(model, new Matrix4().trn(-5f, 0f, 5f), "cone", true)); instances.add(new ModelInstance(model, new Matrix4().trn(5f, 0f, 5f), "cylinder", true)); }
@Override public void create () { super.create(); lights = new Environment(); lights.set(new ColorAttribute(ColorAttribute.AmbientLight, 0.4f, 0.4f, 0.4f, 1.f)); lights.add((shadowLight = new DirectionalShadowLight(1024, 1024, 30f, 30f, 1f, 100f)) .set(0.8f, 0.8f, 0.8f, -.4f, -.4f, -.4f)); lights.shadowMap = shadowLight; inputController.rotateLeftKey = inputController.rotateRightKey = inputController.forwardKey = inputController.backwardKey = 0; cam.position.set(25, 25, 25); cam.lookAt(0, 0, 0); cam.update(); modelsWindow.setVisible(false); assets.load("data/g3d/skydome.g3db", Model.class); assets.load("data/g3d/concrete.png", Texture.class); assets.load("data/tree.png", Texture.class); loading = true; trForward.translation.set(0, 0, 8f); trBackward.translation.set(0, 0, -8f); trLeft.rotation.setFromAxis(Vector3.Y, 90); trRight.rotation.setFromAxis(Vector3.Y, -90); ModelBuilder builder = new ModelBuilder(); builder.begin(); builder.node().id = "floor"; MeshPartBuilder part = builder.part("floor", GL20.GL_TRIANGLES, Usage.Position | Usage.TextureCoordinates | Usage.Normal, new Material("concrete")); ((MeshBuilder)part).ensureRectangles(1600); for (float x = -200f; x < 200f; x += 10f) { for (float z = -200f; z < 200f; z += 10f) { part.rect(x, 0, z + 10f, x + 10f, 0, z + 10f, x + 10f, 0, z, x, 0, z, 0, 1, 0); } } builder.node().id = "tree"; part = builder.part("tree", GL20.GL_TRIANGLES, Usage.Position | Usage.TextureCoordinates | Usage.Normal, new Material("tree")); part.rect( 0f, 0f, -10f, 10f, 0f, -10f, 10f, 10f, -10f, 0f, 10f, -10f, 0, 0, 1f); part.setUVRange(1, 0, 0, 1); part.rect(10f, 0f, -10f, 0f, 0f, -10f, 0f, 10f, -10f, 10f, 10f, -10f, 0, 0, -1f); floorModel = builder.end(); shadowBatch = new ModelBatch(new DepthShaderProvider()); }
@Override public Model loadSync(AssetManager manager, String fileName, FileHandle file, VxiParameter parameter) { ModelBuilder mb = new ModelBuilder(); mb.begin(); MeshPartBuilder mpb = mb.part(file.nameWithoutExtension(), GL20.GL_TRIANGLES, new VertexAttributes(VertexAttribute.Position(), VertexAttribute.Normal(), VertexAttribute.ColorPacked()), material); Array<Vertex> vertices = new Array<Vertex>(); offsetZ -= depth * (depth < height ? 0.3f : 1 / 3f);// TODO is this doing the trick? for (ColorFace f : faces.values()) { Vertex tl = new Vertex(f.tl.cpy().add(f.pos).add(offsetX, offsetY, offsetZ).scl(resolution), f.dir.dir, f.c); Vertex bl = new Vertex(f.bl.cpy().add(f.pos).add(offsetX, offsetY, offsetZ).scl(resolution), f.dir.dir, f.c); Vertex br = new Vertex(f.br.cpy().add(f.pos).add(offsetX, offsetY, offsetZ).scl(resolution), f.dir.dir, f.c); Vertex tr = new Vertex(f.tr.cpy().add(f.pos).add(offsetX, offsetY, offsetZ).scl(resolution), f.dir.dir, f.c); rotate(tl.pos); rotate(bl.pos); rotate(br.pos); rotate(tr.pos); if (!vertices.contains(tr, true)) { mpb.vertex(tr.pos, tr.nor, f.c, null); vertices.add(tr); } if (!vertices.contains(br, true)) { mpb.vertex(br.pos, br.nor, f.c, null); vertices.add(br); } if (!vertices.contains(tl, true)) { mpb.vertex(tl.pos, tl.nor, f.c, null); vertices.add(tl); } if (!vertices.contains(bl, true)) { mpb.vertex(bl.pos, bl.nor, f.c, null); vertices.add(bl); } mpb.index((short) vertices.indexOf(br, true), (short) vertices.indexOf(bl, true), (short) vertices.indexOf(tl, true)); mpb.index((short) vertices.indexOf(tr, true), (short) vertices.indexOf(br, true), (short) vertices.indexOf(tl, true)); } Model model = mb.end(); for (ReferencePoint p : referencePoints) { Node node = new Node(); node.id = p.name; node.parent = model.nodes.get(0); node.translation.add(p.x, p.y, p.z - depth * (depth < height ? 0.165f : 1 / 4f)).scl(resolution); rotate(node.translation); model.nodes.get(0).children.add(node); } return model; }
/** * Creates a plane, used for testing * @param size the size of the plane * @return */ public static TerrainChunk CreatePlaneChunk (float size) { TerrainChunk chunk = new TerrainChunk(); // graphical representation of the ground Log.debug("createLevel - create ground"); if (Main.isClient()) { ModelBuilder mb = new ModelBuilder(); mb.begin(); Vector3 bl = new Vector3(); Vector3 tl = new Vector3(); Vector3 tr = new Vector3(); Vector3 br = new Vector3(); Vector3 norm = new Vector3(0f, 1f, 0f); // the size of each rect that makes up the ground Texture groundTex = Assets.manager.get("textures/ground1.jpg", Texture.class); Material groundMat = new Material(TextureAttribute.createDiffuse(groundTex)); MeshPartBuilder mpb = mb.part("ground", GL20.GL_TRIANGLES, Usage.Position | Usage.Normal | Usage.TextureCoordinates, groundMat); float u1 = 0f; float v1 = 0f; float u2 = size / 5f; float v2 = size / 5f; mpb.setUVRange(u1, v1, u2, v2); bl.set(0, 0, 0); tl.set(0, 0, size); tr.set(size, 0, size); br.set(size, 0, 0); // mpb.rect(bl, tl, tr, br, norm); int divisions = ((int)size) / 4; mpb.patch(bl, tl, tr, br, norm, divisions, divisions); Model groundModel = mb.end(); chunk.modelInstance = new ModelInstance(groundModel); } // physical representation of the ground btCollisionObject groundObj = new btCollisionObject(); btCollisionShape groundShape = new btStaticPlaneShape(Vector3.Y, 0f); groundObj.setCollisionShape(groundShape); Physics.applyStaticGeometryCollisionFlags(groundObj); Physics.inst.addStaticGeometryToWorld(groundObj); chunk.body = groundObj; return chunk; }