Search in sources :

Example 51 with Type

use of com.jme3.scene.VertexBuffer.Type in project jmonkeyengine by jMonkeyEngine.

the class ObjectHelper method toObject.

/**
     * This method reads the given structure and createn an object that
     * represents the data.
     * 
     * @param objectStructure
     *            the object's structure
     * @param blenderContext
     *            the blender context
     * @return blener's object representation or null if its type is excluded from loading
     * @throws BlenderFileException
     *             an exception is thrown when the given data is inapropriate
     */
public Object toObject(Structure objectStructure, BlenderContext blenderContext) throws BlenderFileException {
    Object loadedResult = blenderContext.getLoadedFeature(objectStructure.getOldMemoryAddress(), LoadedDataType.FEATURE);
    if (loadedResult != null) {
        return loadedResult;
    }
    LOGGER.fine("Loading blender object.");
    if ("ID".equals(objectStructure.getType())) {
        Node object = (Node) this.loadLibrary(objectStructure);
        if (object.getParent() != null) {
            LOGGER.log(Level.FINEST, "Detaching object {0}, loaded from external file, from its parent.", object);
            object.getParent().detachChild(object);
        }
        return object;
    }
    int type = ((Number) objectStructure.getFieldValue("type")).intValue();
    ObjectType objectType = ObjectType.valueOf(type);
    LOGGER.log(Level.FINE, "Type of the object: {0}.", objectType);
    int lay = ((Number) objectStructure.getFieldValue("lay")).intValue();
    if ((lay & blenderContext.getBlenderKey().getLayersToLoad()) == 0) {
        LOGGER.fine("The layer this object is located in is not included in loading.");
        return null;
    }
    blenderContext.pushParent(objectStructure);
    String name = objectStructure.getName();
    LOGGER.log(Level.FINE, "Loading obejct: {0}", name);
    int restrictflag = ((Number) objectStructure.getFieldValue("restrictflag")).intValue();
    boolean visible = (restrictflag & 0x01) != 0;
    Pointer pParent = (Pointer) objectStructure.getFieldValue("parent");
    Object parent = blenderContext.getLoadedFeature(pParent.getOldMemoryAddress(), LoadedDataType.FEATURE);
    if (parent == null && pParent.isNotNull()) {
        Structure parentStructure = pParent.fetchData().get(0);
        parent = this.toObject(parentStructure, blenderContext);
    }
    Transform t = this.getTransformation(objectStructure, blenderContext);
    LOGGER.log(Level.FINE, "Importing object of type: {0}", objectType);
    Node result = null;
    try {
        switch(objectType) {
            case LATTICE:
            case METABALL:
            case TEXT:
            case WAVE:
                LOGGER.log(Level.WARNING, "{0} type is not supported but the node will be returned in order to keep parent - child relationship.", objectType);
            case EMPTY:
            case ARMATURE:
                // need to use an empty node to properly create
                // parent-children relationships between nodes
                result = new Node(name);
                break;
            case MESH:
                result = new Node(name);
                MeshHelper meshHelper = blenderContext.getHelper(MeshHelper.class);
                Pointer pMesh = (Pointer) objectStructure.getFieldValue("data");
                List<Structure> meshesArray = pMesh.fetchData();
                TemporalMesh temporalMesh = meshHelper.toTemporalMesh(meshesArray.get(0), blenderContext);
                if (temporalMesh != null) {
                    result.attachChild(temporalMesh);
                }
                break;
            case SURF:
            case CURVE:
                result = new Node(name);
                Pointer pCurve = (Pointer) objectStructure.getFieldValue("data");
                if (pCurve.isNotNull()) {
                    CurvesHelper curvesHelper = blenderContext.getHelper(CurvesHelper.class);
                    Structure curveData = pCurve.fetchData().get(0);
                    TemporalMesh curvesTemporalMesh = curvesHelper.toCurve(curveData, blenderContext);
                    if (curvesTemporalMesh != null) {
                        result.attachChild(curvesTemporalMesh);
                    }
                }
                break;
            case LAMP:
                Pointer pLamp = (Pointer) objectStructure.getFieldValue("data");
                if (pLamp.isNotNull()) {
                    LightHelper lightHelper = blenderContext.getHelper(LightHelper.class);
                    List<Structure> lampsArray = pLamp.fetchData();
                    Light light = lightHelper.toLight(lampsArray.get(0), blenderContext);
                    if (light == null) {
                        // probably some light type is not supported, just create a node so that we can maintain child-parent relationship for nodes
                        result = new Node(name);
                    } else {
                        result = new LightNode(name, light);
                    }
                }
                break;
            case CAMERA:
                Pointer pCamera = (Pointer) objectStructure.getFieldValue("data");
                if (pCamera.isNotNull()) {
                    CameraHelper cameraHelper = blenderContext.getHelper(CameraHelper.class);
                    List<Structure> camerasArray = pCamera.fetchData();
                    Camera camera = cameraHelper.toCamera(camerasArray.get(0), blenderContext);
                    if (camera == null) {
                        // just create a node so that we can maintain child-parent relationship for nodes
                        result = new Node(name);
                    } else {
                        result = new CameraNode(name, camera);
                    }
                }
                break;
            default:
                LOGGER.log(Level.WARNING, "Unsupported object type: {0}", type);
        }
        if (result != null) {
            LOGGER.fine("Storing loaded feature in blender context and applying markers (those will be removed before the final result is released).");
            Long oma = objectStructure.getOldMemoryAddress();
            blenderContext.addLoadedFeatures(oma, LoadedDataType.STRUCTURE, objectStructure);
            blenderContext.addLoadedFeatures(oma, LoadedDataType.FEATURE, result);
            blenderContext.addMarker(OMA_MARKER, result, objectStructure.getOldMemoryAddress());
            if (objectType == ObjectType.ARMATURE) {
                blenderContext.addMarker(ARMATURE_NODE_MARKER, result, Boolean.TRUE);
            }
            result.setLocalTransform(t);
            result.setCullHint(visible ? CullHint.Always : CullHint.Inherit);
            if (parent instanceof Node) {
                ((Node) parent).attachChild(result);
            }
            LOGGER.fine("Reading and applying object's modifiers.");
            ModifierHelper modifierHelper = blenderContext.getHelper(ModifierHelper.class);
            Collection<Modifier> modifiers = modifierHelper.readModifiers(objectStructure, blenderContext);
            for (Modifier modifier : modifiers) {
                modifier.apply(result, blenderContext);
            }
            if (result.getChildren() != null && result.getChildren().size() > 0) {
                if (result.getChildren().size() == 1 && result.getChild(0) instanceof TemporalMesh) {
                    LOGGER.fine("Converting temporal mesh into jme geometries.");
                    ((TemporalMesh) result.getChild(0)).toGeometries();
                }
                LOGGER.fine("Applying proper scale to the geometries.");
                for (Spatial child : result.getChildren()) {
                    if (child instanceof Geometry) {
                        this.flipMeshIfRequired((Geometry) child, child.getWorldScale());
                    }
                }
            }
            // I prefer do compute bounding box here than read it from the file
            result.updateModelBound();
            LOGGER.fine("Applying animations to the object if such are defined.");
            AnimationHelper animationHelper = blenderContext.getHelper(AnimationHelper.class);
            animationHelper.applyAnimations(result, blenderContext.getBlenderKey().getAnimationMatchMethod());
            LOGGER.fine("Loading constraints connected with this object.");
            ConstraintHelper constraintHelper = blenderContext.getHelper(ConstraintHelper.class);
            constraintHelper.loadConstraints(objectStructure, blenderContext);
            LOGGER.fine("Loading custom properties.");
            if (blenderContext.getBlenderKey().isLoadObjectProperties()) {
                Properties properties = this.loadProperties(objectStructure, blenderContext);
                // each value and set it to Spatial
                if (properties != null && properties.getValue() != null) {
                    this.applyProperties(result, properties);
                }
            }
        }
    } finally {
        blenderContext.popParent();
    }
    return result;
}
Also used : LightNode(com.jme3.scene.LightNode) Node(com.jme3.scene.Node) CameraNode(com.jme3.scene.CameraNode) CameraNode(com.jme3.scene.CameraNode) Pointer(com.jme3.scene.plugins.blender.file.Pointer) ModifierHelper(com.jme3.scene.plugins.blender.modifiers.ModifierHelper) LightNode(com.jme3.scene.LightNode) Light(com.jme3.light.Light) Camera(com.jme3.renderer.Camera) Structure(com.jme3.scene.plugins.blender.file.Structure) Modifier(com.jme3.scene.plugins.blender.modifiers.Modifier) CameraHelper(com.jme3.scene.plugins.blender.cameras.CameraHelper) AnimationHelper(com.jme3.scene.plugins.blender.animations.AnimationHelper) ConstraintHelper(com.jme3.scene.plugins.blender.constraints.ConstraintHelper) CullHint(com.jme3.scene.Spatial.CullHint) TemporalMesh(com.jme3.scene.plugins.blender.meshes.TemporalMesh) Geometry(com.jme3.scene.Geometry) Spatial(com.jme3.scene.Spatial) CurvesHelper(com.jme3.scene.plugins.blender.curves.CurvesHelper) Transform(com.jme3.math.Transform) LightHelper(com.jme3.scene.plugins.blender.lights.LightHelper) MeshHelper(com.jme3.scene.plugins.blender.meshes.MeshHelper)

