19244abf367bce0e823d8cacc8f2ad15d3c83d154badlogicgames/******************************************************************************* 29244abf367bce0e823d8cacc8f2ad15d3c83d154badlogicgames * Copyright 2011 See AUTHORS file. 3192aca09e83d3f70a712948a7946ace5ee03045dbadlogicgames * 49244abf367bce0e823d8cacc8f2ad15d3c83d154badlogicgames * Licensed under the Apache License, Version 2.0 (the "License"); 59244abf367bce0e823d8cacc8f2ad15d3c83d154badlogicgames * you may not use this file except in compliance with the License. 69244abf367bce0e823d8cacc8f2ad15d3c83d154badlogicgames * You may obtain a copy of the License at 7192aca09e83d3f70a712948a7946ace5ee03045dbadlogicgames * 89244abf367bce0e823d8cacc8f2ad15d3c83d154badlogicgames * http://www.apache.org/licenses/LICENSE-2.0 9192aca09e83d3f70a712948a7946ace5ee03045dbadlogicgames * 109244abf367bce0e823d8cacc8f2ad15d3c83d154badlogicgames * Unless required by applicable law or agreed to in writing, software 119244abf367bce0e823d8cacc8f2ad15d3c83d154badlogicgames * distributed under the License is distributed on an "AS IS" BASIS, 129244abf367bce0e823d8cacc8f2ad15d3c83d154badlogicgames * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139244abf367bce0e823d8cacc8f2ad15d3c83d154badlogicgames * See the License for the specific language governing permissions and 149244abf367bce0e823d8cacc8f2ad15d3c83d154badlogicgames * limitations under the License. 159244abf367bce0e823d8cacc8f2ad15d3c83d154badlogicgames ******************************************************************************/ 162f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet 17114c5c91c13f74b04c08c0816d649da267bdcbbdbadlogicgamespackage com.badlogic.gdx.graphics; 18114c5c91c13f74b04c08c0816d649da267bdcbbdbadlogicgames 19114c5c91c13f74b04c08c0816d649da267bdcbbdbadlogicgamesimport java.nio.FloatBuffer; 20114c5c91c13f74b04c08c0816d649da267bdcbbdbadlogicgamesimport java.nio.ShortBuffer; 2192ed4d69842a61ff92fabe3167305fbf82bb5e94badlogicgamesimport java.util.HashMap; 2292ed4d69842a61ff92fabe3167305fbf82bb5e94badlogicgamesimport java.util.Map; 23114c5c91c13f74b04c08c0816d649da267bdcbbdbadlogicgames 2492ed4d69842a61ff92fabe3167305fbf82bb5e94badlogicgamesimport com.badlogic.gdx.Application; 25fc2eb8df6aa4fed814c0f809851ad291e9ab7043badlogicgamesimport com.badlogic.gdx.Gdx; 26114c5c91c13f74b04c08c0816d649da267bdcbbdbadlogicgamesimport com.badlogic.gdx.graphics.VertexAttributes.Usage; 274ed6a0159542602b27e875e1a3a1f419d175148dXoppaimport com.badlogic.gdx.graphics.glutils.IndexArray; 284ed6a0159542602b27e875e1a3a1f419d175148dXoppaimport com.badlogic.gdx.graphics.glutils.IndexBufferObject; 294ed6a0159542602b27e875e1a3a1f419d175148dXoppaimport com.badlogic.gdx.graphics.glutils.IndexBufferObjectSubData; 304ed6a0159542602b27e875e1a3a1f419d175148dXoppaimport com.badlogic.gdx.graphics.glutils.IndexData; 314ed6a0159542602b27e875e1a3a1f419d175148dXoppaimport com.badlogic.gdx.graphics.glutils.ShaderProgram; 324ed6a0159542602b27e875e1a3a1f419d175148dXoppaimport com.badlogic.gdx.graphics.glutils.VertexArray; 334ed6a0159542602b27e875e1a3a1f419d175148dXoppaimport com.badlogic.gdx.graphics.glutils.VertexBufferObject; 344ed6a0159542602b27e875e1a3a1f419d175148dXoppaimport com.badlogic.gdx.graphics.glutils.VertexBufferObjectSubData; 354ed6a0159542602b27e875e1a3a1f419d175148dXoppaimport com.badlogic.gdx.graphics.glutils.VertexBufferObjectWithVAO; 364ed6a0159542602b27e875e1a3a1f419d175148dXoppaimport com.badlogic.gdx.graphics.glutils.VertexData; 37ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppaimport com.badlogic.gdx.math.Matrix3; 3806e0eeb03633afc78536b775f5ef878288b1de02Xoppaimport com.badlogic.gdx.math.Matrix4; 3906e0eeb03633afc78536b775f5ef878288b1de02Xoppaimport com.badlogic.gdx.math.Vector2; 4006e0eeb03633afc78536b775f5ef878288b1de02Xoppaimport com.badlogic.gdx.math.Vector3; 415dc2f5d616354b058897632abb2d080dcde123c8badlogicgamesimport com.badlogic.gdx.math.collision.BoundingBox; 420a5c1025d1f147746db4f92bfd3c1ba4abea58b9Jon Rennerimport com.badlogic.gdx.utils.Array; 43dd6866e5fe155220c2b8b231f7789dc5ff584b2cbadlogicgamesimport com.badlogic.gdx.utils.Disposable; 445dc2f5d616354b058897632abb2d080dcde123c8badlogicgamesimport com.badlogic.gdx.utils.GdxRuntimeException; 45114c5c91c13f74b04c08c0816d649da267bdcbbdbadlogicgames 462f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet/** <p> 47c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet * A Mesh holds vertices composed of attributes specified by a {@link VertexAttributes} instance. The vertices are held either in 48575cf286b878302f75e8513c42877ae254da4886Xoppa * VRAM in form of vertex buffer objects or in RAM in form of vertex arrays. The former variant is more performant and is 49575cf286b878302f75e8513c42877ae254da4886Xoppa * preferred over vertex arrays if hardware supports it. 50847c371a0012580e84fa65d7348b930a7aa4e805badlogicgames * </p> 51847c371a0012580e84fa65d7348b930a7aa4e805badlogicgames * 5230597377f5f74e1e402481d423a8ecc933e65ed2nathan.sweet * <p> 53c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet * Meshes are automatically managed. If the OpenGL context is lost all vertex buffer objects get invalidated and must be reloaded 54c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet * when the context is recreated. This only happens on Android when a user switches to another application or receives an incoming 55c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet * call. A managed Mesh will be reloaded automagically so you don't have to do this manually. 56847c371a0012580e84fa65d7348b930a7aa4e805badlogicgames * </p> 57847c371a0012580e84fa65d7348b930a7aa4e805badlogicgames * 58847c371a0012580e84fa65d7348b930a7aa4e805badlogicgames * <p> 59c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet * A Mesh consists of vertices and optionally indices which specify which vertices define a triangle. Each vertex is composed of 60c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet * attributes such as position, normal, color or texture coordinate. Note that not all of this attributes must be given, except 61c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet * for position which is non-optional. Each attribute has an alias which is used when rendering a Mesh in OpenGL ES 2.0. The alias 62c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet * is used to bind a specific vertex attribute to a shader attribute. The shader source and the alias of the attribute must match 6308711a2152eda79f20c2db6064b4f1b444b6ea0cbadlogic * exactly for this to work. 6430597377f5f74e1e402481d423a8ecc933e65ed2nathan.sweet * </p> 65114c5c91c13f74b04c08c0816d649da267bdcbbdbadlogicgames * 66575cf286b878302f75e8513c42877ae254da4886Xoppa * @author mzechner, Dave Clayton <contact@redskyforge.com>, Xoppa */ 67a2acdc681d9192e68b424f5ca8c28dadae17a100badlogicgamespublic class Mesh implements Disposable { 68938a5b1860782c073367237a0305db43da3289e5badlogicgames public enum VertexDataType { 69e4f285b4a85ce8a1a1da9fb38106da6924d6879bNateAustin VertexArray, VertexBufferObject, VertexBufferObjectSubData, VertexBufferObjectWithVAO 70938a5b1860782c073367237a0305db43da3289e5badlogicgames } 71938a5b1860782c073367237a0305db43da3289e5badlogicgames 72114c5c91c13f74b04c08c0816d649da267bdcbbdbadlogicgames /** list of all meshes **/ 730a5c1025d1f147746db4f92bfd3c1ba4abea58b9Jon Renner static final Map<Application, Array<Mesh>> meshes = new HashMap<Application, Array<Mesh>>(); 7430597377f5f74e1e402481d423a8ecc933e65ed2nathan.sweet 75f1fa40492f7ea283f5ded3d671ce685277405dc3badlogicgames final VertexData vertices; 76938a5b1860782c073367237a0305db43da3289e5badlogicgames final IndexData indices; 772f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet boolean autoBind = true; 78f1fa40492f7ea283f5ded3d671ce685277405dc3badlogicgames final boolean isVertexArray; 790fb217903b1b0c5a4a3a63c604e912a3a2e6d4e2badlogicgames 80575cf286b878302f75e8513c42877ae254da4886Xoppa protected Mesh (VertexData vertices, IndexData indices, boolean isVertexArray) { 81575cf286b878302f75e8513c42877ae254da4886Xoppa this.vertices = vertices; 82575cf286b878302f75e8513c42877ae254da4886Xoppa this.indices = indices; 83575cf286b878302f75e8513c42877ae254da4886Xoppa this.isVertexArray = isVertexArray; 84575cf286b878302f75e8513c42877ae254da4886Xoppa 85575cf286b878302f75e8513c42877ae254da4886Xoppa addManagedMesh(Gdx.app, this); 86575cf286b878302f75e8513c42877ae254da4886Xoppa } 87575cf286b878302f75e8513c42877ae254da4886Xoppa 882f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet /** Creates a new Mesh with the given attributes. 89114c5c91c13f74b04c08c0816d649da267bdcbbdbadlogicgames * 90c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet * @param isStatic whether this mesh is static or not. Allows for internal optimizations. 91c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet * @param maxVertices the maximum number of vertices this mesh can hold 92c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet * @param maxIndices the maximum number of indices this mesh can hold 93c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet * @param attributes the {@link VertexAttribute}s. Each vertex attribute defines one property of a vertex such as position, 942f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet * normal or texture coordinate */ 95c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet public Mesh (boolean isStatic, int maxVertices, int maxIndices, VertexAttribute... attributes) { 96e4f285b4a85ce8a1a1da9fb38106da6924d6879bNateAustin vertices = makeVertexBuffer(isStatic, maxVertices, new VertexAttributes(attributes)); 9708711a2152eda79f20c2db6064b4f1b444b6ea0cbadlogic indices = new IndexBufferObject(isStatic, maxIndices); 9808711a2152eda79f20c2db6064b4f1b444b6ea0cbadlogic isVertexArray = false; 990fb217903b1b0c5a4a3a63c604e912a3a2e6d4e2badlogicgames 10092ed4d69842a61ff92fabe3167305fbf82bb5e94badlogicgames addManagedMesh(Gdx.app, this); 101114c5c91c13f74b04c08c0816d649da267bdcbbdbadlogicgames } 1022f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet 1032f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet /** Creates a new Mesh with the given attributes. 1049bcb0acaadd34d3fc8ccdc01f9b574077cc9f597davedx@gmail.com * 1052f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet * @param isStatic whether this mesh is static or not. Allows for internal optimizations. 1062f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet * @param maxVertices the maximum number of vertices this mesh can hold 1072f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet * @param maxIndices the maximum number of indices this mesh can hold 1082f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet * @param attributes the {@link VertexAttributes}. Each vertex attribute defines one property of a vertex such as position, 1092f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet * normal or texture coordinate */ 1102f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet public Mesh (boolean isStatic, int maxVertices, int maxIndices, VertexAttributes attributes) { 111e4f285b4a85ce8a1a1da9fb38106da6924d6879bNateAustin vertices = makeVertexBuffer(isStatic, maxVertices, attributes); 11208711a2152eda79f20c2db6064b4f1b444b6ea0cbadlogic indices = new IndexBufferObject(isStatic, maxIndices); 11308711a2152eda79f20c2db6064b4f1b444b6ea0cbadlogic isVertexArray = false; 1149bcb0acaadd34d3fc8ccdc01f9b574077cc9f597davedx@gmail.com 11592ed4d69842a61ff92fabe3167305fbf82bb5e94badlogicgames addManagedMesh(Gdx.app, this); 1169bcb0acaadd34d3fc8ccdc01f9b574077cc9f597davedx@gmail.com } 11730597377f5f74e1e402481d423a8ecc933e65ed2nathan.sweet 1189433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet /** by jw: Creates a new Mesh with the given attributes. Adds extra optimizations for dynamic (frequently modified) meshes. 1197d9423bce885a999053d1da46f5e312284f844d6Jaroslaw Wisniewski * 1207d9423bce885a999053d1da46f5e312284f844d6Jaroslaw Wisniewski * @param staticVertices whether vertices of this mesh are static or not. Allows for internal optimizations. 1217d9423bce885a999053d1da46f5e312284f844d6Jaroslaw Wisniewski * @param staticIndices whether indices of this mesh are static or not. Allows for internal optimizations. 1227d9423bce885a999053d1da46f5e312284f844d6Jaroslaw Wisniewski * @param maxVertices the maximum number of vertices this mesh can hold 1237d9423bce885a999053d1da46f5e312284f844d6Jaroslaw Wisniewski * @param maxIndices the maximum number of indices this mesh can hold 1247d9423bce885a999053d1da46f5e312284f844d6Jaroslaw Wisniewski * @param attributes the {@link VertexAttributes}. Each vertex attribute defines one property of a vertex such as position, 1259433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet * normal or texture coordinate 1269433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet * 1279433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet * @author Jaroslaw Wisniewski <j.wisniewski@appsisle.com> **/ 1287d9423bce885a999053d1da46f5e312284f844d6Jaroslaw Wisniewski public Mesh (boolean staticVertices, boolean staticIndices, int maxVertices, int maxIndices, VertexAttributes attributes) { 129e4f285b4a85ce8a1a1da9fb38106da6924d6879bNateAustin vertices = makeVertexBuffer(staticVertices, maxVertices, attributes); 13008711a2152eda79f20c2db6064b4f1b444b6ea0cbadlogic indices = new IndexBufferObject(staticIndices, maxIndices); 13108711a2152eda79f20c2db6064b4f1b444b6ea0cbadlogic isVertexArray = false; 1327d9423bce885a999053d1da46f5e312284f844d6Jaroslaw Wisniewski 1337d9423bce885a999053d1da46f5e312284f844d6Jaroslaw Wisniewski addManagedMesh(Gdx.app, this); 1347d9423bce885a999053d1da46f5e312284f844d6Jaroslaw Wisniewski } 1359433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet 136d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa private VertexData makeVertexBuffer (boolean isStatic, int maxVertices, VertexAttributes vertexAttributes) { 137d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa if (Gdx.gl30 != null) { 138e4f285b4a85ce8a1a1da9fb38106da6924d6879bNateAustin return new VertexBufferObjectWithVAO(isStatic, maxVertices, vertexAttributes); 139e4f285b4a85ce8a1a1da9fb38106da6924d6879bNateAustin } else { 140e4f285b4a85ce8a1a1da9fb38106da6924d6879bNateAustin return new VertexBufferObject(isStatic, maxVertices, vertexAttributes); 141e4f285b4a85ce8a1a1da9fb38106da6924d6879bNateAustin } 142e4f285b4a85ce8a1a1da9fb38106da6924d6879bNateAustin } 143e4f285b4a85ce8a1a1da9fb38106da6924d6879bNateAustin 1442f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet /** Creates a new Mesh with the given attributes. This is an expert method with no error checking. Use at your own risk. 145938a5b1860782c073367237a0305db43da3289e5badlogicgames * 146c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet * @param type the {@link VertexDataType} to be used, VBO or VA. 147c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet * @param isStatic whether this mesh is static or not. Allows for internal optimizations. 148c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet * @param maxVertices the maximum number of vertices this mesh can hold 149c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet * @param maxIndices the maximum number of indices this mesh can hold 150c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet * @param attributes the {@link VertexAttribute}s. Each vertex attribute defines one property of a vertex such as position, 1512f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet * normal or texture coordinate */ 152c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet public Mesh (VertexDataType type, boolean isStatic, int maxVertices, int maxIndices, VertexAttribute... attributes) { 153d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa switch (type) { 154d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa case VertexBufferObject: 155d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa vertices = new VertexBufferObject(isStatic, maxVertices, attributes); 156d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa indices = new IndexBufferObject(isStatic, maxIndices); 157d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa isVertexArray = false; 158d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa break; 159d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa case VertexBufferObjectSubData: 160d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa vertices = new VertexBufferObjectSubData(isStatic, maxVertices, attributes); 161d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa indices = new IndexBufferObjectSubData(isStatic, maxIndices); 162d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa isVertexArray = false; 163d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa break; 164d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa case VertexBufferObjectWithVAO: 165d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa vertices = new VertexBufferObjectWithVAO(isStatic, maxVertices, attributes); 166d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa indices = new IndexBufferObjectSubData(isStatic, maxIndices); 167d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa isVertexArray = false; 168d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa break; 169d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa case VertexArray: 170d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa default: 171d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa vertices = new VertexArray(maxVertices, attributes); 172d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa indices = new IndexArray(maxIndices); 173d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa isVertexArray = true; 174d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa break; 175938a5b1860782c073367237a0305db43da3289e5badlogicgames } 176e4f285b4a85ce8a1a1da9fb38106da6924d6879bNateAustin 1772f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet addManagedMesh(Gdx.app, this); 178938a5b1860782c073367237a0305db43da3289e5badlogicgames } 1799433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet 1800b066287d2300050e41fa341bc24c722a775e7f2badlogic /** Sets the vertices of this Mesh. The attributes are assumed to be given in float format. 181114c5c91c13f74b04c08c0816d649da267bdcbbdbadlogicgames * 18202ccb3898475086fc1d53a8c71be542af5b2e2a0Peter LaValle * @param vertices the vertices. 1839433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet * @return the mesh for invocation chaining. */ 18402ccb3898475086fc1d53a8c71be542af5b2e2a0Peter LaValle public Mesh setVertices (float[] vertices) { 185f1fa40492f7ea283f5ded3d671ce685277405dc3badlogicgames this.vertices.setVertices(vertices, 0, vertices.length); 1869433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet 18702ccb3898475086fc1d53a8c71be542af5b2e2a0Peter LaValle return this; 188114c5c91c13f74b04c08c0816d649da267bdcbbdbadlogicgames } 18930597377f5f74e1e402481d423a8ecc933e65ed2nathan.sweet 1900b066287d2300050e41fa341bc24c722a775e7f2badlogic /** Sets the vertices of this Mesh. The attributes are assumed to be given in float format. 191114c5c91c13f74b04c08c0816d649da267bdcbbdbadlogicgames * 192c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet * @param vertices the vertices. 193c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet * @param offset the offset into the vertices array 1949433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet * @param count the number of floats to use 1959433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet * @return the mesh for invocation chaining. */ 19602ccb3898475086fc1d53a8c71be542af5b2e2a0Peter LaValle public Mesh setVertices (float[] vertices, int offset, int count) { 197f1fa40492f7ea283f5ded3d671ce685277405dc3badlogicgames this.vertices.setVertices(vertices, offset, count); 1989433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet 19902ccb3898475086fc1d53a8c71be542af5b2e2a0Peter LaValle return this; 200114c5c91c13f74b04c08c0816d649da267bdcbbdbadlogicgames } 2012f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet 2027a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa /** Update (a portion of) the vertices. Does not resize the backing buffer. 2037a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa * @param targetOffset the offset in number of floats of the mesh part. 2049433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet * @param source the vertex data to update the mesh part with */ 2057a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa public Mesh updateVertices (int targetOffset, float[] source) { 2067a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa return updateVertices(targetOffset, source, 0, source.length); 2079433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet } 2089433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet 2097a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa /** Update (a portion of) the vertices. Does not resize the backing buffer. 2107a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa * @param targetOffset the offset in number of floats of the mesh part. 2119433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet * @param source the vertex data to update the mesh part with 2127a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa * @param sourceOffset the offset in number of floats within the source array 2139433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet * @param count the number of floats to update */ 2147a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa public Mesh updateVertices (int targetOffset, float[] source, int sourceOffset, int count) { 2157a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa this.vertices.updateVertices(targetOffset, source, sourceOffset, count); 2167a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa return this; 2177a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa } 2187a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa 2192f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet /** Copies the vertices from the Mesh to the float array. The float array must be large enough to hold all the Mesh's vertices. 2202f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet * @param vertices the array to copy the vertices to */ 2217a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa public float[] getVertices (float[] vertices) { 2227a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa return getVertices(0, -1, vertices); 22306e0eeb03633afc78536b775f5ef878288b1de02Xoppa } 2249433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet 2259433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet /** Copies the the remaining vertices from the Mesh to the float array. The float array must be large enough to hold the 2269433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet * remaining vertices. 22706e0eeb03633afc78536b775f5ef878288b1de02Xoppa * @param srcOffset the offset (in number of floats) of the vertices in the mesh to copy 22806e0eeb03633afc78536b775f5ef878288b1de02Xoppa * @param vertices the array to copy the vertices to */ 2297a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa public float[] getVertices (int srcOffset, float[] vertices) { 2307a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa return getVertices(srcOffset, -1, vertices); 23106e0eeb03633afc78536b775f5ef878288b1de02Xoppa } 23206e0eeb03633afc78536b775f5ef878288b1de02Xoppa 23306e0eeb03633afc78536b775f5ef878288b1de02Xoppa /** Copies the specified vertices from the Mesh to the float array. The float array must be large enough to hold count vertices. 23406e0eeb03633afc78536b775f5ef878288b1de02Xoppa * @param srcOffset the offset (in number of floats) of the vertices in the mesh to copy 23506e0eeb03633afc78536b775f5ef878288b1de02Xoppa * @param count the amount of floats to copy 23606e0eeb03633afc78536b775f5ef878288b1de02Xoppa * @param vertices the array to copy the vertices to */ 2377a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa public float[] getVertices (int srcOffset, int count, float[] vertices) { 2387a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa return getVertices(srcOffset, count, vertices, 0); 23906e0eeb03633afc78536b775f5ef878288b1de02Xoppa } 2409433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet 2419433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet /** Copies the specified vertices from the Mesh to the float array. The float array must be large enough to hold 2429433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet * destOffset+count vertices. 24306e0eeb03633afc78536b775f5ef878288b1de02Xoppa * @param srcOffset the offset (in number of floats) of the vertices in the mesh to copy 24406e0eeb03633afc78536b775f5ef878288b1de02Xoppa * @param count the amount of floats to copy 24506e0eeb03633afc78536b775f5ef878288b1de02Xoppa * @param vertices the array to copy the vertices to 24606e0eeb03633afc78536b775f5ef878288b1de02Xoppa * @param destOffset the offset (in floats) in the vertices array to start copying */ 2477a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa public float[] getVertices (int srcOffset, int count, float[] vertices, int destOffset) { 24806e0eeb03633afc78536b775f5ef878288b1de02Xoppa // TODO: Perhaps this method should be vertexSize aware?? 24906e0eeb03633afc78536b775f5ef878288b1de02Xoppa final int max = getNumVertices() * getVertexSize() / 4; 25006e0eeb03633afc78536b775f5ef878288b1de02Xoppa if (count == -1) { 25106e0eeb03633afc78536b775f5ef878288b1de02Xoppa count = max - srcOffset; 2529433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet if (count > vertices.length - destOffset) count = vertices.length - destOffset; 25306e0eeb03633afc78536b775f5ef878288b1de02Xoppa } 25406e0eeb03633afc78536b775f5ef878288b1de02Xoppa if (srcOffset < 0 || count <= 0 || (srcOffset + count) > max || destOffset < 0 || destOffset >= vertices.length) 25506e0eeb03633afc78536b775f5ef878288b1de02Xoppa throw new IndexOutOfBoundsException(); 25606e0eeb03633afc78536b775f5ef878288b1de02Xoppa if ((vertices.length - destOffset) < count) 2579433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet throw new IllegalArgumentException("not enough room in vertices array, has " + vertices.length + " floats, needs " 2589433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet + count); 2592f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet int pos = getVerticesBuffer().position(); 26006e0eeb03633afc78536b775f5ef878288b1de02Xoppa getVerticesBuffer().position(srcOffset); 26106e0eeb03633afc78536b775f5ef878288b1de02Xoppa getVerticesBuffer().get(vertices, destOffset, count); 2624732e63a3c5a351cef799716735039019c3bd364badlogicgames getVerticesBuffer().position(pos); 2637a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa return vertices; 2644732e63a3c5a351cef799716735039019c3bd364badlogicgames } 26530597377f5f74e1e402481d423a8ecc933e65ed2nathan.sweet 2662f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet /** Sets the indices of this Mesh 267114c5c91c13f74b04c08c0816d649da267bdcbbdbadlogicgames * 26802ccb3898475086fc1d53a8c71be542af5b2e2a0Peter LaValle * @param indices the indices 26902ccb3898475086fc1d53a8c71be542af5b2e2a0Peter LaValle * @return the mesh for invocation chaining. */ 27002ccb3898475086fc1d53a8c71be542af5b2e2a0Peter LaValle public Mesh setIndices (short[] indices) { 271f1fa40492f7ea283f5ded3d671ce685277405dc3badlogicgames this.indices.setIndices(indices, 0, indices.length); 2729433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet 27302ccb3898475086fc1d53a8c71be542af5b2e2a0Peter LaValle return this; 274f1fa40492f7ea283f5ded3d671ce685277405dc3badlogicgames } 2750fb217903b1b0c5a4a3a63c604e912a3a2e6d4e2badlogicgames 2762f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet /** Sets the indices of this Mesh. 277f1fa40492f7ea283f5ded3d671ce685277405dc3badlogicgames * 278c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet * @param indices the indices 279c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet * @param offset the offset into the indices array 28002ccb3898475086fc1d53a8c71be542af5b2e2a0Peter LaValle * @param count the number of indices to copy 28102ccb3898475086fc1d53a8c71be542af5b2e2a0Peter LaValle * @return the mesh for invocation chaining. */ 28202ccb3898475086fc1d53a8c71be542af5b2e2a0Peter LaValle public Mesh setIndices (short[] indices, int offset, int count) { 283f1fa40492f7ea283f5ded3d671ce685277405dc3badlogicgames this.indices.setIndices(indices, offset, count); 2849433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet 28502ccb3898475086fc1d53a8c71be542af5b2e2a0Peter LaValle return this; 286114c5c91c13f74b04c08c0816d649da267bdcbbdbadlogicgames } 2872f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet 2882f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet /** Copies the indices from the Mesh to the short array. The short array must be large enough to hold all the Mesh's indices. 2892f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet * @param indices the array to copy the indices to */ 2902f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet public void getIndices (short[] indices) { 29106e0eeb03633afc78536b775f5ef878288b1de02Xoppa getIndices(indices, 0); 29206e0eeb03633afc78536b775f5ef878288b1de02Xoppa } 29306e0eeb03633afc78536b775f5ef878288b1de02Xoppa 2949433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet /** Copies the indices from the Mesh to the short array. The short array must be large enough to hold destOffset + all the 2959433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet * Mesh's indices. 2969433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet * @param indices the array to copy the indices to 29706e0eeb03633afc78536b775f5ef878288b1de02Xoppa * @param destOffset the offset in the indices array to start copying */ 2989433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet public void getIndices (short[] indices, int destOffset) { 299b1e5f16aadd6d8481c7b749ecccf8a8210c0cc55Xoppa getIndices(0, indices, destOffset); 300b1e5f16aadd6d8481c7b749ecccf8a8210c0cc55Xoppa } 301b1e5f16aadd6d8481c7b749ecccf8a8210c0cc55Xoppa 302b1e5f16aadd6d8481c7b749ecccf8a8210c0cc55Xoppa /** Copies the remaining indices from the Mesh to the short array. The short array must be large enough to hold destOffset + all 303b1e5f16aadd6d8481c7b749ecccf8a8210c0cc55Xoppa * the remaining indices. 304b1e5f16aadd6d8481c7b749ecccf8a8210c0cc55Xoppa * @param srcOffset the zero-based offset of the first index to fetch 305b1e5f16aadd6d8481c7b749ecccf8a8210c0cc55Xoppa * @param indices the array to copy the indices to 306b1e5f16aadd6d8481c7b749ecccf8a8210c0cc55Xoppa * @param destOffset the offset in the indices array to start copying */ 307b1e5f16aadd6d8481c7b749ecccf8a8210c0cc55Xoppa public void getIndices (int srcOffset, short[] indices, int destOffset) { 308b1e5f16aadd6d8481c7b749ecccf8a8210c0cc55Xoppa getIndices(srcOffset, -1, indices, destOffset); 309b1e5f16aadd6d8481c7b749ecccf8a8210c0cc55Xoppa } 310b1e5f16aadd6d8481c7b749ecccf8a8210c0cc55Xoppa 311b1e5f16aadd6d8481c7b749ecccf8a8210c0cc55Xoppa /** Copies the indices from the Mesh to the short array. The short array must be large enough to hold destOffset + count 312b1e5f16aadd6d8481c7b749ecccf8a8210c0cc55Xoppa * indices. 313b1e5f16aadd6d8481c7b749ecccf8a8210c0cc55Xoppa * @param srcOffset the zero-based offset of the first index to fetch 314b1e5f16aadd6d8481c7b749ecccf8a8210c0cc55Xoppa * @param count the total amount of indices to copy 315b1e5f16aadd6d8481c7b749ecccf8a8210c0cc55Xoppa * @param indices the array to copy the indices to 316b1e5f16aadd6d8481c7b749ecccf8a8210c0cc55Xoppa * @param destOffset the offset in the indices array to start copying */ 317b1e5f16aadd6d8481c7b749ecccf8a8210c0cc55Xoppa public void getIndices (int srcOffset, int count, short[] indices, int destOffset) { 318b1e5f16aadd6d8481c7b749ecccf8a8210c0cc55Xoppa int max = getNumIndices(); 319b1e5f16aadd6d8481c7b749ecccf8a8210c0cc55Xoppa if (count < 0) count = max - srcOffset; 320b1e5f16aadd6d8481c7b749ecccf8a8210c0cc55Xoppa if (srcOffset < 0 || srcOffset >= max || srcOffset + count > max) 321b1e5f16aadd6d8481c7b749ecccf8a8210c0cc55Xoppa throw new IllegalArgumentException("Invalid range specified, offset: " + srcOffset + ", count: " + count + ", max: " 322b1e5f16aadd6d8481c7b749ecccf8a8210c0cc55Xoppa + max); 323b1e5f16aadd6d8481c7b749ecccf8a8210c0cc55Xoppa if ((indices.length - destOffset) < count) 324b1e5f16aadd6d8481c7b749ecccf8a8210c0cc55Xoppa throw new IllegalArgumentException("not enough room in indices array, has " + indices.length + " shorts, needs " + count); 3252f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet int pos = getIndicesBuffer().position(); 326b1e5f16aadd6d8481c7b749ecccf8a8210c0cc55Xoppa getIndicesBuffer().position(srcOffset); 327b1e5f16aadd6d8481c7b749ecccf8a8210c0cc55Xoppa getIndicesBuffer().get(indices, destOffset, count); 3284732e63a3c5a351cef799716735039019c3bd364badlogicgames getIndicesBuffer().position(pos); 3294732e63a3c5a351cef799716735039019c3bd364badlogicgames } 33030597377f5f74e1e402481d423a8ecc933e65ed2nathan.sweet 3312f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet /** @return the number of defined indices */ 332c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet public int getNumIndices () { 333f1fa40492f7ea283f5ded3d671ce685277405dc3badlogicgames return indices.getNumIndices(); 334114c5c91c13f74b04c08c0816d649da267bdcbbdbadlogicgames } 33530597377f5f74e1e402481d423a8ecc933e65ed2nathan.sweet 3362f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet /** @return the number of defined vertices */ 337c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet public int getNumVertices () { 338f1fa40492f7ea283f5ded3d671ce685277405dc3badlogicgames return vertices.getNumVertices(); 339f1fa40492f7ea283f5ded3d671ce685277405dc3badlogicgames } 3400fb217903b1b0c5a4a3a63c604e912a3a2e6d4e2badlogicgames 3412f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet /** @return the maximum number of vertices this mesh can hold */ 342c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet public int getMaxVertices () { 343f1fa40492f7ea283f5ded3d671ce685277405dc3badlogicgames return vertices.getNumMaxVertices(); 344f1fa40492f7ea283f5ded3d671ce685277405dc3badlogicgames } 345f1fa40492f7ea283f5ded3d671ce685277405dc3badlogicgames 3462f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet /** @return the maximum number of indices this mesh can hold */ 347c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet public int getMaxIndices () { 348f1fa40492f7ea283f5ded3d671ce685277405dc3badlogicgames return indices.getNumMaxIndices(); 349114c5c91c13f74b04c08c0816d649da267bdcbbdbadlogicgames } 35030597377f5f74e1e402481d423a8ecc933e65ed2nathan.sweet 3512f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet /** @return the size of a single vertex in bytes */ 352c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet public int getVertexSize () { 353f1fa40492f7ea283f5ded3d671ce685277405dc3badlogicgames return vertices.getAttributes().vertexSize; 354f1fa40492f7ea283f5ded3d671ce685277405dc3badlogicgames } 355f1fa40492f7ea283f5ded3d671ce685277405dc3badlogicgames 3562f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet /** Sets whether to bind the underlying {@link VertexArray} or {@link VertexBufferObject} automatically on a call to one of the 3579433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet * render methods. Usually you want to use autobind. Manual binding is an expert functionality. There is a driver bug on the 3589433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet * MSM720xa chips that will fuck up memory if you manipulate the vertices and indices of a Mesh multiple times while it is 3599433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet * bound. Keep this in mind. 3600c2f4f311d59a0dc53b2e074f5e583b640566956badlogicgames * 3612f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet * @param autoBind whether to autobind meshes. */ 362c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet public void setAutoBind (boolean autoBind) { 3630c2f4f311d59a0dc53b2e074f5e583b640566956badlogicgames this.autoBind = autoBind; 3649433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet } 3650fb217903b1b0c5a4a3a63c604e912a3a2e6d4e2badlogicgames 3662f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet /** Binds the underlying {@link VertexBufferObject} and {@link IndexBufferObject} if indices where given. Use this with OpenGL 367c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet * ES 2.0 and when auto-bind is disabled. 3680fb217903b1b0c5a4a3a63c604e912a3a2e6d4e2badlogicgames * 3692f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet * @param shader the shader (does not bind the shader) */ 370e3286411b0bf0d72eca4462a1468bdf4c0b885cfXoppa public void bind (final ShaderProgram shader) { 371e3286411b0bf0d72eca4462a1468bdf4c0b885cfXoppa bind(shader, null); 372e3286411b0bf0d72eca4462a1468bdf4c0b885cfXoppa } 373e3286411b0bf0d72eca4462a1468bdf4c0b885cfXoppa 374e3286411b0bf0d72eca4462a1468bdf4c0b885cfXoppa /** Binds the underlying {@link VertexBufferObject} and {@link IndexBufferObject} if indices where given. Use this with OpenGL 375e3286411b0bf0d72eca4462a1468bdf4c0b885cfXoppa * ES 2.0 and when auto-bind is disabled. 376e3286411b0bf0d72eca4462a1468bdf4c0b885cfXoppa * 3779433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet * @param shader the shader (does not bind the shader) 37893642c20846d2342e9d75c02292d9031e48316cbXoppa * @param locations array containing the attribute locations. */ 37993642c20846d2342e9d75c02292d9031e48316cbXoppa public void bind (final ShaderProgram shader, final int[] locations) { 380e3286411b0bf0d72eca4462a1468bdf4c0b885cfXoppa vertices.bind(shader, locations); 381c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet if (indices.getNumIndices() > 0) indices.bind(); 382f1fa40492f7ea283f5ded3d671ce685277405dc3badlogicgames } 3830fb217903b1b0c5a4a3a63c604e912a3a2e6d4e2badlogicgames 3842f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet /** Unbinds the underlying {@link VertexBufferObject} and {@link IndexBufferObject} is indices were given. Use this with OpenGL 385c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet * ES 1.x and when auto-bind is disabled. 3860fb217903b1b0c5a4a3a63c604e912a3a2e6d4e2badlogicgames * 3872f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet * @param shader the shader (does not unbind the shader) */ 388e3286411b0bf0d72eca4462a1468bdf4c0b885cfXoppa public void unbind (final ShaderProgram shader) { 389e3286411b0bf0d72eca4462a1468bdf4c0b885cfXoppa unbind(shader, null); 390e3286411b0bf0d72eca4462a1468bdf4c0b885cfXoppa } 3919433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet 392e3286411b0bf0d72eca4462a1468bdf4c0b885cfXoppa /** Unbinds the underlying {@link VertexBufferObject} and {@link IndexBufferObject} is indices were given. Use this with OpenGL 393e3286411b0bf0d72eca4462a1468bdf4c0b885cfXoppa * ES 1.x and when auto-bind is disabled. 394e3286411b0bf0d72eca4462a1468bdf4c0b885cfXoppa * 395e3286411b0bf0d72eca4462a1468bdf4c0b885cfXoppa * @param shader the shader (does not unbind the shader) 39693642c20846d2342e9d75c02292d9031e48316cbXoppa * @param locations array containing the attribute locations. */ 39793642c20846d2342e9d75c02292d9031e48316cbXoppa public void unbind (final ShaderProgram shader, final int[] locations) { 398e3286411b0bf0d72eca4462a1468bdf4c0b885cfXoppa vertices.unbind(shader, locations); 399c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet if (indices.getNumIndices() > 0) indices.unbind(); 400f1fa40492f7ea283f5ded3d671ce685277405dc3badlogicgames } 4010fb217903b1b0c5a4a3a63c604e912a3a2e6d4e2badlogicgames 4022f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet /** <p> 403c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet * Renders the mesh using the given primitive type. If indices are set for this mesh then getNumIndices() / #vertices per 404c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet * primitive primitives are rendered. If no indices are set then getNumVertices() / #vertices per primitive are rendered. 405847c371a0012580e84fa65d7348b930a7aa4e805badlogicgames * </p> 406114c5c91c13f74b04c08c0816d649da267bdcbbdbadlogicgames * 407847c371a0012580e84fa65d7348b930a7aa4e805badlogicgames * <p> 408c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet * This method will automatically bind each vertex attribute as specified at construction time via {@link VertexAttributes} to 409c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet * the respective shader attributes. The binding is based on the alias defined for each VertexAttribute. 410847c371a0012580e84fa65d7348b930a7aa4e805badlogicgames * </p> 411847c371a0012580e84fa65d7348b930a7aa4e805badlogicgames * 412847c371a0012580e84fa65d7348b930a7aa4e805badlogicgames * <p> 413c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet * This method must only be called after the {@link ShaderProgram#begin()} method has been called! 414847c371a0012580e84fa65d7348b930a7aa4e805badlogicgames * </p> 415847c371a0012580e84fa65d7348b930a7aa4e805badlogicgames * 416847c371a0012580e84fa65d7348b930a7aa4e805badlogicgames * <p> 417c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet * This method is intended for use with OpenGL ES 2.0 and will throw an IllegalStateException when OpenGL ES 1.x is used. 418847c371a0012580e84fa65d7348b930a7aa4e805badlogicgames * </p> 419847c371a0012580e84fa65d7348b930a7aa4e805badlogicgames * 4202f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet * @param primitiveType the primitive type */ 421c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet public void render (ShaderProgram shader, int primitiveType) { 422e3286411b0bf0d72eca4462a1468bdf4c0b885cfXoppa render(shader, primitiveType, 0, indices.getNumMaxIndices() > 0 ? getNumIndices() : getNumVertices(), autoBind); 423114c5c91c13f74b04c08c0816d649da267bdcbbdbadlogicgames } 424847c371a0012580e84fa65d7348b930a7aa4e805badlogicgames 4252f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet /** <p> 426c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet * Renders the mesh using the given primitive type. offset specifies the offset into either the vertex buffer or the index 427c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet * buffer depending on whether indices are defined. count specifies the number of vertices or indices to use thus count / 428c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet * #vertices per primitive primitives are rendered. 429847c371a0012580e84fa65d7348b930a7aa4e805badlogicgames * </p> 430847c371a0012580e84fa65d7348b930a7aa4e805badlogicgames * 431847c371a0012580e84fa65d7348b930a7aa4e805badlogicgames * <p> 432c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet * This method will automatically bind each vertex attribute as specified at construction time via {@link VertexAttributes} to 433c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet * the respective shader attributes. The binding is based on the alias defined for each VertexAttribute. 434847c371a0012580e84fa65d7348b930a7aa4e805badlogicgames * </p> 435847c371a0012580e84fa65d7348b930a7aa4e805badlogicgames * 436847c371a0012580e84fa65d7348b930a7aa4e805badlogicgames * <p> 437c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet * This method must only be called after the {@link ShaderProgram#begin()} method has been called! 438847c371a0012580e84fa65d7348b930a7aa4e805badlogicgames * </p> 439847c371a0012580e84fa65d7348b930a7aa4e805badlogicgames * 440847c371a0012580e84fa65d7348b930a7aa4e805badlogicgames * <p> 441c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet * This method is intended for use with OpenGL ES 2.0 and will throw an IllegalStateException when OpenGL ES 1.x is used. 442847c371a0012580e84fa65d7348b930a7aa4e805badlogicgames * </p> 443847c371a0012580e84fa65d7348b930a7aa4e805badlogicgames * 444c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet * @param shader the shader to be used 445c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet * @param primitiveType the primitive type 446c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet * @param offset the offset into the vertex or index buffer 4472f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet * @param count number of vertices or indices to use */ 448c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet public void render (ShaderProgram shader, int primitiveType, int offset, int count) { 4499433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet render(shader, primitiveType, offset, count, autoBind); 450e3286411b0bf0d72eca4462a1468bdf4c0b885cfXoppa } 4519433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet 452e3286411b0bf0d72eca4462a1468bdf4c0b885cfXoppa /** <p> 453e3286411b0bf0d72eca4462a1468bdf4c0b885cfXoppa * Renders the mesh using the given primitive type. offset specifies the offset into either the vertex buffer or the index 454e3286411b0bf0d72eca4462a1468bdf4c0b885cfXoppa * buffer depending on whether indices are defined. count specifies the number of vertices or indices to use thus count / 455e3286411b0bf0d72eca4462a1468bdf4c0b885cfXoppa * #vertices per primitive primitives are rendered. 456e3286411b0bf0d72eca4462a1468bdf4c0b885cfXoppa * </p> 457e3286411b0bf0d72eca4462a1468bdf4c0b885cfXoppa * 458e3286411b0bf0d72eca4462a1468bdf4c0b885cfXoppa * <p> 459e3286411b0bf0d72eca4462a1468bdf4c0b885cfXoppa * This method will automatically bind each vertex attribute as specified at construction time via {@link VertexAttributes} to 460e3286411b0bf0d72eca4462a1468bdf4c0b885cfXoppa * the respective shader attributes. The binding is based on the alias defined for each VertexAttribute. 461e3286411b0bf0d72eca4462a1468bdf4c0b885cfXoppa * </p> 462e3286411b0bf0d72eca4462a1468bdf4c0b885cfXoppa * 463e3286411b0bf0d72eca4462a1468bdf4c0b885cfXoppa * <p> 464e3286411b0bf0d72eca4462a1468bdf4c0b885cfXoppa * This method must only be called after the {@link ShaderProgram#begin()} method has been called! 465e3286411b0bf0d72eca4462a1468bdf4c0b885cfXoppa * </p> 466e3286411b0bf0d72eca4462a1468bdf4c0b885cfXoppa * 467e3286411b0bf0d72eca4462a1468bdf4c0b885cfXoppa * <p> 468e3286411b0bf0d72eca4462a1468bdf4c0b885cfXoppa * This method is intended for use with OpenGL ES 2.0 and will throw an IllegalStateException when OpenGL ES 1.x is used. 469e3286411b0bf0d72eca4462a1468bdf4c0b885cfXoppa * </p> 470e3286411b0bf0d72eca4462a1468bdf4c0b885cfXoppa * 471e3286411b0bf0d72eca4462a1468bdf4c0b885cfXoppa * @param shader the shader to be used 472e3286411b0bf0d72eca4462a1468bdf4c0b885cfXoppa * @param primitiveType the primitive type 473e3286411b0bf0d72eca4462a1468bdf4c0b885cfXoppa * @param offset the offset into the vertex or index buffer 474e3286411b0bf0d72eca4462a1468bdf4c0b885cfXoppa * @param count number of vertices or indices to use 475e3286411b0bf0d72eca4462a1468bdf4c0b885cfXoppa * @param autoBind overrides the autoBind member of this Mesh */ 476e3286411b0bf0d72eca4462a1468bdf4c0b885cfXoppa public void render (ShaderProgram shader, int primitiveType, int offset, int count, boolean autoBind) { 4772c9030de2ddb983cfaeb5736089453b32c559cc1Nathan Sweet if (count == 0) return; 4782c9030de2ddb983cfaeb5736089453b32c559cc1Nathan Sweet 479c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet if (autoBind) bind(shader); 4800fb217903b1b0c5a4a3a63c604e912a3a2e6d4e2badlogicgames 481f693d47c8859c9fb3039441d6da01289564b8726badlogicgames if (isVertexArray) { 482f693d47c8859c9fb3039441d6da01289564b8726badlogicgames if (indices.getNumIndices() > 0) { 483f693d47c8859c9fb3039441d6da01289564b8726badlogicgames ShortBuffer buffer = indices.getBuffer(); 484f693d47c8859c9fb3039441d6da01289564b8726badlogicgames int oldPosition = buffer.position(); 485f693d47c8859c9fb3039441d6da01289564b8726badlogicgames int oldLimit = buffer.limit(); 486f693d47c8859c9fb3039441d6da01289564b8726badlogicgames buffer.position(offset); 487f693d47c8859c9fb3039441d6da01289564b8726badlogicgames buffer.limit(offset + count); 48808711a2152eda79f20c2db6064b4f1b444b6ea0cbadlogic Gdx.gl20.glDrawElements(primitiveType, count, GL20.GL_UNSIGNED_SHORT, buffer); 489f693d47c8859c9fb3039441d6da01289564b8726badlogicgames buffer.position(oldPosition); 490f693d47c8859c9fb3039441d6da01289564b8726badlogicgames buffer.limit(oldLimit); 49159787375f8b2ebe19189a355a281199688d5a5e9badlogicgames } else { 49259787375f8b2ebe19189a355a281199688d5a5e9badlogicgames Gdx.gl20.glDrawArrays(primitiveType, offset, count); 49359787375f8b2ebe19189a355a281199688d5a5e9badlogicgames } 494f693d47c8859c9fb3039441d6da01289564b8726badlogicgames } else { 495f693d47c8859c9fb3039441d6da01289564b8726badlogicgames if (indices.getNumIndices() > 0) 49608711a2152eda79f20c2db6064b4f1b444b6ea0cbadlogic Gdx.gl20.glDrawElements(primitiveType, count, GL20.GL_UNSIGNED_SHORT, offset * 2); 497f693d47c8859c9fb3039441d6da01289564b8726badlogicgames else 498f693d47c8859c9fb3039441d6da01289564b8726badlogicgames Gdx.gl20.glDrawArrays(primitiveType, offset, count); 499f693d47c8859c9fb3039441d6da01289564b8726badlogicgames } 5000fb217903b1b0c5a4a3a63c604e912a3a2e6d4e2badlogicgames 501c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet if (autoBind) unbind(shader); 502114c5c91c13f74b04c08c0816d649da267bdcbbdbadlogicgames } 50330597377f5f74e1e402481d423a8ecc933e65ed2nathan.sweet 5042f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet /** Frees all resources associated with this Mesh */ 505c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet public void dispose () { 5060a5c1025d1f147746db4f92bfd3c1ba4abea58b9Jon Renner if (meshes.get(Gdx.app) != null) meshes.get(Gdx.app).removeValue(this, true); 507f1fa40492f7ea283f5ded3d671ce685277405dc3badlogicgames vertices.dispose(); 508f1fa40492f7ea283f5ded3d671ce685277405dc3badlogicgames indices.dispose(); 509114c5c91c13f74b04c08c0816d649da267bdcbbdbadlogicgames } 510114c5c91c13f74b04c08c0816d649da267bdcbbdbadlogicgames 5112f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet /** Returns the first {@link VertexAttribute} having the given {@link Usage}. 512114c5c91c13f74b04c08c0816d649da267bdcbbdbadlogicgames * 513c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet * @param usage the Usage. 5142f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet * @return the VertexAttribute or null if no attribute with that usage was found. */ 515c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet public VertexAttribute getVertexAttribute (int usage) { 516f1fa40492f7ea283f5ded3d671ce685277405dc3badlogicgames VertexAttributes attributes = vertices.getAttributes(); 517f1fa40492f7ea283f5ded3d671ce685277405dc3badlogicgames int len = attributes.size(); 518f1fa40492f7ea283f5ded3d671ce685277405dc3badlogicgames for (int i = 0; i < len; i++) 519c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet if (attributes.get(i).usage == usage) return attributes.get(i); 52030597377f5f74e1e402481d423a8ecc933e65ed2nathan.sweet 521114c5c91c13f74b04c08c0816d649da267bdcbbdbadlogicgames return null; 522114c5c91c13f74b04c08c0816d649da267bdcbbdbadlogicgames } 52330597377f5f74e1e402481d423a8ecc933e65ed2nathan.sweet 5242f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet /** @return the vertex attributes of this Mesh */ 525c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet public VertexAttributes getVertexAttributes () { 526f1fa40492f7ea283f5ded3d671ce685277405dc3badlogicgames return vertices.getAttributes(); 527114c5c91c13f74b04c08c0816d649da267bdcbbdbadlogicgames } 52830597377f5f74e1e402481d423a8ecc933e65ed2nathan.sweet 5292f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet /** @return the backing FloatBuffer holding the vertices. Does not have to be a direct buffer on Android! */ 530c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet public FloatBuffer getVerticesBuffer () { 531f1fa40492f7ea283f5ded3d671ce685277405dc3badlogicgames return vertices.getBuffer(); 5325836b479b519807d4a6fab91600fe6943d637505badlogicgames } 5332f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet 5342f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet /** Calculates the {@link BoundingBox} of the vertices contained in this mesh. In case no vertices are defined yet a 5352f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet * {@link GdxRuntimeException} is thrown. This method creates a new BoundingBox instance. 5365dc2f5d616354b058897632abb2d080dcde123c8badlogicgames * 5372f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet * @return the bounding box. */ 5382f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet public BoundingBox calculateBoundingBox () { 5396c11e3667fcc1328385f17ac08ba57d3432e9380badlogicgames BoundingBox bbox = new BoundingBox(); 5406c11e3667fcc1328385f17ac08ba57d3432e9380badlogicgames calculateBoundingBox(bbox); 5416c11e3667fcc1328385f17ac08ba57d3432e9380badlogicgames return bbox; 5426c11e3667fcc1328385f17ac08ba57d3432e9380badlogicgames } 5432f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet 5442f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet /** Calculates the {@link BoundingBox} of the vertices contained in this mesh. In case no vertices are defined yet a 5452f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet * {@link GdxRuntimeException} is thrown. 5466c11e3667fcc1328385f17ac08ba57d3432e9380badlogicgames * 5472f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet * @param bbox the bounding box to store the result in. */ 5482f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet public void calculateBoundingBox (BoundingBox bbox) { 5495dc2f5d616354b058897632abb2d080dcde123c8badlogicgames final int numVertices = getNumVertices(); 5502f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet if (numVertices == 0) throw new GdxRuntimeException("No vertices defined"); 5512f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet 5525dc2f5d616354b058897632abb2d080dcde123c8badlogicgames final FloatBuffer verts = vertices.getBuffer(); 5535dc2f5d616354b058897632abb2d080dcde123c8badlogicgames bbox.inf(); 5545dc2f5d616354b058897632abb2d080dcde123c8badlogicgames final VertexAttribute posAttrib = getVertexAttribute(Usage.Position); 5552f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet final int offset = posAttrib.offset / 4; 5565dc2f5d616354b058897632abb2d080dcde123c8badlogicgames final int vertexSize = vertices.getAttributes().vertexSize / 4; 5575dc2f5d616354b058897632abb2d080dcde123c8badlogicgames int idx = offset; 5582f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet 5592f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet switch (posAttrib.numComponents) { 5602f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet case 1: 5612f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet for (int i = 0; i < numVertices; i++) { 5622f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet bbox.ext(verts.get(idx), 0, 0); 5632f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet idx += vertexSize; 5642f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet } 5652f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet break; 5662f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet case 2: 5672f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet for (int i = 0; i < numVertices; i++) { 5682f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet bbox.ext(verts.get(idx), verts.get(idx + 1), 0); 5692f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet idx += vertexSize; 5702f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet } 5712f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet break; 5722f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet case 3: 5732f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet for (int i = 0; i < numVertices; i++) { 5742f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet bbox.ext(verts.get(idx), verts.get(idx + 1), verts.get(idx + 2)); 5752f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet idx += vertexSize; 5762f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet } 5772f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet break; 5782f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet } 5792f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet } 5809433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet 581ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa /** Calculate the {@link BoundingBox} of the specified part. 5829433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet * @param out the bounding box to store the result in. 583ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa * @param offset the start index of the part. 5849433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet * @param count the amount of indices the part contains. 585ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa * @return the value specified by out. */ 5869433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet public BoundingBox calculateBoundingBox (final BoundingBox out, int offset, int count) { 587ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa return extendBoundingBox(out.inf(), offset, count); 588ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa } 5899433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet 590c92ddcf1b1795845789dbcbaee455be4540e7d42Xoppa /** Calculate the {@link BoundingBox} of the specified part. 5919433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet * @param out the bounding box to store the result in. 592c92ddcf1b1795845789dbcbaee455be4540e7d42Xoppa * @param offset the start index of the part. 5939433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet * @param count the amount of indices the part contains. 594c92ddcf1b1795845789dbcbaee455be4540e7d42Xoppa * @return the value specified by out. */ 5959433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet public BoundingBox calculateBoundingBox (final BoundingBox out, int offset, int count, final Matrix4 transform) { 596c92ddcf1b1795845789dbcbaee455be4540e7d42Xoppa return extendBoundingBox(out.inf(), offset, count, transform); 597c92ddcf1b1795845789dbcbaee455be4540e7d42Xoppa } 598c92ddcf1b1795845789dbcbaee455be4540e7d42Xoppa 599ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa /** Extends the specified {@link BoundingBox} with the specified part. 6009433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet * @param out the bounding box to store the result in. 601ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa * @param offset the start index of the part. 6029433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet * @param count the amount of indices the part contains. 603ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa * @return the value specified by out. */ 6049433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet public BoundingBox extendBoundingBox (final BoundingBox out, int offset, int count) { 605c92ddcf1b1795845789dbcbaee455be4540e7d42Xoppa return extendBoundingBox(out, offset, count, null); 606c92ddcf1b1795845789dbcbaee455be4540e7d42Xoppa } 6079433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet 608c92ddcf1b1795845789dbcbaee455be4540e7d42Xoppa private final Vector3 tmpV = new Vector3(); 6099433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet 610c92ddcf1b1795845789dbcbaee455be4540e7d42Xoppa /** Extends the specified {@link BoundingBox} with the specified part. 6119433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet * @param out the bounding box to store the result in. 612d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa * @param offset the start of the part. 613d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa * @param count the size of the part. 614c92ddcf1b1795845789dbcbaee455be4540e7d42Xoppa * @return the value specified by out. */ 6159433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet public BoundingBox extendBoundingBox (final BoundingBox out, int offset, int count, final Matrix4 transform) { 616d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa final int numIndices = getNumIndices(); 617d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa final int numVertices = getNumVertices(); 618d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa final int max = numIndices == 0 ? numVertices : numIndices; 619d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa if (offset < 0 || count < 1 || offset + count > max) 620d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa throw new GdxRuntimeException("Invalid part specified ( offset=" + offset + ", count=" + count + ", max=" + max + " )"); 6219433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet 622ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa final FloatBuffer verts = vertices.getBuffer(); 623ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa final ShortBuffer index = indices.getBuffer(); 624ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa final VertexAttribute posAttrib = getVertexAttribute(Usage.Position); 625ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa final int posoff = posAttrib.offset / 4; 626ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa final int vertexSize = vertices.getAttributes().vertexSize / 4; 627ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa final int end = offset + count; 6289433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet 629ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa switch (posAttrib.numComponents) { 630ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa case 1: 631d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa if (numIndices > 0) { 632d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa for (int i = offset; i < end; i++) { 633d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa final int idx = index.get(i) * vertexSize + posoff; 634d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa tmpV.set(verts.get(idx), 0, 0); 635d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa if (transform != null) tmpV.mul(transform); 636d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa out.ext(tmpV); 637d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa } 638d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa } else { 639d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa for (int i = offset; i < end; i++) { 640d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa final int idx = i * vertexSize + posoff; 641d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa tmpV.set(verts.get(idx), 0, 0); 642d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa if (transform != null) tmpV.mul(transform); 643d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa out.ext(tmpV); 644d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa } 645ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa } 646ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa break; 647ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa case 2: 648d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa if (numIndices > 0) { 649d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa for (int i = offset; i < end; i++) { 650d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa final int idx = index.get(i) * vertexSize + posoff; 651d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa tmpV.set(verts.get(idx), verts.get(idx + 1), 0); 652d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa if (transform != null) tmpV.mul(transform); 653d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa out.ext(tmpV); 654d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa } 655d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa } else { 656d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa for (int i = offset; i < end; i++) { 657d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa final int idx = i * vertexSize + posoff; 658d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa tmpV.set(verts.get(idx), verts.get(idx + 1), 0); 659d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa if (transform != null) tmpV.mul(transform); 660d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa out.ext(tmpV); 661d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa } 662ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa } 663ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa break; 664ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa case 3: 665d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa if (numIndices > 0) { 666d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa for (int i = offset; i < end; i++) { 667d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa final int idx = index.get(i) * vertexSize + posoff; 668d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa tmpV.set(verts.get(idx), verts.get(idx + 1), verts.get(idx + 2)); 669d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa if (transform != null) tmpV.mul(transform); 670d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa out.ext(tmpV); 671d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa } 672d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa } else { 673d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa for (int i = offset; i < end; i++) { 674d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa final int idx = i * vertexSize + posoff; 675d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa tmpV.set(verts.get(idx), verts.get(idx + 1), verts.get(idx + 2)); 676d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa if (transform != null) tmpV.mul(transform); 677d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa out.ext(tmpV); 678d7fa8a0037ceb94f45b1a1877f74b70fb3751ed9Xoppa } 679ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa } 680ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa break; 681ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa } 682ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa return out; 683ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa } 6849433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet 6857a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa /** Calculates the squared radius of the bounding sphere around the specified center for the specified part. 6867a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa * @param centerX The X coordinate of the center of the bounding sphere 6877a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa * @param centerY The Y coordinate of the center of the bounding sphere 6887a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa * @param centerZ The Z coordinate of the center of the bounding sphere 6897a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa * @param offset the start index of the part. 6909433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet * @param count the amount of indices the part contains. 6917a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa * @return the squared radius of the bounding sphere. */ 6929433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet public float calculateRadiusSquared (final float centerX, final float centerY, final float centerZ, int offset, int count, 6939433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet final Matrix4 transform) { 6947a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa int numIndices = getNumIndices(); 6959433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet if (offset < 0 || count < 1 || offset + count > numIndices) throw new GdxRuntimeException("Not enough indices"); 6969433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet 6977a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa final FloatBuffer verts = vertices.getBuffer(); 6987a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa final ShortBuffer index = indices.getBuffer(); 6997a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa final VertexAttribute posAttrib = getVertexAttribute(Usage.Position); 7007a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa final int posoff = posAttrib.offset / 4; 7017a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa final int vertexSize = vertices.getAttributes().vertexSize / 4; 7027a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa final int end = offset + count; 7039433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet 7047a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa float result = 0; 7059433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet 7067a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa switch (posAttrib.numComponents) { 7077a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa case 1: 7087a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa for (int i = offset; i < end; i++) { 7097a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa final int idx = index.get(i) * vertexSize + posoff; 7107a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa tmpV.set(verts.get(idx), 0, 0); 7119433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet if (transform != null) tmpV.mul(transform); 7127a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa final float r = tmpV.sub(centerX, centerY, centerZ).len2(); 7139433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet if (r > result) result = r; 7147a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa } 7157a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa break; 7167a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa case 2: 7177a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa for (int i = offset; i < end; i++) { 7187a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa final int idx = index.get(i) * vertexSize + posoff; 7197a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa tmpV.set(verts.get(idx), verts.get(idx + 1), 0); 7209433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet if (transform != null) tmpV.mul(transform); 7217a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa final float r = tmpV.sub(centerX, centerY, centerZ).len2(); 7229433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet if (r > result) result = r; 7237a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa } 7247a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa break; 7257a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa case 3: 7267a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa for (int i = offset; i < end; i++) { 7277a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa final int idx = index.get(i) * vertexSize + posoff; 7287a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa tmpV.set(verts.get(idx), verts.get(idx + 1), verts.get(idx + 2)); 7299433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet if (transform != null) tmpV.mul(transform); 7307a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa final float r = tmpV.sub(centerX, centerY, centerZ).len2(); 7319433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet if (r > result) result = r; 7327a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa } 7337a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa break; 7347a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa } 7357a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa return result; 7367a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa } 7379433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet 7387a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa /** Calculates the radius of the bounding sphere around the specified center for the specified part. 7397a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa * @param centerX The X coordinate of the center of the bounding sphere 7407a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa * @param centerY The Y coordinate of the center of the bounding sphere 7417a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa * @param centerZ The Z coordinate of the center of the bounding sphere 7427a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa * @param offset the start index of the part. 7439433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet * @param count the amount of indices the part contains. 7447a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa * @return the radius of the bounding sphere. */ 7459433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet public float calculateRadius (final float centerX, final float centerY, final float centerZ, int offset, int count, 7469433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet final Matrix4 transform) { 7477a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa return (float)Math.sqrt(calculateRadiusSquared(centerX, centerY, centerZ, offset, count, transform)); 7487a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa } 7499433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet 7507a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa /** Calculates the squared radius of the bounding sphere around the specified center for the specified part. 7517a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa * @param center The center of the bounding sphere 7527a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa * @param offset the start index of the part. 7539433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet * @param count the amount of indices the part contains. 7547a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa * @return the squared radius of the bounding sphere. */ 7559433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet public float calculateRadius (final Vector3 center, int offset, int count, final Matrix4 transform) { 7567a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa return calculateRadius(center.x, center.y, center.z, offset, count, transform); 7577a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa } 7589433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet 7597a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa /** Calculates the squared radius of the bounding sphere around the specified center for the specified part. 7607a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa * @param centerX The X coordinate of the center of the bounding sphere 7617a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa * @param centerY The Y coordinate of the center of the bounding sphere 7627a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa * @param centerZ The Z coordinate of the center of the bounding sphere 7637a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa * @param offset the start index of the part. 7649433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet * @param count the amount of indices the part contains. 7657a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa * @return the squared radius of the bounding sphere. */ 7669433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet public float calculateRadius (final float centerX, final float centerY, final float centerZ, int offset, int count) { 7677a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa return calculateRadius(centerX, centerY, centerZ, offset, count, null); 7687a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa } 7699433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet 7707a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa /** Calculates the squared radius of the bounding sphere around the specified center for the specified part. 7717a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa * @param center The center of the bounding sphere 7727a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa * @param offset the start index of the part. 7739433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet * @param count the amount of indices the part contains. 7747a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa * @return the squared radius of the bounding sphere. */ 7759433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet public float calculateRadius (final Vector3 center, int offset, int count) { 7767a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa return calculateRadius(center.x, center.y, center.z, offset, count, null); 7777a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa } 7789433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet 7797a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa /** Calculates the squared radius of the bounding sphere around the specified center for the specified part. 7807a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa * @param centerX The X coordinate of the center of the bounding sphere 7817a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa * @param centerY The Y coordinate of the center of the bounding sphere 7827a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa * @param centerZ The Z coordinate of the center of the bounding sphere 7837a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa * @return the squared radius of the bounding sphere. */ 7849433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet public float calculateRadius (final float centerX, final float centerY, final float centerZ) { 7857a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa return calculateRadius(centerX, centerY, centerZ, 0, getNumIndices(), null); 7867a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa } 7879433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet 7887a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa /** Calculates the squared radius of the bounding sphere around the specified center for the specified part. 7897a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa * @param center The center of the bounding sphere 7907a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa * @return the squared radius of the bounding sphere. */ 7919433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet public float calculateRadius (final Vector3 center) { 7927a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa return calculateRadius(center.x, center.y, center.z, 0, getNumIndices(), null); 7937a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa } 7949433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet 7952f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet /** @return the backing shortbuffer holding the indices. Does not have to be a direct buffer on Android! */ 796c1a20432e96c5ceb32a62b52627aaa6f93e703aenathan.sweet public ShortBuffer getIndicesBuffer () { 797f1fa40492f7ea283f5ded3d671ce685277405dc3badlogicgames return indices.getBuffer(); 798114c5c91c13f74b04c08c0816d649da267bdcbbdbadlogicgames } 79930597377f5f74e1e402481d423a8ecc933e65ed2nathan.sweet 8002f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet private static void addManagedMesh (Application app, Mesh mesh) { 8010a5c1025d1f147746db4f92bfd3c1ba4abea58b9Jon Renner Array<Mesh> managedResources = meshes.get(app); 8020a5c1025d1f147746db4f92bfd3c1ba4abea58b9Jon Renner if (managedResources == null) managedResources = new Array<Mesh>(); 80392ed4d69842a61ff92fabe3167305fbf82bb5e94badlogicgames managedResources.add(mesh); 80492ed4d69842a61ff92fabe3167305fbf82bb5e94badlogicgames meshes.put(app, managedResources); 80592ed4d69842a61ff92fabe3167305fbf82bb5e94badlogicgames } 8062f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet 8072f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet /** Invalidates all meshes so the next time they are rendered new VBO handles are generated. 8082f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet * @param app */ 80992ed4d69842a61ff92fabe3167305fbf82bb5e94badlogicgames public static void invalidateAllMeshes (Application app) { 8100a5c1025d1f147746db4f92bfd3c1ba4abea58b9Jon Renner Array<Mesh> meshesArray = meshes.get(app); 8110a5c1025d1f147746db4f92bfd3c1ba4abea58b9Jon Renner if (meshesArray == null) return; 8120a5c1025d1f147746db4f92bfd3c1ba4abea58b9Jon Renner for (int i = 0; i < meshesArray.size; i++) { 8135f4eac0a477e0e9f952ceab25c89dd9da51d3e03Xoppa meshesArray.get(i).vertices.invalidate(); 8140a5c1025d1f147746db4f92bfd3c1ba4abea58b9Jon Renner meshesArray.get(i).indices.invalidate(); 815114c5c91c13f74b04c08c0816d649da267bdcbbdbadlogicgames } 816114c5c91c13f74b04c08c0816d649da267bdcbbdbadlogicgames } 81730597377f5f74e1e402481d423a8ecc933e65ed2nathan.sweet 8182f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet /** Will clear the managed mesh cache. I wouldn't use this if i was you :) */ 8192f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet public static void clearAllMeshes (Application app) { 82092ed4d69842a61ff92fabe3167305fbf82bb5e94badlogicgames meshes.remove(app); 82192ed4d69842a61ff92fabe3167305fbf82bb5e94badlogicgames } 8222f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet 8232f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet public static String getManagedStatus () { 82492ed4d69842a61ff92fabe3167305fbf82bb5e94badlogicgames StringBuilder builder = new StringBuilder(); 82592ed4d69842a61ff92fabe3167305fbf82bb5e94badlogicgames int i = 0; 82692ed4d69842a61ff92fabe3167305fbf82bb5e94badlogicgames builder.append("Managed meshes/app: { "); 8272f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet for (Application app : meshes.keySet()) { 8280a5c1025d1f147746db4f92bfd3c1ba4abea58b9Jon Renner builder.append(meshes.get(app).size); 82992ed4d69842a61ff92fabe3167305fbf82bb5e94badlogicgames builder.append(" "); 83092ed4d69842a61ff92fabe3167305fbf82bb5e94badlogicgames } 83192ed4d69842a61ff92fabe3167305fbf82bb5e94badlogicgames builder.append("}"); 83292ed4d69842a61ff92fabe3167305fbf82bb5e94badlogicgames return builder.toString(); 833fc2eb8df6aa4fed814c0f809851ad291e9ab7043badlogicgames } 8342f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet 8352f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet /** Method to scale the positions in the mesh. Normals will be kept as is. This is a potentially slow operation, use with care. 8362f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet * It will also create a temporary float[] which will be garbage collected. 83707e23dedf55a93606dff1c5069e379c053b73a78badlogicgames * 83807e23dedf55a93606dff1c5069e379c053b73a78badlogicgames * @param scaleX scale on x 83907e23dedf55a93606dff1c5069e379c053b73a78badlogicgames * @param scaleY scale on y 8402f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet * @param scaleZ scale on z */ 8412f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet public void scale (float scaleX, float scaleY, float scaleZ) { 84206e0eeb03633afc78536b775f5ef878288b1de02Xoppa final VertexAttribute posAttr = getVertexAttribute(Usage.Position); 84306e0eeb03633afc78536b775f5ef878288b1de02Xoppa final int offset = posAttr.offset / 4; 84406e0eeb03633afc78536b775f5ef878288b1de02Xoppa final int numComponents = posAttr.numComponents; 84506e0eeb03633afc78536b775f5ef878288b1de02Xoppa final int numVertices = getNumVertices(); 84606e0eeb03633afc78536b775f5ef878288b1de02Xoppa final int vertexSize = getVertexSize() / 4; 8472f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet 84806e0eeb03633afc78536b775f5ef878288b1de02Xoppa final float[] vertices = new float[numVertices * vertexSize]; 84907e23dedf55a93606dff1c5069e379c053b73a78badlogicgames getVertices(vertices); 8502f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet 85107e23dedf55a93606dff1c5069e379c053b73a78badlogicgames int idx = offset; 8522f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet switch (numComponents) { 85307e23dedf55a93606dff1c5069e379c053b73a78badlogicgames case 1: 8542f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet for (int i = 0; i < numVertices; i++) { 8552f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet vertices[idx] *= scaleX; 8562f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet idx += vertexSize; 85707e23dedf55a93606dff1c5069e379c053b73a78badlogicgames } 85807e23dedf55a93606dff1c5069e379c053b73a78badlogicgames break; 85907e23dedf55a93606dff1c5069e379c053b73a78badlogicgames case 2: 8602f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet for (int i = 0; i < numVertices; i++) { 86107e23dedf55a93606dff1c5069e379c053b73a78badlogicgames vertices[idx] *= scaleX; 8622f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet vertices[idx + 1] *= scaleY; 8632f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet idx += vertexSize; 86407e23dedf55a93606dff1c5069e379c053b73a78badlogicgames } 86507e23dedf55a93606dff1c5069e379c053b73a78badlogicgames break; 86607e23dedf55a93606dff1c5069e379c053b73a78badlogicgames case 3: 8672f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet for (int i = 0; i < numVertices; i++) { 86807e23dedf55a93606dff1c5069e379c053b73a78badlogicgames vertices[idx] *= scaleX; 8692f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet vertices[idx + 1] *= scaleY; 8702f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet vertices[idx + 2] *= scaleZ; 8712f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet idx += vertexSize; 87207e23dedf55a93606dff1c5069e379c053b73a78badlogicgames } 87307e23dedf55a93606dff1c5069e379c053b73a78badlogicgames break; 87407e23dedf55a93606dff1c5069e379c053b73a78badlogicgames } 8752f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet 87607e23dedf55a93606dff1c5069e379c053b73a78badlogicgames setVertices(vertices); 8772f412de0a867ffffe70909d9bb69434e3ac6b16bnathan.sweet } 8789433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet 8799433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet /** Method to transform the positions in the mesh. Normals will be kept as is. This is a potentially slow operation, use with 8809433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet * care. It will also create a temporary float[] which will be garbage collected. 88106e0eeb03633afc78536b775f5ef878288b1de02Xoppa * 88206e0eeb03633afc78536b775f5ef878288b1de02Xoppa * @param matrix the transformation matrix */ 8839433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet public void transform (final Matrix4 matrix) { 88406e0eeb03633afc78536b775f5ef878288b1de02Xoppa transform(matrix, 0, getNumVertices()); 88506e0eeb03633afc78536b775f5ef878288b1de02Xoppa } 8869433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet 88706e0eeb03633afc78536b775f5ef878288b1de02Xoppa // TODO: Protected for now, because transforming a portion works but still copies all vertices 8889433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet public void transform (final Matrix4 matrix, final int start, final int count) { 88906e0eeb03633afc78536b775f5ef878288b1de02Xoppa final VertexAttribute posAttr = getVertexAttribute(Usage.Position); 8907a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa final int posOffset = posAttr.offset / 4; 8917a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa final int stride = getVertexSize() / 4; 89206e0eeb03633afc78536b775f5ef878288b1de02Xoppa final int numComponents = posAttr.numComponents; 89306e0eeb03633afc78536b775f5ef878288b1de02Xoppa final int numVertices = getNumVertices(); 8949433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet 8957a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa final float[] vertices = new float[count * stride]; 8967a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa getVertices(start * stride, count * stride, vertices); 8977a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa // getVertices(0, vertices.length, vertices); 8987a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa transform(matrix, vertices, stride, posOffset, numComponents, 0, count); 8999433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet // setVertices(vertices, 0, vertices.length); 9007a0073fb6e1d9cf0f56101489abe2d4780a780e6Xoppa updateVertices(start * stride, vertices); 90106e0eeb03633afc78536b775f5ef878288b1de02Xoppa } 9029433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet 9039433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet /** Method to transform the positions in the float array. Normals will be kept as is. This is a potentially slow operation, use 9049433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet * with care. 90506e0eeb03633afc78536b775f5ef878288b1de02Xoppa * @param matrix the transformation matrix 90606e0eeb03633afc78536b775f5ef878288b1de02Xoppa * @param vertices the float array 90706e0eeb03633afc78536b775f5ef878288b1de02Xoppa * @param vertexSize the number of floats in each vertex 90806e0eeb03633afc78536b775f5ef878288b1de02Xoppa * @param offset the offset within a vertex to the position 90906e0eeb03633afc78536b775f5ef878288b1de02Xoppa * @param dimensions the size of the position 91006e0eeb03633afc78536b775f5ef878288b1de02Xoppa * @param start the vertex to start with 9119433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet * @param count the amount of vertices to transform */ 9129433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet public static void transform (final Matrix4 matrix, final float[] vertices, int vertexSize, int offset, int dimensions, 9139433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet int start, int count) { 9149433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet if (offset < 0 || dimensions < 1 || (offset + dimensions) > vertexSize) throw new IndexOutOfBoundsException(); 91506e0eeb03633afc78536b775f5ef878288b1de02Xoppa if (start < 0 || count < 1 || ((start + count) * vertexSize) > vertices.length) 9169433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet throw new IndexOutOfBoundsException("start = " + start + ", count = " + count + ", vertexSize = " + vertexSize 9179433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet + ", length = " + vertices.length); 9189433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet 919ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa final Vector3 tmp = new Vector3(); 9209433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet 92106e0eeb03633afc78536b775f5ef878288b1de02Xoppa int idx = offset + (start * vertexSize); 9229433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet switch (dimensions) { 92306e0eeb03633afc78536b775f5ef878288b1de02Xoppa case 1: 92406e0eeb03633afc78536b775f5ef878288b1de02Xoppa for (int i = 0; i < count; i++) { 92506e0eeb03633afc78536b775f5ef878288b1de02Xoppa tmp.set(vertices[idx], 0, 0).mul(matrix); 92606e0eeb03633afc78536b775f5ef878288b1de02Xoppa vertices[idx] = tmp.x; 92706e0eeb03633afc78536b775f5ef878288b1de02Xoppa idx += vertexSize; 92806e0eeb03633afc78536b775f5ef878288b1de02Xoppa } 92906e0eeb03633afc78536b775f5ef878288b1de02Xoppa break; 93006e0eeb03633afc78536b775f5ef878288b1de02Xoppa case 2: 93106e0eeb03633afc78536b775f5ef878288b1de02Xoppa for (int i = 0; i < count; i++) { 93206e0eeb03633afc78536b775f5ef878288b1de02Xoppa tmp.set(vertices[idx], vertices[idx + 1], 0).mul(matrix); 93306e0eeb03633afc78536b775f5ef878288b1de02Xoppa vertices[idx] = tmp.x; 9349433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet vertices[idx + 1] = tmp.y; 93506e0eeb03633afc78536b775f5ef878288b1de02Xoppa idx += vertexSize; 93606e0eeb03633afc78536b775f5ef878288b1de02Xoppa } 93706e0eeb03633afc78536b775f5ef878288b1de02Xoppa break; 93806e0eeb03633afc78536b775f5ef878288b1de02Xoppa case 3: 93906e0eeb03633afc78536b775f5ef878288b1de02Xoppa for (int i = 0; i < count; i++) { 94006e0eeb03633afc78536b775f5ef878288b1de02Xoppa tmp.set(vertices[idx], vertices[idx + 1], vertices[idx + 2]).mul(matrix); 94106e0eeb03633afc78536b775f5ef878288b1de02Xoppa vertices[idx] = tmp.x; 9429433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet vertices[idx + 1] = tmp.y; 9439433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet vertices[idx + 2] = tmp.z; 94406e0eeb03633afc78536b775f5ef878288b1de02Xoppa idx += vertexSize; 94506e0eeb03633afc78536b775f5ef878288b1de02Xoppa } 94606e0eeb03633afc78536b775f5ef878288b1de02Xoppa break; 94706e0eeb03633afc78536b775f5ef878288b1de02Xoppa } 94806e0eeb03633afc78536b775f5ef878288b1de02Xoppa } 9499433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet 9509433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet /** Method to transform the texture coordinates in the mesh. This is a potentially slow operation, use with care. It will also 9519433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet * create a temporary float[] which will be garbage collected. 952ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa * 953ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa * @param matrix the transformation matrix */ 9549433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet public void transformUV (final Matrix3 matrix) { 955ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa transformUV(matrix, 0, getNumVertices()); 956ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa } 9579433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet 958ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa // TODO: Protected for now, because transforming a portion works but still copies all vertices 9599433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet protected void transformUV (final Matrix3 matrix, final int start, final int count) { 960ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa final VertexAttribute posAttr = getVertexAttribute(Usage.TextureCoordinates); 961ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa final int offset = posAttr.offset / 4; 962ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa final int vertexSize = getVertexSize() / 4; 963ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa final int numVertices = getNumVertices(); 9649433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet 965ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa final float[] vertices = new float[numVertices * vertexSize]; 966ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa // TODO: getVertices(vertices, start * vertexSize, count * vertexSize); 967ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa getVertices(0, vertices.length, vertices); 968ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa transformUV(matrix, vertices, vertexSize, offset, start, count); 969ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa setVertices(vertices, 0, vertices.length); 970ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa // TODO: setVertices(start * vertexSize, vertices, 0, vertices.length); 971ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa } 9729433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet 9739433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet /** Method to transform the texture coordinates (UV) in the float array. This is a potentially slow operation, use with care. 974ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa * @param matrix the transformation matrix 975ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa * @param vertices the float array 976ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa * @param vertexSize the number of floats in each vertex 977ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa * @param offset the offset within a vertex to the texture location 978ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa * @param start the vertex to start with 9799433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet * @param count the amount of vertices to transform */ 9809433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet public static void transformUV (final Matrix3 matrix, final float[] vertices, int vertexSize, int offset, int start, int count) { 981ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa if (start < 0 || count < 1 || ((start + count) * vertexSize) > vertices.length) 9829433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet throw new IndexOutOfBoundsException("start = " + start + ", count = " + count + ", vertexSize = " + vertexSize 9839433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet + ", length = " + vertices.length); 9849433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet 985ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa final Vector2 tmp = new Vector2(); 9869433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet 987ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa int idx = offset + (start * vertexSize); 988ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa for (int i = 0; i < count; i++) { 9899433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet tmp.set(vertices[idx], vertices[idx + 1]).mul(matrix); 990ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa vertices[idx] = tmp.x; 9919433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet vertices[idx + 1] = tmp.y; 992ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa idx += vertexSize; 993ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa } 994ba5b19207d55f30c027b4a5ac3deb50d05bf8992Xoppa } 9959433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet 9968a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa /** Copies this mesh optionally removing duplicate vertices and/or reducing the amount of attributes. 9978a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa * @param isStatic whether the new mesh is static or not. Allows for internal optimizations. 9988a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa * @param removeDuplicates whether to remove duplicate vertices if possible. Only the vertices specified by usage are checked. 9998a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa * @param usage which attributes (if available) to copy 10009433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet * @return the copy of this mesh */ 10019433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet public Mesh copy (boolean isStatic, boolean removeDuplicates, final int[] usage) { 10028a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa // TODO move this to a copy constructor? 10038a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa // TODO duplicate the buffers without double copying the data if possible. 10048a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa // TODO perhaps move this code to JNI if it turns out being too slow. 10058a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa final int vertexSize = getVertexSize() / 4; 10068a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa int numVertices = getNumVertices(); 10078a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa float[] vertices = new float[numVertices * vertexSize]; 10088a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa getVertices(0, vertices.length, vertices); 10098a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa short[] checks = null; 10108a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa VertexAttribute[] attrs = null; 10118a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa int newVertexSize = 0; 10128a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa if (usage != null) { 10138a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa int size = 0; 10148a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa int as = 0; 10158a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa for (int i = 0; i < usage.length; i++) 10168a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa if (getVertexAttribute(usage[i]) != null) { 10178a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa size += getVertexAttribute(usage[i]).numComponents; 10188a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa as++; 10198a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa } 10208a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa if (size > 0) { 10218a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa attrs = new VertexAttribute[as]; 10228a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa checks = new short[size]; 10238a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa int idx = -1; 10248a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa int ai = -1; 10258a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa for (int i = 0; i < usage.length; i++) { 10268a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa VertexAttribute a = getVertexAttribute(usage[i]); 10279433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet if (a == null) continue; 10288a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa for (int j = 0; j < a.numComponents; j++) 10298a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa checks[++idx] = (short)(a.offset + j); 10308a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa attrs[++ai] = new VertexAttribute(a.usage, a.numComponents, a.alias); 10318a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa newVertexSize += a.numComponents; 10328a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa } 10338a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa } 10348a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa } 10358a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa if (checks == null) { 10368a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa checks = new short[vertexSize]; 10378a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa for (short i = 0; i < vertexSize; i++) 10388a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa checks[i] = i; 10398a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa newVertexSize = vertexSize; 10408a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa } 10419433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet 10428a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa int numIndices = getNumIndices(); 10439433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet short[] indices = null; 10448a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa if (numIndices > 0) { 10458a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa indices = new short[numIndices]; 10468a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa getIndices(indices); 10478a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa if (removeDuplicates || newVertexSize != vertexSize) { 10488a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa float[] tmp = new float[vertices.length]; 10498a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa int size = 0; 10508a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa for (int i = 0; i < numIndices; i++) { 10518a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa final int idx1 = indices[i] * vertexSize; 10528a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa short newIndex = -1; 10538a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa if (removeDuplicates) { 10548a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa for (short j = 0; j < size && newIndex < 0; j++) { 10559433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet final int idx2 = j * newVertexSize; 10568a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa boolean found = true; 10578a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa for (int k = 0; k < checks.length && found; k++) { 10589433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet if (tmp[idx2 + k] != vertices[idx1 + checks[k]]) found = false; 10598a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa } 10609433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet if (found) newIndex = j; 10618a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa } 10628a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa } 10638a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa if (newIndex > 0) 10648a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa indices[i] = newIndex; 10658a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa else { 10668a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa final int idx = size * newVertexSize; 10678a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa for (int j = 0; j < checks.length; j++) 10689433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet tmp[idx + j] = vertices[idx1 + checks[j]]; 10698a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa indices[i] = (short)size; 10708a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa size++; 10718a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa } 10728a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa } 10738a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa vertices = tmp; 10748a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa numVertices = size; 10758a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa } 10768a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa } 10779433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet 10788a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa Mesh result; 10798a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa if (attrs == null) 10808a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa result = new Mesh(isStatic, numVertices, indices == null ? 0 : indices.length, getVertexAttributes()); 10818a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa else 10828a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa result = new Mesh(isStatic, numVertices, indices == null ? 0 : indices.length, attrs); 10838a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa result.setVertices(vertices, 0, numVertices * newVertexSize); 10848a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa result.setIndices(indices); 10858a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa return result; 10868a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa } 10879433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet 10888a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa /** Copies this mesh. 10898a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa * @param isStatic whether the new mesh is static or not. Allows for internal optimizations. 10909433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet * @return the copy of this mesh */ 10919433d7435548a2583fa50137ea0dc9c424f8acd6NathanSweet public Mesh copy (boolean isStatic) { 10928a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa return copy(isStatic, false, null); 10938a78a4a9b44d8c24c8afd90945dbc2cb570226edXoppa } 1094114c5c91c13f74b04c08c0816d649da267bdcbbdbadlogicgames} 1095