Package com.ardor3d.extension.model.obj

Source Code of com.ardor3d.extension.model.obj.ObjGeometryStore

/**
* 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.obj;

import java.nio.Buffer;
import java.nio.FloatBuffer;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;

import com.ardor3d.math.Vector2;
import com.ardor3d.math.Vector3;
import com.ardor3d.renderer.queue.RenderBucketType;
import com.ardor3d.renderer.state.BlendState;
import com.ardor3d.renderer.state.MaterialState;
import com.ardor3d.renderer.state.TextureState;
import com.ardor3d.scenegraph.IndexBufferData;
import com.ardor3d.scenegraph.Line;
import com.ardor3d.scenegraph.Mesh;
import com.ardor3d.scenegraph.Node;
import com.ardor3d.scenegraph.Point;
import com.ardor3d.scenegraph.Spatial;
import com.ardor3d.scenegraph.hint.LightCombineMode;
import com.ardor3d.util.geom.BufferUtils;
import com.ardor3d.util.geom.GeometryTool;
import com.ardor3d.util.geom.GeometryTool.MatchCondition;
import com.ardor3d.util.geom.VertGroupData;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

public class ObjGeometryStore {
    private static final String DEFAULT_GROUP = "_default_";

    private final ObjDataStore _dataStore = new ObjDataStore();

    private int _totalPoints = 0;
    private int _totalLines = 0;
    private int _totalMeshes = 0;
    private final Node _root = new Node();
    private final Map<String, Spatial> _groupMap = Maps.newHashMap();

    private ObjMaterial _currentMaterial = new ObjMaterial("default");
    private String _currentObjectName;
    private String[] _currentGroupNames;

    private ObjSetManager _meshManager;
    private ObjSetManager _lineManager;
    private ObjSetManager _pointManager;

    private final Map<String, ObjMaterial> materialLibrary = Maps.newHashMap();
    private final Map<Spatial, String> _materialMap = Maps.newHashMap();

    public Map<String, ObjMaterial> getMaterialLibrary() {
        return materialLibrary;
    }

    public ObjDataStore getDataStore() {
        return _dataStore;
    }

    public Node getScene() {
        return _root;
    }

    void addFace(final List<ObjIndexSet> indices) {
        if (_meshManager == null) {
            _meshManager = new ObjSetManager();
        }

        // Build a fan of triangles
        final ObjIndexSet first = indices.get(0);
        final int firstIndex = _meshManager.findSet(first);
        ObjIndexSet second = indices.get(1);
        int secondIndex = _meshManager.findSet(second);
        for (int i = 2; i < indices.size(); i++) {
            final ObjIndexSet third = indices.get(i);
            final int thirdIndex = _meshManager.findSet(third);
            _meshManager.addIndex(firstIndex);
            _meshManager.addIndex(secondIndex);
            _meshManager.addIndex(thirdIndex);
            if (first.getVnIndex() == -1 || second.getVnIndex() == -1 || third.getVnIndex() == -1) {
                // Generate flat face normal.
                final Vector3 v = new Vector3(_dataStore.getVertices().get(second.getVIndex()));
                final Vector3 w = new Vector3(_dataStore.getVertices().get(third.getVIndex()));
                v.subtractLocal(_dataStore.getVertices().get(first.getVIndex()));
                w.subtractLocal(_dataStore.getVertices().get(first.getVIndex()));
                v.crossLocal(w);
                v.normalizeLocal();
                _dataStore.getGeneratedNormals().add(v);
                final int genIndex = -1 * (_dataStore.getGeneratedNormals().size() - 1) - 2;
                if (first.getVnIndex() == -1) {
                    first.setVnIndex(genIndex);
                }
                if (second.getVnIndex() == -1) {
                    second.setVnIndex(genIndex);
                }
                if (third.getVnIndex() == -1) {
                    third.setVnIndex(genIndex);
                }
            }
            second = third;
            secondIndex = thirdIndex;
        }
    }

    void addLine(final List<ObjIndexSet> indices) {
        if (_lineManager == null) {
            _lineManager = new ObjSetManager();
        }

        // Build a single long line
        for (int i = 0; i < indices.size(); i++) {
            final ObjIndexSet point = indices.get(i);
            final int index = _lineManager.findSet(point);
            _lineManager.addIndex(index);
        }

        _lineManager.addLength(indices.size());
    }

    void addPoints(final List<ObjIndexSet> indices) {
        if (_pointManager == null) {
            _pointManager = new ObjSetManager();
        }

        // Add points
        for (int i = 0; i < indices.size(); i++) {
            final ObjIndexSet point = indices.get(i);
            final int index = _pointManager.findSet(point);
            _pointManager.addIndex(index);
        }
    }

    void setCurrentGroupNames(final String[] names) {
        commitObjects();
        _currentGroupNames = names;
    }

    void setCurrentObjectName(final String name) {
        commitObjects();
        _currentObjectName = name;
    }

    void setCurrentMaterial(final ObjMaterial material) {
        if (material != null) {
            commitObjects();
            _currentMaterial = material;
        }
    }

    void cleanup() {
        _currentGroupNames = null;
        _currentMaterial = null;
        _currentObjectName = null;

        _meshManager = null;
        _lineManager = null;
        _pointManager = null;
    }

    void commitObjects() {
        // go through each manager, if not null, turn into a scenegraph object and attach to root.
        if (_pointManager != null) {
            String name = _currentObjectName;
            if (name == null) {
                name = "obj_points" + _totalPoints;
            }

            final Vector3[] vertices = new Vector3[_pointManager.getStore().size()];
            int i = 0;
            for (final ObjIndexSet set : _pointManager.getStore().keySet()) {
                vertices[i++] = _dataStore.getVertices().get(set.getVIndex());
            }

            final Point points = new Point(name, vertices, null, null, null);
            final IndexBufferData<? extends Buffer> indexBuffer = BufferUtils.createIndexBufferData(_pointManager
                    .getIndices().size(), vertices.length - 1);
            for (final int index : _pointManager.getIndices()) {
                indexBuffer.put(index);
            }
            points.getMeshData().setIndices(indexBuffer);

            GeometryTool.minimizeVerts(points, EnumSet.noneOf(MatchCondition.class));

            applyCurrentMaterial(points);
            mapToGroups(points);

            points.updateModelBound();

            _root.attachChild(points);
            _pointManager = null;
            _totalPoints++;
        }

        if (_lineManager != null) {
            String name = _currentObjectName;
            if (name == null) {
                name = "obj_lines" + _totalLines;
            }

            final Vector3[] vertices = new Vector3[_lineManager.getStore().size()];
            final Vector2[] uvs = new Vector2[vertices.length];
            boolean hasUVs = false;
            int i = 0;
            for (final ObjIndexSet set : _lineManager.getStore().keySet()) {
                vertices[i] = _dataStore.getVertices().get(set.getVIndex());
                if (set.getVtIndex() >= 0) {
                    final Vector3 uv = _dataStore.getUvs().get(set.getVtIndex());
                    // our line only supports 2d uvs
                    uvs[i] = new Vector2(uv.getX(), uv.getY());
                    hasUVs = true;
                }
                i++;
            }

            final Line line = new Line(name, vertices, null, null, hasUVs ? uvs : null);
            final IndexBufferData<? extends Buffer> indexBuffer = BufferUtils.createIndexBufferData(_lineManager
                    .getIndices().size(), vertices.length - 1);
            for (final int index : _lineManager.getIndices()) {
                indexBuffer.put(index);
            }
            line.getMeshData().setIndices(indexBuffer);
            if (_lineManager.getLengths().size() > 1) {
                final int[] lengths = new int[_lineManager.getLengths().size()];
                i = 0;
                for (final int l : _lineManager.getLengths()) {
                    lengths[i++] = l;
                }
                line.getMeshData().setIndexLengths(lengths);
            }
            GeometryTool.minimizeVerts(line, EnumSet.of(MatchCondition.UVs));

            applyCurrentMaterial(line);
            mapToGroups(line);

            line.updateModelBound();

            _root.attachChild(line);
            _lineManager = null;
            _totalLines++;
        }

        if (_meshManager != null) {
            String name = _currentObjectName;
            if (name == null) {
                name = "obj_mesh" + _totalMeshes;
            }

            final Mesh mesh = new Mesh(name);

            final FloatBuffer vertices = BufferUtils.createVector3Buffer(_meshManager.getStore().size());
            final FloatBuffer normals = BufferUtils.createFloatBuffer(vertices.capacity());
            final FloatBuffer uvs = BufferUtils.createFloatBuffer(vertices.capacity());
            boolean hasNormals = false, hasUVs = false;

            int j = 0;
            final long[] vertGroups = new long[_meshManager.getStore().size()];
            final List<Long> groups = Lists.newArrayList();
            Vector3 vector;
            for (final ObjIndexSet set : _meshManager.getStore().keySet()) {
                vertGroups[j] = set.getSmoothGroup();
                if (!groups.contains(set.getSmoothGroup())) {
                    groups.add(set.getSmoothGroup());
                }
                vector = _dataStore.getVertices().get(set.getVIndex());
                vertices.put(vector.getXf()).put(vector.getYf()).put(vector.getZf());
                if (set.getVnIndex() >= 0) {
                    vector = _dataStore.getNormals().get(set.getVnIndex());
                    normals.put(vector.getXf()).put(vector.getYf()).put(vector.getZf());
                    hasNormals = true;
                } else if (set.getVnIndex() < -1) {
                    vector = _dataStore.getGeneratedNormals().get(-1 * set.getVnIndex() - 2);
                    normals.put(vector.getXf()).put(vector.getYf()).put(vector.getZf());
                    hasNormals = true;
                }
                if (set.getVtIndex() >= 0) {
                    vector = _dataStore.getUvs().get(set.getVtIndex());
                    // TODO: add 3d tex support?
                    uvs.put(vector.getXf()).put(vector.getYf());
                    hasUVs = true;
                }
                j++;
            }

            mesh.getMeshData().setVertexBuffer(vertices);
            if (hasNormals) {
                mesh.getMeshData().setNormalBuffer(normals);
            }
            if (hasUVs) {
                mesh.getMeshData().setTextureBuffer(uvs, 0);
            }

            final IndexBufferData<? extends Buffer> indexBuffer = BufferUtils.createIndexBufferData(_meshManager
                    .getIndices().size(), _meshManager.getStore().size() - 1);
            for (final int index : _meshManager.getIndices()) {
                indexBuffer.put(index);
            }
            mesh.getMeshData().setIndices(indexBuffer);

            final VertGroupData groupData = new VertGroupData();
            // set all smooth groups to use "blend as long as UVs and SmoothGroup are same".
            for (final long group : groups) {
                groupData.setGroupConditions(group, EnumSet.of(MatchCondition.UVs));
            }
            // set the "no smooth" smooth group to use "blend only if vertex is same". (No color data in obj, so
            // ignoring)
            groupData.setVertGroups(vertGroups);
            groupData.setGroupConditions(VertGroupData.DEFAULT_GROUP,
                    EnumSet.of(MatchCondition.Normal, MatchCondition.UVs));
            GeometryTool.minimizeVerts(mesh, groupData);

            applyCurrentMaterial(mesh);
            mapToGroups(mesh);

            mesh.updateModelBound();

            _root.attachChild(mesh);
            _meshManager = null;
            _totalMeshes++;
        }
    }

    private void applyCurrentMaterial(final Spatial target) {
        final MaterialState material = _currentMaterial.getMaterialState();
        if (material != null) {
            target.setRenderState(material);
        }

        final TextureState tState = _currentMaterial.getTextureState();
        if (tState != null) {
            target.setRenderState(tState);
        }

        final BlendState blend = _currentMaterial.getBlendState();
        if (blend != null) {
            target.setRenderState(blend);
            target.getSceneHints().setRenderBucketType(RenderBucketType.Transparent);
        }

        if (_currentMaterial.illumType == 0) {
            target.getSceneHints().setLightCombineMode(LightCombineMode.Off);
        }

        _materialMap.put(target, _currentMaterial.getName());
    }

    private void mapToGroups(final Spatial target) {
        if (_currentGroupNames != null) {
            for (final String groupName : _currentGroupNames) {
                _groupMap.put(groupName, target);
            }
        } else {
            _groupMap.put(ObjGeometryStore.DEFAULT_GROUP, target);
        }

    }

    public Map<Spatial, String> getMaterialMap() {
        return _materialMap;
    }
}
TOP

Related Classes of com.ardor3d.extension.model.obj.ObjGeometryStore

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.