Example 52 with Type

use of com.jme3.scene.VertexBuffer.Type in project jmonkeyengine by jMonkeyEngine.

the class Properties method load.

/**
     * This method loads the property from the belnder file.
     * @param idPropertyStructure
     *            the ID structure constining the property
     * @param blenderContext
     *            the blender context
     * @throws BlenderFileException
     *             an exception is thrown when the belnder file is somehow invalid
     */
public void load(Structure idPropertyStructure, BlenderContext blenderContext) throws BlenderFileException {
    name = idPropertyStructure.getFieldValue("name").toString();
    if (name == null || name.length() == 0) {
        name = DEFAULT_NAME;
    }
    subType = ((Number) idPropertyStructure.getFieldValue("subtype")).intValue();
    type = ((Number) idPropertyStructure.getFieldValue("type")).intValue();
    // reading the data
    Structure data = (Structure) idPropertyStructure.getFieldValue("data");
    int len = ((Number) idPropertyStructure.getFieldValue("len")).intValue();
    switch(type) {
        case IDP_STRING:
            {
                Pointer pointer = (Pointer) data.getFieldValue("pointer");
                BlenderInputStream bis = blenderContext.getInputStream();
                FileBlockHeader dataFileBlock = blenderContext.getFileBlock(pointer.getOldMemoryAddress());
                bis.setPosition(dataFileBlock.getBlockPosition());
                value = bis.readString();
                break;
            }
        case IDP_INT:
            int intValue = ((Number) data.getFieldValue("val")).intValue();
            value = Integer.valueOf(intValue);
            break;
        case IDP_FLOAT:
            int floatValue = ((Number) data.getFieldValue("val")).intValue();
            value = Float.valueOf(Float.intBitsToFloat(floatValue));
            break;
        case IDP_ARRAY:
            {
                Pointer pointer = (Pointer) data.getFieldValue("pointer");
                BlenderInputStream bis = blenderContext.getInputStream();
                FileBlockHeader dataFileBlock = blenderContext.getFileBlock(pointer.getOldMemoryAddress());
                bis.setPosition(dataFileBlock.getBlockPosition());
                int elementAmount = dataFileBlock.getSize();
                switch(subType) {
                    case IDP_INT:
                        elementAmount /= 4;
                        int[] intList = new int[elementAmount];
                        for (int i = 0; i < elementAmount; ++i) {
                            intList[i] = bis.readInt();
                        }
                        value = intList;
                        break;
                    case IDP_FLOAT:
                        elementAmount /= 4;
                        float[] floatList = new float[elementAmount];
                        for (int i = 0; i < elementAmount; ++i) {
                            floatList[i] = bis.readFloat();
                        }
                        value = floatList;
                        break;
                    case IDP_DOUBLE:
                        elementAmount /= 8;
                        double[] doubleList = new double[elementAmount];
                        for (int i = 0; i < elementAmount; ++i) {
                            doubleList[i] = bis.readDouble();
                        }
                        value = doubleList;
                        break;
                    default:
                        throw new IllegalStateException("Invalid array subtype: " + subType);
                }
            }
        case IDP_GROUP:
            Structure group = (Structure) data.getFieldValue("group");
            List<Structure> dataList = group.evaluateListBase();
            List<Properties> subProperties = new ArrayList<Properties>(len);
            for (Structure d : dataList) {
                Properties properties = new Properties();
                properties.load(d, blenderContext);
                subProperties.add(properties);
            }
            value = subProperties;
            break;
        case IDP_DOUBLE:
            int doublePart1 = ((Number) data.getFieldValue("val")).intValue();
            int doublePart2 = ((Number) data.getFieldValue("val2")).intValue();
            long doubleVal = (long) doublePart2 << 32 | doublePart1;
            value = Double.valueOf(Double.longBitsToDouble(doubleVal));
            break;
        case IDP_IDPARRAY:
            {
                Pointer pointer = (Pointer) data.getFieldValue("pointer");
                List<Structure> arrays = pointer.fetchData();
                List<Object> result = new ArrayList<Object>(arrays.size());
                Properties temp = new Properties();
                for (Structure array : arrays) {
                    temp.load(array, blenderContext);
                    result.add(temp.value);
                }
                value = result;
                break;
            }
        case IDP_NUMTYPES:
            throw new UnsupportedOperationException();
        // return null;
        default:
            throw new IllegalStateException("Unknown custom property type: " + type);
    }
    this.completeLoading();
}
Also used : FileBlockHeader(com.jme3.scene.plugins.blender.file.FileBlockHeader) ArrayList(java.util.ArrayList) Pointer(com.jme3.scene.plugins.blender.file.Pointer) BlenderInputStream(com.jme3.scene.plugins.blender.file.BlenderInputStream) List(java.util.List) ArrayList(java.util.ArrayList) Structure(com.jme3.scene.plugins.blender.file.Structure)

