Java tutorial
/** * Copyright (c) 2008-2012 Ardor Labs, Inc. * * This file is part of Ardor3D. * * Ardor3D is free software: you can redistribute it and/or modify it * under the terms of its license which may be found in the accompanying * LICENSE file or at <http://www.ardor3d.com/LICENSE>. */ package com.ardor3d.extension.model.collada.jdom; import java.nio.FloatBuffer; import java.util.Arrays; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import org.jdom2.Element; import com.ardor3d.extension.model.collada.jdom.data.DataCache; import com.ardor3d.scenegraph.FloatBufferData; import com.ardor3d.scenegraph.MeshData; import com.ardor3d.util.geom.BufferUtils; /** * The purpose of this class is to tie a <source> and accessor together to pull out data. */ public class ColladaInputPipe { private static final Logger logger = Logger.getLogger(ColladaInputPipe.class.getName()); private final int _offset; private final int _set; private final Element _source; private int _paramCount; private SourceData _sourceData = null; private Type _type; private FloatBuffer _buffer; private int _texCoord = 0; public enum Type { VERTEX, POSITION, NORMAL, TEXCOORD, COLOR, JOINT, WEIGHT, TEXTANGENT, TEXBINORMAL, // INV_BIND_MATRIX, INPUT, IN_TANGENT, OUT_TANGENT, OUTPUT, INTERPOLATION, UNKNOWN } static class SourceData { int count; int stride; int offset; ParamType paramType; float[] floatArray; boolean[] boolArray; int[] intArray; String[] stringArray; @Override public String toString() { switch (paramType) { case bool_param: return "SourceData [boolArray=" + Arrays.toString(boolArray) + "]"; case float_param: return "SourceData [floatArray=" + Arrays.toString(floatArray) + "]"; case idref_param: return "SourceData [idrefArray=" + Arrays.toString(stringArray) + "]"; case int_param: return "SourceData [intArray=" + Arrays.toString(intArray) + "]"; case name_param: return "SourceData [nameArray=" + Arrays.toString(stringArray) + "]"; default: return "Unknown paramType"; } } } public enum ParamType { float_param, bool_param, int_param, name_param, idref_param } @SuppressWarnings("unchecked") public ColladaInputPipe(final ColladaDOMUtil colladaDOMUtil, final Element input) { // Setup our type try { _type = Type.valueOf(input.getAttributeValue("semantic")); } catch (final Exception ex) { ColladaInputPipe.logger.warning("Unknown input type: " + input.getAttributeValue("semantic")); _type = Type.UNKNOWN; } // Locate our source final Element n = colladaDOMUtil.findTargetWithId(input.getAttributeValue("source")); if (n == null) { throw new ColladaException("Input source not found: " + input.getAttributeValue("source"), input); } if ("source".equals(n.getName())) { _source = n; } else if ("vertices".equals(n.getName())) { _source = colladaDOMUtil.getPositionSource(n); } else { throw new ColladaException("Input source not found: " + input.getAttributeValue("source"), input); } // TODO: Need to go through the params and see if they have a name set, and skip values if not when // parsing the array? _sourceData = new SourceData(); if (_source.getChild("float_array") != null) { _sourceData.floatArray = colladaDOMUtil.parseFloatArray(_source.getChild("float_array")); _sourceData.paramType = ParamType.float_param; } else if (_source.getChild("bool_array") != null) { _sourceData.boolArray = colladaDOMUtil.parseBooleanArray(_source.getChild("bool_array")); _sourceData.paramType = ParamType.bool_param; } else if (_source.getChild("int_array") != null) { _sourceData.intArray = colladaDOMUtil.parseIntArray(_source.getChild("int_array")); _sourceData.paramType = ParamType.int_param; } else if (_source.getChild("Name_array") != null) { _sourceData.stringArray = colladaDOMUtil.parseStringArray(_source.getChild("Name_array")); _sourceData.paramType = ParamType.name_param; } else if (_source.getChild("IDREF_array") != null) { _sourceData.stringArray = colladaDOMUtil.parseStringArray(_source.getChild("IDREF_array")); _sourceData.paramType = ParamType.idref_param; } // add a hook to our params from the technique_common final Element accessor = getCommonAccessor(_source); if (accessor != null) { if (ColladaInputPipe.logger.isLoggable(Level.FINE)) { ColladaInputPipe.logger.fine("Creating buffers for: " + _source.getAttributeValue("id")); } final List<Element> params = accessor.getChildren("param"); _paramCount = params.size(); // Might use this info for real later, but use for testing for unsupported param skipping. boolean skippedParam = false; for (final Element param : params) { final String paramName = param.getAttributeValue("name"); if (paramName == null) { skippedParam = true; break; } // String paramType = param.getAttributeValue("type"); } if (_paramCount > 1 && skippedParam) { ColladaInputPipe.logger.warning("Parameter skipping not yet supported when parsing sources. " + _source.getAttributeValue("id")); } _sourceData.count = colladaDOMUtil.getAttributeIntValue(accessor, "count", 0); _sourceData.stride = colladaDOMUtil.getAttributeIntValue(accessor, "stride", 1); _sourceData.offset = colladaDOMUtil.getAttributeIntValue(accessor, "offset", 0); } // save our offset _offset = colladaDOMUtil.getAttributeIntValue(input, "offset", 0); _set = colladaDOMUtil.getAttributeIntValue(input, "set", 0); _texCoord = 0; } public int getOffset() { return _offset; } public int getSet() { return _set; } public Type getType() { return _type; } public SourceData getSourceData() { return _sourceData; } public void setupBuffer(final int numEntries, final MeshData meshData, final DataCache cache) { // use our source and the number of params to determine our buffer length // we'll use the params from the common technique accessor: final int size = _paramCount * numEntries; switch (_type) { case POSITION: _buffer = BufferUtils.createFloatBuffer(size); meshData.setVertexCoords(new FloatBufferData(_buffer, _paramCount)); break; case NORMAL: _buffer = BufferUtils.createFloatBuffer(size); meshData.setNormalCoords(new FloatBufferData(_buffer, _paramCount)); break; case TEXCOORD: _buffer = BufferUtils.createFloatBuffer(size); meshData.setTextureCoords(new FloatBufferData(_buffer, _paramCount), _texCoord); break; case COLOR: _buffer = BufferUtils.createFloatBuffer(size); meshData.setColorCoords(new FloatBufferData(_buffer, _paramCount)); cache.getParsedVertexColors().put(meshData, _buffer); break; case TEXTANGENT: _buffer = BufferUtils.createFloatBuffer(size); meshData.setTangentCoords(new FloatBufferData(_buffer, _paramCount)); break; // case TEXBINORMAL: // _buffer = BufferUtils.createFloatBuffer(size); // meshData.setTangentBuffer(_buffer); // break; default: } } void pushValues(final int memberIndex) { if (_buffer == null) { return; } if (_sourceData == null) { throw new ColladaException("No source data found in pipe!", _source); } if (memberIndex >= _sourceData.count) { ColladaInputPipe.logger.warning("Accessed invalid index " + memberIndex + " on source " + _source + ". Count: " + _sourceData.count); return; } int index = memberIndex * _sourceData.stride + _sourceData.offset; final ParamType paramType = _sourceData.paramType; for (int i = 0; i < _paramCount; i++) { if (ParamType.float_param == paramType) { _buffer.put(_sourceData.floatArray[index]); } else if (ParamType.int_param == paramType) { _buffer.put(_sourceData.intArray[index]); } index++; } } public void setTexCoord(final int texCoord) { _texCoord = texCoord; } private Element getCommonAccessor(final Element source) { final Element techniqueCommon = source.getChild("technique_common"); if (techniqueCommon != null) { return techniqueCommon.getChild("accessor"); } return null; } }