/** * This method triangulates the faces if they are given as a polylist. Does nothing in case the * faces are given as triangles already. * * @param polyList */ private void triangulate(Element polyList) { if (!polyList.getName().equals("polylist")) return; Element colladaPolys = polyList.getChildByName("vcount"); if (colladaPolys == null) throw new GdxRuntimeException("<polylist> does not contain <vcount> element"); String[] tokens = colladaPolys.getText().split("\\s+"); int[] polys = new int[tokens.length]; int vertexCount = 0; for (int i = 0; i < tokens.length; i++) { int verts = Integer.parseInt(tokens[i]); polys[i] = verts; vertexCount += verts; } Array<VertexIndices> newVertices = new Array<VertexIndices>(vertexCount); int idx = 0; for (int i = 0; i < polys.length; i++) { int numVertices = polys[i]; VertexIndices baseVertex = triangles.get(idx++); for (int j = 1; j < numVertices - 1; j++) { newVertices.add(baseVertex); newVertices.add(triangles.get(idx)); newVertices.add(triangles.get(idx + 1)); idx++; } idx++; } triangles = newVertices; }
private VertexAttribute[] getVertexAttributes() { VertexAttribute[] attributes = new VertexAttribute[inputs.size]; int texUnit = 0; for (int i = 0; i < inputs.size; i++) { Element input = inputs.get(i); String semantic = input.getAttribute("semantic"); Source source = sourcesMap.get(input.getAttribute("source")); int usage = getVertexAttributeUsage(semantic); int components = source.components; String alias = getVertexAttributeAlias(semantic); if (alias.equals("a_tex")) alias += texUnit++; attributes[i] = new VertexAttribute(usage, components, alias); } return attributes; }
/** * Conditions the inputs for a triangles/polylist list of faces and generates unique vertices * while merging duplicate vertices. * * @param faces */ private void parseVertices(Element faces) { inputs = faces.getChildrenByName("input"); if (inputs == null) throw new GdxRuntimeException("no <input> elements in <triangles>/<polylist>"); int[] offsets = new int[inputs.size]; int stride = 0; // normalize source references, should use the URI/address scheme of Collada FIXME // calculate stride and prepare to untangle the index lists mess... sources = new Source[inputs.size]; for (int i = 0; i < inputs.size; i++) { Element input = inputs.get(i); // map source if it was defined in <vertices> tag String source = input.getAttribute("source").substring(1); if (mappings.containsKey(source)) { input.setAttribute("source", mappings.get(source)); } else { input.setAttribute("source", source); } // check whether source exists source = input.getAttribute("source"); if (!sourcesMap.containsKey(source)) throw new GdxRuntimeException("source '" + source + "' not in mesh> but in <triangle>"); sources[i] = sourcesMap.get(source); offsets[i] = Integer.parseInt(input.getAttribute("offset")); stride = Math.max(offsets[i], stride); } // addjust for zero source offsets stride += 1; // parse <p> indices, yeah, that takes up a bit more memory. String[] tokens = faces.getChildByName("p").getText().split("\\s+"); int[] indices = new int[tokens.length]; for (int i = 0; i < tokens.length; i++) { indices[i] = Integer.parseInt(tokens[i]); } // untangle indices on a per source basis Map<VertexIndices, VertexIndices> indicesSet = new HashMap<VertexIndices, VertexIndices>(); VertexIndices vertex = new VertexIndices(inputs.size); triangles = new Array<VertexIndices>(indices.length / stride); vertices = new Array<VertexIndices>(indices.length / stride); int index = 0; for (int i = 0; i < indices.length; i += stride) { for (int j = 0; j < inputs.size; j++) { vertex.indices[j] = indices[i + offsets[j]]; vertex.index = index; } VertexIndices lookup = indicesSet.get(vertex); if (lookup != null) { triangles.add(lookup); } else { triangles.add(vertex); vertices.add(vertex); indicesSet.put(vertex, vertex); vertex = new VertexIndices(inputs.size); index++; } } numVertices = index; }