Example 53 with Type

use of com.jme3.scene.VertexBuffer.Type in project jmonkeyengine by jMonkeyEngine.

the class CombinedTexture method flatten.

/**
	 * This method flattens the texture and creates a single result of Texture2D
	 * type.
	 * 
	 * @param geometry
	 *            the geometry the texture is created for
	 * @param geometriesOMA
	 *            the old memory address of the geometries list that the given
	 *            geometry belongs to (needed for bounding box creation)
	 * @param userDefinedUVCoordinates
	 *            the UV's defined by user (null or zero length table if none
	 *            were defined)
	 * @param blenderContext
	 *            the blender context
	 * @return the name of the user UV coordinates used (null if the UV's were
	 *         generated)
	 */
public String flatten(Geometry geometry, Long geometriesOMA, Map<String, List<Vector2f>> userDefinedUVCoordinates, BlenderContext blenderContext) {
    Mesh mesh = geometry.getMesh();
    Texture previousTexture = null;
    UVCoordinatesType masterUVCoordinatesType = null;
    String masterUserUVSetName = null;
    for (TextureData textureData : textureDatas) {
        // decompress compressed textures (all will be merged into one texture anyway)
        if (textureDatas.size() > 1 && textureData.texture.getImage().getFormat().isCompressed()) {
            textureData.texture.setImage(ImageUtils.decompress(textureData.texture.getImage()));
            textureData.textureBlender = TextureBlenderFactory.alterTextureType(textureData.texture.getImage().getFormat(), textureData.textureBlender);
        }
        if (previousTexture == null) {
            // the first texture will lead the others to its shape
            if (textureData.texture instanceof GeneratedTexture) {
                resultTexture = ((GeneratedTexture) textureData.texture).triangulate(mesh, geometriesOMA, textureData.uvCoordinatesType, blenderContext);
            } else if (textureData.texture instanceof Texture2D) {
                resultTexture = textureData.texture;
                if (textureData.uvCoordinatesType == UVCoordinatesType.TEXCO_UV && userDefinedUVCoordinates != null && userDefinedUVCoordinates.size() > 0) {
                    if (textureData.uvCoordinatesName == null) {
                        // get the first UV available
                        resultUVS = userDefinedUVCoordinates.values().iterator().next();
                    } else {
                        resultUVS = userDefinedUVCoordinates.get(textureData.uvCoordinatesName);
                    }
                    if (resultUVS == null && LOGGER.isLoggable(Level.WARNING)) {
                        LOGGER.warning("The texture " + textureData.texture.getName() + " has assigned non existing UV coordinates group: " + textureData.uvCoordinatesName + ".");
                    }
                    masterUserUVSetName = textureData.uvCoordinatesName;
                } else {
                    TemporalMesh temporalMesh = (TemporalMesh) blenderContext.getLoadedFeature(geometriesOMA, LoadedDataType.TEMPORAL_MESH);
                    resultUVS = UVCoordinatesGenerator.generateUVCoordinatesFor2DTexture(mesh, textureData.uvCoordinatesType, textureData.projectionType, temporalMesh);
                }
            }
            this.blend(resultTexture, textureData.textureBlender, blenderContext);
            previousTexture = resultTexture;
            masterUVCoordinatesType = textureData.uvCoordinatesType;
        } else {
            if (textureData.texture instanceof GeneratedTexture) {
                if (!(resultTexture instanceof TriangulatedTexture)) {
                    resultTexture = new TriangulatedTexture((Texture2D) resultTexture, resultUVS, blenderContext);
                    resultUVS = null;
                    previousTexture = resultTexture;
                }
                TriangulatedTexture triangulatedTexture = ((GeneratedTexture) textureData.texture).triangulate(mesh, geometriesOMA, textureData.uvCoordinatesType, blenderContext);
                triangulatedTexture.castToUVS((TriangulatedTexture) resultTexture, blenderContext);
                triangulatedTexture.blend(textureData.textureBlender, (TriangulatedTexture) resultTexture, blenderContext);
                resultTexture = previousTexture = triangulatedTexture;
            } else if (textureData.texture instanceof Texture2D) {
                if (this.isUVTypesMatch(masterUVCoordinatesType, masterUserUVSetName, textureData.uvCoordinatesType, textureData.uvCoordinatesName) && resultTexture instanceof Texture2D) {
                    this.scale((Texture2D) textureData.texture, resultTexture.getImage().getWidth(), resultTexture.getImage().getHeight());
                    ImageUtils.merge(resultTexture.getImage(), textureData.texture.getImage());
                    previousTexture = resultTexture;
                } else {
                    if (!(resultTexture instanceof TriangulatedTexture)) {
                        resultTexture = new TriangulatedTexture((Texture2D) resultTexture, resultUVS, blenderContext);
                        resultUVS = null;
                    }
                    // first triangulate the current texture
                    List<Vector2f> textureUVS = null;
                    if (textureData.uvCoordinatesType == UVCoordinatesType.TEXCO_UV && userDefinedUVCoordinates != null && userDefinedUVCoordinates.size() > 0) {
                        if (textureData.uvCoordinatesName == null) {
                            // get the first UV available
                            textureUVS = userDefinedUVCoordinates.values().iterator().next();
                        } else {
                            textureUVS = userDefinedUVCoordinates.get(textureData.uvCoordinatesName);
                        }
                    } else {
                        TemporalMesh geometries = (TemporalMesh) blenderContext.getLoadedFeature(geometriesOMA, LoadedDataType.TEMPORAL_MESH);
                        textureUVS = UVCoordinatesGenerator.generateUVCoordinatesFor2DTexture(mesh, textureData.uvCoordinatesType, textureData.projectionType, geometries);
                    }
                    TriangulatedTexture triangulatedTexture = new TriangulatedTexture((Texture2D) textureData.texture, textureUVS, blenderContext);
                    // then move the texture to different UV's
                    triangulatedTexture.castToUVS((TriangulatedTexture) resultTexture, blenderContext);
                    // merge triangulated textures
                    for (int i = 0; i < ((TriangulatedTexture) resultTexture).getFaceTextureCount(); ++i) {
                        ImageUtils.merge(((TriangulatedTexture) resultTexture).getFaceTextureElement(i).image, triangulatedTexture.getFaceTextureElement(i).image);
                    }
                }
            }
        }
    }
    if (resultTexture instanceof TriangulatedTexture) {
        if (mappingType == MaterialContext.MTEX_NOR) {
            for (int i = 0; i < ((TriangulatedTexture) resultTexture).getFaceTextureCount(); ++i) {
                TriangleTextureElement triangleTextureElement = ((TriangulatedTexture) resultTexture).getFaceTextureElement(i);
                // TODO: get proper strength factor
                triangleTextureElement.image = ImageUtils.convertToNormalMapTexture(triangleTextureElement.image, 1);
            }
        }
        resultUVS = ((TriangulatedTexture) resultTexture).getResultUVS();
        resultTexture = ((TriangulatedTexture) resultTexture).getResultTexture();
        masterUserUVSetName = null;
    }
    // setting additional data
    resultTexture.setWrap(WrapMode.Repeat);
    // the filters are required if generated textures are used because
    // otherwise ugly lines appear between the mesh faces
    resultTexture.setMagFilter(MagFilter.Nearest);
    resultTexture.setMinFilter(MinFilter.NearestNoMipMaps);
    return masterUserUVSetName;
}
Also used : TemporalMesh(com.jme3.scene.plugins.blender.meshes.TemporalMesh) Texture2D(com.jme3.texture.Texture2D) TriangleTextureElement(com.jme3.scene.plugins.blender.textures.TriangulatedTexture.TriangleTextureElement) UVCoordinatesType(com.jme3.scene.plugins.blender.textures.UVCoordinatesGenerator.UVCoordinatesType) TemporalMesh(com.jme3.scene.plugins.blender.meshes.TemporalMesh) Mesh(com.jme3.scene.Mesh) ArrayList(java.util.ArrayList) List(java.util.List) Texture(com.jme3.texture.Texture)

Example 54 with Type

use of com.jme3.scene.VertexBuffer.Type in project jmonkeyengine by jMonkeyEngine.

the class LightHelper method toLight.

public Light toLight(Structure structure, BlenderContext blenderContext) throws BlenderFileException {
    Light result = (Light) blenderContext.getLoadedFeature(structure.getOldMemoryAddress(), LoadedDataType.FEATURE);
    if (result != null) {
        return result;
    }
    Light light = null;
    int type = ((Number) structure.getFieldValue("type")).intValue();
    switch(type) {
        case // Lamp
        0:
            light = new PointLight();
            float distance = ((Number) structure.getFieldValue("dist")).floatValue();
            ((PointLight) light).setRadius(distance);
            break;
        case // Sun
        1:
            LOGGER.log(Level.WARNING, "'Sun' lamp is not supported in jMonkeyEngine. Using PointLight with radius = Float.MAX_VALUE.");
            light = new PointLight();
            ((PointLight) light).setRadius(Float.MAX_VALUE);
            break;
        case // Spot
        2:
            light = new SpotLight();
            // range
            ((SpotLight) light).setSpotRange(((Number) structure.getFieldValue("dist")).floatValue());
            // outer angle
            float outerAngle = ((Number) structure.getFieldValue("spotsize")).floatValue() * FastMath.DEG_TO_RAD * 0.5f;
            ((SpotLight) light).setSpotOuterAngle(outerAngle);
            // inner angle
            float spotblend = ((Number) structure.getFieldValue("spotblend")).floatValue();
            spotblend = FastMath.clamp(spotblend, 0, 1);
            float innerAngle = outerAngle * (1 - spotblend);
            ((SpotLight) light).setSpotInnerAngle(innerAngle);
            break;
        case // Hemi
        3:
            LOGGER.log(Level.WARNING, "'Hemi' lamp is not supported in jMonkeyEngine. Using DirectionalLight instead.");
        case // Area
        4:
            light = new DirectionalLight();
            break;
        default:
            throw new BlenderFileException("Unknown light source type: " + type);
    }
    float r = ((Number) structure.getFieldValue("r")).floatValue();
    float g = ((Number) structure.getFieldValue("g")).floatValue();
    float b = ((Number) structure.getFieldValue("b")).floatValue();
    light.setColor(new ColorRGBA(r, g, b, 1.0f));
    light.setName(structure.getName());
    return light;
}
Also used : ColorRGBA(com.jme3.math.ColorRGBA) DirectionalLight(com.jme3.light.DirectionalLight) SpotLight(com.jme3.light.SpotLight) Light(com.jme3.light.Light) PointLight(com.jme3.light.PointLight) DirectionalLight(com.jme3.light.DirectionalLight) BlenderFileException(com.jme3.scene.plugins.blender.file.BlenderFileException) PointLight(com.jme3.light.PointLight) SpotLight(com.jme3.light.SpotLight)

Example 55 with Type

use of com.jme3.scene.VertexBuffer.Type in project jmonkeyengine by jMonkeyEngine.

the class TemporalMesh method prepareFacesGeometry.

/**
     * The method creates geometries from faces.
     * @param result
     *            the list where new geometries will be appended
     * @param meshHelper
     *            the mesh helper
     */
protected void prepareFacesGeometry(List<Geometry> result, MeshHelper meshHelper) {
    LOGGER.fine("Preparing faces geometries.");
    this.triangulate();
    Vector3f[] tempVerts = new Vector3f[3];
    Vector3f[] tempNormals = new Vector3f[3];
    byte[][] tempVertColors = new byte[3][];
    List<Map<Float, Integer>> boneBuffers = new ArrayList<Map<Float, Integer>>(3);
    LOGGER.log(Level.FINE, "Appending {0} faces to mesh buffers.", faces.size());
    Map<Integer, MeshBuffers> faceMeshes = new HashMap<Integer, MeshBuffers>();
    for (Face face : faces) {
        MeshBuffers meshBuffers = faceMeshes.get(face.getMaterialNumber());
        if (meshBuffers == null) {
            meshBuffers = new MeshBuffers(face.getMaterialNumber());
            faceMeshes.put(face.getMaterialNumber(), meshBuffers);
        }
        List<List<Integer>> triangulatedIndexes = face.getCurrentIndexes();
        List<byte[]> vertexColors = face.getVertexColors();
        for (List<Integer> indexes : triangulatedIndexes) {
            assert indexes.size() == 3 : "The mesh has not been properly triangulated!";
            Vector3f normal = null;
            if (!face.isSmooth()) {
                normal = FastMath.computeNormal(vertices.get(indexes.get(0)), vertices.get(indexes.get(1)), vertices.get(indexes.get(2)));
            }
            boneBuffers.clear();
            for (int i = 0; i < 3; ++i) {
                int vertIndex = indexes.get(i);
                tempVerts[i] = vertices.get(vertIndex);
                tempNormals[i] = normal != null ? normal : normals.get(vertIndex);
                tempVertColors[i] = vertexColors != null ? vertexColors.get(face.getIndexes().indexOf(vertIndex)) : null;
                if (boneIndexes.size() > 0 && vertexGroups.size() > 0) {
                    Map<Float, Integer> boneBuffersForVertex = new HashMap<Float, Integer>();
                    Map<String, Float> vertexGroupsForVertex = vertexGroups.get(vertIndex);
                    for (Entry<String, Integer> entry : boneIndexes.entrySet()) {
                        if (vertexGroupsForVertex.containsKey(entry.getKey())) {
                            float weight = vertexGroupsForVertex.get(entry.getKey());
                            if (weight > MINIMUM_BONE_WEIGHT) {
                                // only values of weight greater than MINIMUM_BONE_WEIGHT are used
                                // if all non zero weights were used, and they were samm enough, problems with normalisation would occur
                                // because adding a very small value to 1.0 will give 1.0
                                // so in order to avoid such errors, which can cause severe animation artifacts we need to use some minimum weight value
                                boneBuffersForVertex.put(weight, entry.getValue());
                            }
                        }
                    }
                    if (boneBuffersForVertex.size() == 0) {
                        // attach the vertex to zero-indexed bone so that it does not collapse to (0, 0, 0)
                        boneBuffersForVertex.put(1.0f, 0);
                    }
                    boneBuffers.add(boneBuffersForVertex);
                }
            }
            Map<String, List<Vector2f>> uvs = meshHelper.selectUVSubset(face, indexes.toArray(new Integer[indexes.size()]));
            meshBuffers.append(face.isSmooth(), tempVerts, tempNormals, uvs, tempVertColors, boneBuffers);
        }
    }
    LOGGER.fine("Converting mesh buffers to geometries.");
    Map<Geometry, MeshBuffers> geometryToBuffersMap = new HashMap<Geometry, MeshBuffers>();
    for (Entry<Integer, MeshBuffers> entry : faceMeshes.entrySet()) {
        MeshBuffers meshBuffers = entry.getValue();
        Mesh mesh = new Mesh();
        if (meshBuffers.isShortIndexBuffer()) {
            mesh.setBuffer(Type.Index, 1, (ShortBuffer) meshBuffers.getIndexBuffer());
        } else {
            mesh.setBuffer(Type.Index, 1, (IntBuffer) meshBuffers.getIndexBuffer());
        }
        mesh.setBuffer(meshBuffers.getPositionsBuffer());
        mesh.setBuffer(meshBuffers.getNormalsBuffer());
        if (meshBuffers.areVertexColorsUsed()) {
            mesh.setBuffer(Type.Color, 4, meshBuffers.getVertexColorsBuffer());
            mesh.getBuffer(Type.Color).setNormalized(true);
        }
        BoneBuffersData boneBuffersData = meshBuffers.getBoneBuffers();
        if (boneBuffersData != null) {
            mesh.setMaxNumWeights(boneBuffersData.maximumWeightsPerVertex);
            mesh.setBuffer(boneBuffersData.verticesWeights);
            mesh.setBuffer(boneBuffersData.verticesWeightsIndices);
            LOGGER.fine("Generating bind pose and normal buffers.");
            mesh.generateBindPose(true);
            // change the usage type of vertex and normal buffers from Static to Stream
            mesh.getBuffer(Type.Position).setUsage(Usage.Stream);
            mesh.getBuffer(Type.Normal).setUsage(Usage.Stream);
            // creating empty buffers for HW skinning; the buffers will be setup if ever used
            VertexBuffer verticesWeightsHW = new VertexBuffer(Type.HWBoneWeight);
            VertexBuffer verticesWeightsIndicesHW = new VertexBuffer(Type.HWBoneIndex);
            mesh.setBuffer(verticesWeightsHW);
            mesh.setBuffer(verticesWeightsIndicesHW);
        }
        Geometry geometry = new Geometry(name + (result.size() + 1), mesh);
        if (properties != null && properties.getValue() != null) {
            meshHelper.applyProperties(geometry, properties);
        }
        result.add(geometry);
        geometryToBuffersMap.put(geometry, meshBuffers);
    }
    LOGGER.fine("Applying materials to geometries.");
    for (Entry<Geometry, MeshBuffers> entry : geometryToBuffersMap.entrySet()) {
        int materialIndex = entry.getValue().getMaterialIndex();
        Geometry geometry = entry.getKey();
        if (materialIndex >= 0 && materials != null && materials.length > materialIndex && materials[materialIndex] != null) {
            materials[materialIndex].applyMaterial(geometry, meshStructure.getOldMemoryAddress(), entry.getValue().getUvCoords(), blenderContext);
        } else {
            Material defaultMaterial = blenderContext.getDefaultMaterial().clone();
            defaultMaterial.getAdditionalRenderState().setFaceCullMode(FaceCullMode.Off);
            geometry.setMaterial(defaultMaterial);
        }
    }
}
Also used : HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) VertexBuffer(com.jme3.scene.VertexBuffer) ArrayList(java.util.ArrayList) BoneBuffersData(com.jme3.scene.plugins.blender.meshes.MeshBuffers.BoneBuffersData) ArrayList(java.util.ArrayList) List(java.util.List) Mesh(com.jme3.scene.Mesh) Material(com.jme3.material.Material) Geometry(com.jme3.scene.Geometry) Vector3f(com.jme3.math.Vector3f) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map)

Aggregations

ArrayList (java.util.ArrayList)18 Structure (com.jme3.scene.plugins.blender.file.Structure)12 Vector3f (com.jme3.math.Vector3f)11 Pointer (com.jme3.scene.plugins.blender.file.Pointer)10 IOException (java.io.IOException)10 List (java.util.List)9 ColorRGBA (com.jme3.math.ColorRGBA)8 Texture (com.jme3.texture.Texture)8 Geometry (com.jme3.scene.Geometry)6 Image (com.jme3.texture.Image)6 BoundingBox (com.jme3.bounding.BoundingBox)5 BoundingSphere (com.jme3.bounding.BoundingSphere)5 Light (com.jme3.light.Light)5 TemporalMesh (com.jme3.scene.plugins.blender.meshes.TemporalMesh)5 Uniform (com.jme3.shader.Uniform)5 Material (com.jme3.material.Material)4 Quaternion (com.jme3.math.Quaternion)4 Transform (com.jme3.math.Transform)4 Mesh (com.jme3.scene.Mesh)4 BlenderFileException (com.jme3.scene.plugins.blender.file.BlenderFileException)4