Merge remote-tracking branch 'origin/master' into in-pass-shadows

This commit is contained in:
Kirill Vainer 2018-03-19 14:00:01 -04:00
commit 6fb2d029d2
503 changed files with 142268 additions and 14044 deletions

1
.gitignore vendored
View File

@ -2,6 +2,7 @@
**/.classpath **/.classpath
**/.settings **/.settings
**/.project **/.project
**/out
/.gradle/ /.gradle/
/.nb-gradle/ /.nb-gradle/
/.idea/ /.idea/

View File

@ -55,5 +55,5 @@ We generally abide by the standard Java Code Conventions. Besides that, just mak
## Documentation ## Documentation
- How to edit the wiki - WIP - How to edit the [wiki](https://github.com/jMonkeyEngine/wiki).
- How to edit JavaDocs - WIP - How to edit JavaDocs - WIP

View File

@ -3,7 +3,7 @@ jMonkeyEngine
[![Build Status](https://travis-ci.org/jMonkeyEngine/jmonkeyengine.svg?branch=master)](https://travis-ci.org/jMonkeyEngine/jmonkeyengine) [![Build Status](https://travis-ci.org/jMonkeyEngine/jmonkeyengine.svg?branch=master)](https://travis-ci.org/jMonkeyEngine/jmonkeyengine)
jMonkeyEngine is a 3D game engine for adventurous Java developers. Its open-source, cross-platform, and cutting-edge. 3.1.0 is the latest stable version of the jMonkeyEngine 3 SDK, a complete game development suite. We'll release 3.1.x updates until the major 3.2 release arrives. jMonkeyEngine is a 3D game engine for adventurous Java developers. Its open-source, cross-platform, and cutting-edge. 3.2.0 is the latest stable version of the jMonkeyEngine 3 SDK, a complete game development suite. We'll release 3.2.x updates until the major 3.3 release arrives.
The engine is used by several commercial game studios and computer-science courses. Here's a taste: The engine is used by several commercial game studios and computer-science courses. Here's a taste:

View File

@ -15,7 +15,7 @@ apply from: file('version.gradle')
subprojects { subprojects {
if(!project.name.equals('jme3-android-examples')) { if(!project.name.equals('jme3-android-examples')) {
apply from: rootProject.file('common.gradle') apply from: rootProject.file('common.gradle')
if (!['jme3-testdata', 'sdk'].contains(project.name)) { if (!project.name.equals('jme3-testdata')) {
apply from: rootProject.file('bintray.gradle') apply from: rootProject.file('bintray.gradle')
} }
} else { } else {
@ -116,7 +116,7 @@ task mergedSource(type: Copy){
} }
task wrapper(type: Wrapper, description: 'Creates and deploys the Gradle wrapper to the current directory.') { task wrapper(type: Wrapper, description: 'Creates and deploys the Gradle wrapper to the current directory.') {
gradleVersion = '3.2.1' gradleVersion = '4.1'
} }
ext { ext {

View File

@ -16,6 +16,9 @@ repositories {
maven { maven {
url "http://nifty-gui.sourceforge.net/nifty-maven-repo" url "http://nifty-gui.sourceforge.net/nifty-maven-repo"
} }
flatDir {
dirs rootProject.file('lib')
}
} }
dependencies { dependencies {

View File

@ -1,7 +1,7 @@
# Version number used for plugins, only 3 numbers (e.g. 3.1.3) # Version number used for plugins, only 3 numbers (e.g. 3.1.3)
jmeVersion = 3.2.0 jmeVersion = 3.3.0
# Version used for application and settings folder, no spaces! # Version used for application and settings folder, no spaces!
jmeMainVersion = 3.2 jmeMainVersion = 3.3
# Version addition pre-alpha-svn, Stable, Beta # Version addition pre-alpha-svn, Stable, Beta
jmeVersionTag = SNAPSHOT jmeVersionTag = SNAPSHOT
# Increment this each time jmeVersionTag changes but jmeVersion stays the same # Increment this each time jmeVersionTag changes but jmeVersion stays the same

Binary file not shown.

View File

@ -1,6 +1,6 @@
#Fri Nov 25 13:05:50 EST 2016 #Sun Sep 17 22:55:30 EDT 2017
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-3.2.1-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-bin.zip

22
gradlew vendored
View File

@ -1,4 +1,4 @@
#!/usr/bin/env bash #!/usr/bin/env sh
############################################################################## ##############################################################################
## ##
@ -154,11 +154,19 @@ if $cygwin ; then
esac esac
fi fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules # Escape application args
function splitJvmOpts() { save ( ) {
JVM_OPTS=("$@") for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
} }
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS APP_ARGS=$(save "$@")
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" # Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"

6
gradlew.bat vendored
View File

@ -49,7 +49,6 @@ goto fail
@rem Get command-line arguments, handling Windows variants @rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args :win9xME_args
@rem Slurp the command line arguments. @rem Slurp the command line arguments.
@ -60,11 +59,6 @@ set _SKIP=2
if "x%~1" == "x" goto execute if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%* set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute :execute
@rem Setup the command line @rem Setup the command line

View File

@ -214,7 +214,7 @@ public class MainActivity extends AppCompatActivity implements OnItemClickListen
/** /**
* User clicked a view on the screen. Check for the OK and Cancel buttons * User clicked a view on the screen. Check for the OK and Cancel buttons
* and either start the applicaiton or exit. * and either start the application or exit.
* @param view * @param view
*/ */
public void onClick(View view) { public void onClick(View view) {

View File

@ -5,5 +5,5 @@ if (!hasProperty('mainClass')) {
dependencies { dependencies {
compile project(':jme3-core') compile project(':jme3-core')
compile project(':jme3-plugins') compile project(':jme3-plugins')
compile files('../lib/android.jar') compileOnly 'android:android'
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2012 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -59,7 +59,7 @@ import java.util.logging.Logger;
/** /**
* AndroidSensorJoyInput converts the Android Sensor system into Joystick events. * AndroidSensorJoyInput converts the Android Sensor system into Joystick events.
* A single joystick is configured and includes data for all configured sensors * A single joystick is configured and includes data for all configured sensors
* as seperate axes of the joystick. * as separate axes of the joystick.
* *
* Each axis is named according to the static strings in SensorJoystickAxis. * Each axis is named according to the static strings in SensorJoystickAxis.
* Refer to the strings defined in SensorJoystickAxis for a list of supported * Refer to the strings defined in SensorJoystickAxis for a list of supported
@ -285,8 +285,8 @@ public class AndroidSensorJoyInput implements SensorEventListener {
} }
/** /**
* Calculates the device orientation based off the data recieved from the * Calculates the device orientation based off the data received from the
* Acceleration Sensor and Mangetic Field sensor * Acceleration Sensor and Magnetic Field sensor
* Values are returned relative to the Earth. * Values are returned relative to the Earth.
* *
* From the Android Doc * From the Android Doc

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2012 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -136,7 +136,7 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer, SoftTex
// stops at the setFormat call without a crash. // stops at the setFormat call without a crash.
// We look at the user setting for alpha bits and set the surfaceview // We look at the user setting for alpha bits and set the surfaceview
// PixelFormat to either Opaque, Transparent, or Translucent. // PixelFormat to either Opaque, Transparent, or Translucent.
// ConfigChooser will do it's best to honor the alpha requested by the user // ConfigChooser will do its best to honor the alpha requested by the user
// For best rendering performance, use Opaque (alpha bits = 0). // For best rendering performance, use Opaque (alpha bits = 0).
int curAlphaBits = settings.getAlphaBits(); int curAlphaBits = settings.getAlphaBits();
logger.log(Level.FINE, "curAlphaBits: {0}", curAlphaBits); logger.log(Level.FINE, "curAlphaBits: {0}", curAlphaBits);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2012 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -69,7 +69,7 @@ public class BlenderKey extends ModelKey {
*/ */
protected String usedWorld; protected String usedWorld;
/** /**
* User's default material that is set fo objects that have no material definition in blender. The default value is * User's default material that is set for objects that have no material definition in blender. The default value is
* null. If the value is null the importer will use its own default material (gray color - like in blender). * null. If the value is null the importer will use its own default material (gray color - like in blender).
*/ */
protected Material defaultMaterial; protected Material defaultMaterial;
@ -476,9 +476,9 @@ public class BlenderKey extends ModelKey {
} }
/** /**
* This mehtod sets the name of the WORLD data block taht should be used during file loading. By default the name is * This method sets the name of the WORLD data block that should be used during file loading. By default the name is
* not set. If no name is set or the given name does not occur in the file - the first WORLD data block will be used * not set. If no name is set or the given name does not occur in the file - the first WORLD data block will be used
* during loading (assumin any exists in the file). * during loading (assuming any exists in the file).
* @param usedWorld * @param usedWorld
* the name of the WORLD block used during loading * the name of the WORLD block used during loading
*/ */
@ -487,7 +487,7 @@ public class BlenderKey extends ModelKey {
} }
/** /**
* This mehtod returns the name of the WORLD data block taht should be used during file loading. * This method returns the name of the WORLD data block that should be used during file loading.
* @return the name of the WORLD block used during loading * @return the name of the WORLD block used during loading
*/ */
public String getUsedWorld() { public String getUsedWorld() {

View File

@ -237,7 +237,7 @@ public class SimulationNode {
} }
} }
// ... add virtual tracks if neccessary, for bones that were altered but had no tracks before ... // ... add virtual tracks if necessary, for bones that were altered but had no tracks before ...
for (Long boneOMA : alteredOmas) { for (Long boneOMA : alteredOmas) {
BoneContext boneContext = blenderContext.getBoneContext(boneOMA); BoneContext boneContext = blenderContext.getBoneContext(boneOMA);
int boneIndex = skeleton.getBoneIndex(boneContext.getBone()); int boneIndex = skeleton.getBoneIndex(boneContext.getBone());

View File

@ -37,7 +37,7 @@ import com.jme3.util.BufferUtils;
/** /**
* A temporal mesh for curves and surfaces. It works in similar way as TemporalMesh for meshes. * A temporal mesh for curves and surfaces. It works in similar way as TemporalMesh for meshes.
* It prepares all neccessary lines and faces and allows to apply modifiers just like in regular temporal mesh. * It prepares all necessary lines and faces and allows to apply modifiers just like in regular temporal mesh.
* *
* @author Marcin Roguski (Kaelthas) * @author Marcin Roguski (Kaelthas)
*/ */
@ -210,7 +210,7 @@ public class CurvesTemporalMesh extends TemporalMesh {
} }
/** /**
* The method computes the value of a point at the certain relational distance from its beggining. * The method computes the value of a point at the certain relational distance from its beginning.
* @param alongRatio * @param alongRatio
* the relative distance along the curve; should be a value between 0 and 1 inclusive; * the relative distance along the curve; should be a value between 0 and 1 inclusive;
* if the value exceeds the boundaries it is truncated to them * if the value exceeds the boundaries it is truncated to them
@ -369,7 +369,7 @@ public class CurvesTemporalMesh extends TemporalMesh {
} }
/** /**
* The method loads the bevel object that sould be applied to curve. It can either be another curve or a generated one * The method loads the bevel object that should be applied to curve. It can either be another curve or a generated one
* based on the bevel generating parameters in blender. * based on the bevel generating parameters in blender.
* @param curveStructure * @param curveStructure
* the structure with the curve's data (the curve being loaded, NOT the bevel curve) * the structure with the curve's data (the curve being loaded, NOT the bevel curve)
@ -707,7 +707,7 @@ public class CurvesTemporalMesh extends TemporalMesh {
/** /**
* the method applies scale for the given bevel points. The points table is * the method applies scale for the given bevel points. The points table is
* being modified so expect ypur result there. * being modified so expect your result there.
* *
* @param points * @param points
* the bevel points * the bevel points
@ -726,7 +726,7 @@ public class CurvesTemporalMesh extends TemporalMesh {
/** /**
* A helper class that represents a single bezier line. It consists of Edge's and allows to * A helper class that represents a single bezier line. It consists of Edge's and allows to
* get a subline of a lentgh of the line. * get a subline of a length of the line.
* *
* @author Marcin Roguski (Kaelthas) * @author Marcin Roguski (Kaelthas)
*/ */
@ -776,7 +776,7 @@ public class CurvesTemporalMesh extends TemporalMesh {
} }
if (cyclic) { if (cyclic) {
// if the first vertex is repeated at the end the distance will be = 0 so it won't affect the result, and if it is not repeated // if the first vertex is repeated at the end the distance will be = 0 so it won't affect the result, and if it is not repeated
// then it is neccessary to add the length between the last and the first vertex // then it is necessary to add the length between the last and the first vertex
length += vertices[vertices.length - 1].distance(vertices[0]); length += vertices[vertices.length - 1].distance(vertices[0]);
} }
} }
@ -834,7 +834,7 @@ public class CurvesTemporalMesh extends TemporalMesh {
} }
/** /**
* The method computes the value of a point at the certain relational distance from its beggining. * The method computes the value of a point at the certain relational distance from its beginning.
* @param alongRatio * @param alongRatio
* the relative distance along the curve; should be a value between 0 and 1 inclusive; * the relative distance along the curve; should be a value between 0 and 1 inclusive;
* if the value exceeds the boundaries it is truncated to them * if the value exceeds the boundaries it is truncated to them

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2012 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -85,7 +85,7 @@ public class DnaBlockData {
names[i] = inputStream.readString(); names[i] = inputStream.readString();
} }
// reding types // reading types
inputStream.alignPosition(4); inputStream.alignPosition(4);
identifier = inputStream.readByte() << 24 | inputStream.readByte() << 16 | inputStream.readByte() << 8 | inputStream.readByte(); identifier = inputStream.readByte() << 24 | inputStream.readByte() << 16 | inputStream.readByte() << 8 | inputStream.readByte();
if (identifier != TYPE_ID) { if (identifier != TYPE_ID) {
@ -181,7 +181,7 @@ public class DnaBlockData {
/** /**
* This method converts the given identifier code to string. * This method converts the given identifier code to string.
* @param code * @param code
* the code taht is to be converted * the code that is to be converted
* @return the string value of the identifier * @return the string value of the identifier
*/ */
private String toString(int code) { private String toString(int code) {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2012 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -32,7 +32,7 @@
package com.jme3.scene.plugins.blender.file; package com.jme3.scene.plugins.blender.file;
/** /**
* An array that can be dynamically modified/ * An array that can be dynamically modified
* @author Marcin Roguski * @author Marcin Roguski
* @param <T> * @param <T>
* the type of stored data in the array * the type of stored data in the array
@ -42,7 +42,7 @@ public class DynamicArray<T> implements Cloneable {
/** An array object that holds the required data. */ /** An array object that holds the required data. */
private T[] array; private T[] array;
/** /**
* This table holds the sizes of dimetions of the dynamic table. It's length specifies the table dimension or a * This table holds the sizes of dimensions of the dynamic table. Its length specifies the table dimension or a
* pointer level. For example: if tableSizes.length == 3 then it either specifies a dynamic table of fixed lengths: * pointer level. For example: if tableSizes.length == 3 then it either specifies a dynamic table of fixed lengths:
* dynTable[a][b][c], where a,b,c are stored in the tableSizes table. * dynTable[a][b][c], where a,b,c are stored in the tableSizes table.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2012 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -169,7 +169,7 @@ public class Structure implements Cloneable {
} }
/** /**
* This methos should be used on structures that are of a 'ListBase' type. It creates a List of structures that are * This method should be used on structures that are of a 'ListBase' type. It creates a List of structures that are
* held by this structure within the blend file. * held by this structure within the blend file.
* @return a list of filled structures * @return a list of filled structures
* @throws BlenderFileException * @throws BlenderFileException
@ -232,7 +232,7 @@ public class Structure implements Cloneable {
} }
/** /**
* This method returns the address of the structure. The strucutre should be filled with data otherwise an exception * This method returns the address of the structure. The structure should be filled with data otherwise an exception
* is thrown. * is thrown.
* @return the address of the feature stored in this structure * @return the address of the feature stored in this structure
*/ */

View File

@ -1,6 +1,7 @@
package com.jme3.scene.plugins.blender.materials; package com.jme3.scene.plugins.blender.materials;
import java.io.IOException; import java.io.IOException;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -106,7 +107,7 @@ public final class MaterialContext implements Savable {
boolean transparent = false; boolean transparent = false;
if (diffuseColor != null) { if (diffuseColor != null) {
transparent = diffuseColor.a < 1.0f; transparent = diffuseColor.a < 1.0f;
if (loadedTextures.size() > 0) {// texutre covers the material color if (loadedTextures.size() > 0) {// texture covers the material color
diffuseColor.set(1, 1, 1, 1); diffuseColor.set(1, 1, 1, 1);
} }
} }
@ -164,6 +165,12 @@ public final class MaterialContext implements Savable {
material.setColor("Ambient", new ColorRGBA(ambientFactor, ambientFactor, ambientFactor, 1f)); material.setColor("Ambient", new ColorRGBA(ambientFactor, ambientFactor, ambientFactor, 1f));
} }
// initializing unused "user-defined UV coords" to all available
Map<String, List<Vector2f>> unusedUserDefinedUVCoords = Collections.emptyMap();
if(userDefinedUVCoordinates != null && !userDefinedUVCoordinates.isEmpty()) {
unusedUserDefinedUVCoords = new HashMap<>(userDefinedUVCoordinates);
}
// applying textures // applying textures
int textureIndex = 0; int textureIndex = 0;
if (loadedTextures != null && loadedTextures.size() > 0) { if (loadedTextures != null && loadedTextures.size() > 0) {
@ -175,6 +182,8 @@ public final class MaterialContext implements Savable {
String usedUserUVSet = combinedTexture.flatten(geometry, geometriesOMA, userDefinedUVCoordinates, blenderContext); String usedUserUVSet = combinedTexture.flatten(geometry, geometriesOMA, userDefinedUVCoordinates, blenderContext);
this.setTexture(material, combinedTexture.getMappingType(), combinedTexture.getResultTexture()); this.setTexture(material, combinedTexture.getMappingType(), combinedTexture.getResultTexture());
if(usedUserUVSet == null || unusedUserDefinedUVCoords.containsKey(usedUserUVSet)) {
List<Vector2f> uvs = combinedTexture.getResultUVS(); List<Vector2f> uvs = combinedTexture.getResultUVS();
if(uvs != null && uvs.size() > 0) { if(uvs != null && uvs.size() > 0) {
VertexBuffer uvCoordsBuffer = new VertexBuffer(TextureHelper.TEXCOORD_TYPES[textureIndex++]); VertexBuffer uvCoordsBuffer = new VertexBuffer(TextureHelper.TEXCOORD_TYPES[textureIndex++]);
@ -182,9 +191,10 @@ public final class MaterialContext implements Savable {
geometry.getMesh().setBuffer(uvCoordsBuffer); geometry.getMesh().setBuffer(uvCoordsBuffer);
}//uvs might be null if the user assigned non existing UV coordinates group name to the mesh (this should be fixed in blender file) }//uvs might be null if the user assigned non existing UV coordinates group name to the mesh (this should be fixed in blender file)
// Remove used "user-defined UV coords" from the unused collection
if(usedUserUVSet != null) { if(usedUserUVSet != null) {
userDefinedUVCoordinates = new HashMap<>(userDefinedUVCoordinates); unusedUserDefinedUVCoords.remove(usedUserUVSet);
userDefinedUVCoordinates.remove(usedUserUVSet); }
} }
} else { } else {
LOGGER.log(Level.WARNING, "The texture could not be applied because JME only supports up to {0} different UV's.", TextureHelper.TEXCOORD_TYPES.length); LOGGER.log(Level.WARNING, "The texture could not be applied because JME only supports up to {0} different UV's.", TextureHelper.TEXCOORD_TYPES.length);
@ -192,12 +202,12 @@ public final class MaterialContext implements Savable {
} }
} }
if (userDefinedUVCoordinates != null && userDefinedUVCoordinates.size() > 0) { if (unusedUserDefinedUVCoords != null && unusedUserDefinedUVCoords.size() > 0) {
LOGGER.fine("Storing unused, user defined UV coordinates sets."); LOGGER.fine("Storing unused, user defined UV coordinates sets.");
if (userDefinedUVCoordinates.size() > TextureHelper.TEXCOORD_TYPES.length) { if (unusedUserDefinedUVCoords.size() > TextureHelper.TEXCOORD_TYPES.length) {
LOGGER.log(Level.WARNING, "The blender file has defined more than {0} different UV coordinates for the mesh. JME supports only {0} UV coordinates buffers.", TextureHelper.TEXCOORD_TYPES.length); LOGGER.log(Level.WARNING, "The blender file has defined more than {0} different UV coordinates for the mesh. JME supports only {0} UV coordinates buffers.", TextureHelper.TEXCOORD_TYPES.length);
} }
for (Entry<String, List<Vector2f>> entry : userDefinedUVCoordinates.entrySet()) { for (Entry<String, List<Vector2f>> entry : unusedUserDefinedUVCoords.entrySet()) {
if (textureIndex < TextureHelper.TEXCOORD_TYPES.length) { if (textureIndex < TextureHelper.TEXCOORD_TYPES.length) {
List<Vector2f> uvs = entry.getValue(); List<Vector2f> uvs = entry.getValue();
VertexBuffer uvCoordsBuffer = new VertexBuffer(TextureHelper.TEXCOORD_TYPES[textureIndex++]); VertexBuffer uvCoordsBuffer = new VertexBuffer(TextureHelper.TEXCOORD_TYPES[textureIndex++]);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2012 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -324,7 +324,7 @@ public final class Vector3d implements Savable, Cloneable, Serializable {
* the vector to take the cross product of with this. * the vector to take the cross product of with this.
* @param result * @param result
* the vector to store the cross product result. * the vector to store the cross product result.
* @return result, after recieving the cross product vector. * @return result, after receiving the cross product vector.
*/ */
public Vector3d cross(Vector3d v, Vector3d result) { public Vector3d cross(Vector3d v, Vector3d result) {
return this.cross(v.x, v.y, v.z, result); return this.cross(v.x, v.y, v.z, result);
@ -342,7 +342,7 @@ public final class Vector3d implements Savable, Cloneable, Serializable {
* z component of the vector to take the cross product of with this. * z component of the vector to take the cross product of with this.
* @param result * @param result
* the vector to store the cross product result. * the vector to store the cross product result.
* @return result, after recieving the cross product vector. * @return result, after receiving the cross product vector.
*/ */
public Vector3d cross(double otherX, double otherY, double otherZ, Vector3d result) { public Vector3d cross(double otherX, double otherY, double otherZ, Vector3d result) {
if (result == null) { if (result == null) {
@ -485,12 +485,12 @@ public final class Vector3d implements Savable, Cloneable, Serializable {
} }
/** /**
* <code>multLocal</code> multiplies a provided vector to this vector * <code>multLocal</code> multiplies a provided vector by this vector
* internally, and returns a handle to this vector for easy chaining of * internally, and returns a handle to this vector for easy chaining of
* calls. If the provided vector is null, null is returned. * calls. If the provided vector is null, null is returned.
* *
* @param vec * @param vec
* the vector to mult to this vector. * the vector to multiply by this vector.
* @return this * @return this
*/ */
public Vector3d multLocal(Vector3d vec) { public Vector3d multLocal(Vector3d vec) {
@ -522,7 +522,7 @@ public final class Vector3d implements Savable, Cloneable, Serializable {
} }
/** /**
* <code>multLocal</code> multiplies a provided vector to this vector * <code>multLocal</code> multiplies a provided vector by this vector
* internally, and returns a handle to this vector for easy chaining of * internally, and returns a handle to this vector for easy chaining of
* calls. If the provided vector is null, null is returned. * calls. If the provided vector is null, null is returned.
* *
@ -539,7 +539,7 @@ public final class Vector3d implements Savable, Cloneable, Serializable {
} }
/** /**
* <code>multLocal</code> multiplies a provided vector to this vector * <code>multLocal</code> multiplies a provided vector by this vector
* internally, and returns a handle to this vector for easy chaining of * internally, and returns a handle to this vector for easy chaining of
* calls. If the provided vector is null, null is returned. * calls. If the provided vector is null, null is returned.
* *
@ -657,7 +657,7 @@ public final class Vector3d implements Savable, Cloneable, Serializable {
} }
/** /**
* <code>subtractLocal</code> subtracts a provided vector to this vector * <code>subtractLocal</code> subtracts a provided vector from this vector
* internally, and returns a handle to this vector for easy chaining of * internally, and returns a handle to this vector for easy chaining of
* calls. If the provided vector is null, null is returned. * calls. If the provided vector is null, null is returned.
* *
@ -825,7 +825,7 @@ public final class Vector3d implements Savable, Cloneable, Serializable {
/** /**
* <code>hashCode</code> returns a unique code for this vector object based * <code>hashCode</code> returns a unique code for this vector object based
* on it's values. If two vectors are logically equivalent, they will return * on its values. If two vectors are logically equivalent, they will return
* the same hash code value. * the same hash code value.
* @return the hash code value of this vector. * @return the hash code value of this vector.
*/ */

View File

@ -291,6 +291,8 @@ public class MeshHelper extends AbstractBlenderHelper {
Structure defbase = (Structure) parent.getFieldValue("defbase"); Structure defbase = (Structure) parent.getFieldValue("defbase");
List<String> groupNames = new ArrayList<String>(); List<String> groupNames = new ArrayList<String>();
List<Structure> defs = defbase.evaluateListBase(); List<Structure> defs = defbase.evaluateListBase();
if(!defs.isEmpty()) {
for (Structure def : defs) { for (Structure def : defs) {
groupNames.add(def.getFieldValue("name").toString()); groupNames.add(def.getFieldValue("name").toString());
} }
@ -315,6 +317,7 @@ public class MeshHelper extends AbstractBlenderHelper {
} }
} }
} }
}
return result; return result;
} }

View File

@ -47,7 +47,7 @@ public class SubdivisionSurfaceModifier extends Modifier {
private Set<Integer> verticesOnOriginalEdges = new HashSet<Integer>(); private Set<Integer> verticesOnOriginalEdges = new HashSet<Integer>();
/** /**
* Constructor loads all neccessary modifier data. * Constructor loads all necessary modifier data.
* @param modifierStructure * @param modifierStructure
* the modifier structure * the modifier structure
* @param blenderContext * @param blenderContext
@ -193,7 +193,7 @@ public class SubdivisionSurfaceModifier extends Modifier {
// moving the vertex // moving the vertex
v.addLocal(t); v.addLocal(t);
// applying crease weight if neccessary // applying crease weight if necessary
CreasePoint creasePoint = creasePoints.get(i); CreasePoint creasePoint = creasePoints.get(i);
if (creasePoint.getTarget() != null && creasePoint.getWeight() != 0) { if (creasePoint.getTarget() != null && creasePoint.getWeight() != 0) {
t = creasePoint.getTarget().subtractLocal(v).multLocal(creasePoint.getWeight()); t = creasePoint.getTarget().subtractLocal(v).multLocal(creasePoint.getWeight());

View File

@ -31,12 +31,14 @@
*/ */
package com.jme3.scene.plugins.blender.textures; package com.jme3.scene.plugins.blender.textures;
import com.jme3.asset.AssetManager;
import com.jme3.asset.TextureKey;
import com.jme3.scene.plugins.blender.file.BlenderInputStream; import com.jme3.scene.plugins.blender.file.BlenderInputStream;
import com.jme3.texture.Image; import com.jme3.texture.Image;
import com.jme3.texture.Texture;
import com.jme3.texture.plugins.AWTLoader; import com.jme3.texture.plugins.AWTLoader;
import com.jme3.texture.plugins.DDSLoader; import com.jme3.texture.plugins.HDRLoader;
import com.jme3.texture.plugins.TGALoader; import java.util.logging.Level;
import java.io.InputStream;
import java.util.logging.Logger; import java.util.logging.Logger;
/** /**
@ -47,11 +49,29 @@ import java.util.logging.Logger;
*/ */
/* package */class ImageLoader extends AWTLoader { /* package */class ImageLoader extends AWTLoader {
private static final Logger LOGGER = Logger.getLogger(ImageLoader.class.getName()); private static final Logger LOGGER = Logger.getLogger(ImageLoader.class.getName());
private static final Logger hdrLogger = Logger.getLogger(HDRLoader.class.getName()); // Used to silence HDR Errors
protected DDSLoader ddsLoader = new DDSLoader(); // DirectX image loader
/** /**
* This method loads the image from the blender file itself. It tries each loader to load the image. * List of Blender-Supported Texture Extensions (we have to guess them, so
* the AssetLoader can find them. Not good, but better than nothing.
* Source: https://docs.blender.org/manual/en/dev/data_system/files/media/image_formats.html
*/
private static final String[] extensions = new String[]
{ /* Windows Bitmap */".bmp",
/* Iris */ ".sgi", ".rgb", ".bw",
/* PNG */ ".png",
/* JPEG */ ".jpg", ".jpeg",
/* JPEG 2000 */ ".jp2", ".j2c",
/* Targa */".tga",
/* Cineon & DPX */".cin", ".dpx",
/* OpenEXR */ ".exr",
/* Radiance HDR */ ".hdr",
/* TIFF */ ".tif", ".tiff",
/* DDS (Direct X) */ ".dds" };
/**
* This method loads a image which is packed into the blender file.
* It makes use of all the registered AssetLoaders
* *
* @param inputStream * @param inputStream
* blender input stream * blender input stream
@ -60,76 +80,57 @@ import java.util.logging.Logger;
* @param flipY * @param flipY
* if the image should be flipped (does not work with DirectX image) * if the image should be flipped (does not work with DirectX image)
* @return loaded image or null if it could not be loaded * @return loaded image or null if it could not be loaded
* @deprecated This method has only been left in for API compability.
* Use loadTexture instead
*/ */
public Image loadImage(BlenderInputStream inputStream, int startPosition, boolean flipY) { public Image loadImage(AssetManager assetManager, BlenderInputStream inputStream, int startPosition, boolean flipY) {
// loading using AWT loader Texture tex = loadTexture(assetManager, inputStream, startPosition, flipY);
inputStream.setPosition(startPosition);
Image result = this.loadImage(inputStream, ImageType.AWT, flipY);
// loading using TGA loader
if (result == null) {
inputStream.setPosition(startPosition);
result = this.loadImage(inputStream, ImageType.TGA, flipY);
}
// loading using DDS loader
if (result == null) {
inputStream.setPosition(startPosition);
result = this.loadImage(inputStream, ImageType.DDS, flipY);
}
if (result == null) { if (tex == null) {
LOGGER.warning("Image could not be loaded by none of available loaders!"); return null;
} else {
return tex.getImage();
} }
return result;
} }
/** /**
* This method loads an image of a specified type from the given input stream. * This method loads a texture which is packed into the blender file.
* It makes use of all the registered AssetLoaders
* *
* @param inputStream * @param inputStream
* the input stream we read the image from * blender input stream
* @param imageType * @param startPosition
* the type of the image {@link ImageType} * position in the stream where the image data starts
* @param flipY * @param flipY
* if the image should be flipped (does not work with DirectX image) * if the image should be flipped (does not work with DirectX image)
* @return loaded image or null if it could not be loaded * @return loaded texture or null if it could not be loaded
*/ */
public Image loadImage(InputStream inputStream, ImageType imageType, boolean flipY) { public Texture loadTexture(AssetManager assetManager, BlenderInputStream inputStream, int startPosition, boolean flipY) {
Image result = null; inputStream.setPosition(startPosition);
switch (imageType) { TextureKey tKey;
case AWT: Texture result = null;
hdrLogger.setLevel(Level.SEVERE); // When we bruteforce try HDR on a non hdr file, it prints unreadable chars
for (String ext: extensions) {
tKey = new TextureKey("dummy" + ext, flipY);
try { try {
result = this.load(inputStream, flipY); result = assetManager.loadAssetFromStream(tKey, inputStream);
} catch (Exception e) { } catch (Exception e) {
LOGGER.warning("Unable to load image using AWT loader!"); continue;
}
break;
case DDS:
try {
result = ddsLoader.load(inputStream);
} catch (Exception e) {
LOGGER.warning("Unable to load image using DDS loader!");
}
break;
case TGA:
try {
result = TGALoader.load(inputStream, flipY);
} catch (Exception e) {
LOGGER.warning("Unable to load image using TGA loader!");
}
break;
default:
throw new IllegalStateException("Unknown image type: " + imageType);
}
return result;
} }
/** if (result != null) {
* Image types that can be loaded. AWT: png, jpg, jped or bmp TGA: tga DDS: DirectX image files break; // Could locate a possible asset
* }
* @author Marcin Roguski (Kaelthas) }
*/
private static enum ImageType { if (result == null) {
AWT, TGA, DDS; LOGGER.warning("Texture could not be loaded by any of the available loaders!\n"
+ "Since the file has been packed into the blender file, there is no"
+ "way for us to tell you which texture it was.");
}
return result;
} }
} }

View File

@ -206,7 +206,7 @@ public final class ImageUtils {
N.z = 1; N.z = 1;
N.divideLocal(den); N.divideLocal(den);
// setting thge pixel in the result image // setting the pixel in the result image
bumpMap.setRGB(x, y, ImageUtils.vectorToColor(N.x, N.y, N.z)); bumpMap.setRGB(x, y, ImageUtils.vectorToColor(N.x, N.y, N.z));
} }
} }
@ -422,7 +422,7 @@ public final class ImageUtils {
* pixel's X coordinate * pixel's X coordinate
* @param y * @param y
* pixel's Y coordinate * pixel's Y coordinate
* @return height reprezented by the given texture in the specified location * @return height represented by the given texture in the specified location
*/ */
private static int getHeight(BufferedImage image, int x, int y) { private static int getHeight(BufferedImage image, int x, int y) {
if (x < 0) { if (x < 0) {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2012 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -72,6 +72,7 @@ import com.jme3.texture.Texture.WrapMode;
import com.jme3.texture.Texture2D; import com.jme3.texture.Texture2D;
import com.jme3.texture.image.ColorSpace; import com.jme3.texture.image.ColorSpace;
import com.jme3.util.BufferUtils; import com.jme3.util.BufferUtils;
import com.jme3.util.PlaceholderAssets;
/** /**
* A class that is used in texture calculations. * A class that is used in texture calculations.
@ -251,7 +252,11 @@ public class TextureHelper extends AbstractBlenderHelper {
blenderContext.getInputStream().setPosition(dataFileBlock.getBlockPosition()); blenderContext.getInputStream().setPosition(dataFileBlock.getBlockPosition());
// Should the texture be flipped? It works for sinbad .. // Should the texture be flipped? It works for sinbad ..
result = new Texture2D(new ImageLoader().loadImage(blenderContext.getInputStream(), dataFileBlock.getBlockPosition(), true)); result = new ImageLoader().loadTexture(blenderContext.getAssetManager(), blenderContext.getInputStream(), dataFileBlock.getBlockPosition(), true);
if (result == null) {
result = new Texture2D(PlaceholderAssets.getPlaceholderImage(blenderContext.getAssetManager()));
LOGGER.fine("ImageLoader returned null. It probably failed to load the packed texture, using placeholder asset");
}
} }
} }
//} else { //} else {
@ -310,7 +315,7 @@ public class TextureHelper extends AbstractBlenderHelper {
* @param pos * @param pos
* the relative position (value of range <0, 1> (both inclusive)) * the relative position (value of range <0, 1> (both inclusive))
* @param size * @param size
* the size of the line the pixel lies on (width, heigth or * the size of the line the pixel lies on (width, height or
* depth) * depth)
* @return the integer index of the pixel on the line of the specified width * @return the integer index of the pixel on the line of the specified width
*/ */
@ -429,10 +434,10 @@ public class TextureHelper extends AbstractBlenderHelper {
} }
/** /**
* This method loads the textre from outside the blend file using the * This method loads the texture from outside the blend file using the
* AssetManager that the blend file was loaded with. It returns a texture * AssetManager that the blend file was loaded with. It returns a texture
* with a full assetKey that references the original texture so it later * with a full assetKey that references the original texture so it later
* doesn't need to ba packed when the model data is serialized. It searches * doesn't need to be packed when the model data is serialized. It searches
* the AssetManager for the full path if the model file is a relative path * the AssetManager for the full path if the model file is a relative path
* and will attempt to truncate the path if it is an absolute file path * and will attempt to truncate the path if it is an absolute file path
* until the path can be found in the AssetManager. If the texture can not * until the path can be found in the AssetManager. If the texture can not
@ -614,8 +619,15 @@ public class TextureHelper extends AbstractBlenderHelper {
int texflag = ((Number) textureData.mtex.getFieldValue("texflag")).intValue(); int texflag = ((Number) textureData.mtex.getFieldValue("texflag")).intValue();
boolean negateTexture = (texflag & 0x04) != 0; boolean negateTexture = (texflag & 0x04) != 0;
boolean colorSet = false;
for (int i = 0; i < mappings.length; ++i) { for (int i = 0; i < mappings.length; ++i) {
if ((mappings[i] & mapto.intValue()) != 0) { if ((mappings[i] & mapto.intValue()) != 0) {
if(mappings[i] == MaterialContext.MTEX_COL) {
colorSet = true;
} else if(colorSet && mappings[i] == MaterialContext.MTEX_ALPHA) {
continue;
}
CombinedTexture combinedTexture = new CombinedTexture(mappings[i], !skyTexture); CombinedTexture combinedTexture = new CombinedTexture(mappings[i], !skyTexture);
int blendType = ((Number) textureData.mtex.getFieldValue("blendtype")).intValue(); int blendType = ((Number) textureData.mtex.getFieldValue("blendtype")).intValue();
float[] color = new float[] { ((Number) textureData.mtex.getFieldValue("r")).floatValue(), ((Number) textureData.mtex.getFieldValue("g")).floatValue(), ((Number) textureData.mtex.getFieldValue("b")).floatValue() }; float[] color = new float[] { ((Number) textureData.mtex.getFieldValue("r")).floatValue(), ((Number) textureData.mtex.getFieldValue("g")).floatValue(), ((Number) textureData.mtex.getFieldValue("b")).floatValue() };
@ -646,8 +658,16 @@ public class TextureHelper extends AbstractBlenderHelper {
Map<Number, List<TextureData>> result = new HashMap<Number, List<TextureData>>(); Map<Number, List<TextureData>> result = new HashMap<Number, List<TextureData>>();
for (TextureData data : textures) { for (TextureData data : textures) {
Number mapto = (Number) data.mtex.getFieldValue("mapto"); Number mapto = (Number) data.mtex.getFieldValue("mapto");
boolean colorSet = false;
for (int i = 0; i < mappings.length; ++i) { for (int i = 0; i < mappings.length; ++i) {
if ((mappings[i] & mapto.intValue()) != 0) { if ((mappings[i] & mapto.intValue()) != 0) {
if(mappings[i] == MaterialContext.MTEX_COL) {
colorSet = true;
} else if(colorSet && mappings[i] == MaterialContext.MTEX_ALPHA) {
continue;
}
List<TextureData> datas = result.get(mappings[i]); List<TextureData> datas = result.get(mappings[i]);
if (datas == null) { if (datas == null) {
datas = new ArrayList<TextureData>(); datas = new ArrayList<TextureData>();

View File

@ -163,8 +163,18 @@ public class TextureBlenderAWT extends AbstractTextureBlender {
* the blender context * the blender context
*/ */
protected void blendPixel(float[] result, float[] materialColor, float[] pixelColor, BlenderContext blenderContext) { protected void blendPixel(float[] result, float[] materialColor, float[] pixelColor, BlenderContext blenderContext) {
// We calculate first the importance of the texture (colFactor * texAlphaValue)
float blendFactor = this.blendFactor * pixelColor[3]; float blendFactor = this.blendFactor * pixelColor[3];
float oneMinusFactor = 1.0f - blendFactor, col; // Then, we get the object material factor ((1 - texture importance) * matAlphaValue)
float oneMinusFactor = (1f - blendFactor) * materialColor[3];
// Finally, we can get the final blendFactor, which is 1 - the material factor.
blendFactor = 1f - oneMinusFactor;
// --- Compact method ---
// float blendFactor = this.blendFactor * (1f - ((1f - pixelColor[3]) * materialColor[3]));
// float oneMinusFactor = 1f - blendFactor;
float col;
switch (blendType) { switch (blendType) {
case MTEX_BLEND: case MTEX_BLEND:

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2012 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -40,7 +40,7 @@ public interface PhysicsCollisionGroupListener {
/** /**
* Called when two physics objects of the registered group are about to collide, <i>called from physics thread</i>.<br> * Called when two physics objects of the registered group are about to collide, <i>called from physics thread</i>.<br>
* This is only called when the collision will happen based on the collisionGroup and collideWithGroups * This is only called when the collision will happen based on the collisionGroup and collideWithGroups
* settings in the PhysicsCollisionObject. That is the case when <b>one</b> of the partys has the * settings in the PhysicsCollisionObject. That is the case when <b>one</b> of the parties has the
* collisionGroup of the other in its collideWithGroups set.<br> * collisionGroup of the other in its collideWithGroups set.<br>
* @param nodeA CollisionObject #1 * @param nodeA CollisionObject #1
* @param nodeB CollisionObject #2 * @param nodeB CollisionObject #2

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2012 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -41,6 +41,7 @@ import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager; import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort; import com.jme3.renderer.ViewPort;
import com.jme3.scene.Spatial; import com.jme3.scene.Spatial;
import com.jme3.scene.control.Control;
import com.jme3.util.clone.Cloner; import com.jme3.util.clone.Cloner;
import com.jme3.util.clone.JmeCloneable; import com.jme3.util.clone.JmeCloneable;
import java.io.IOException; import java.io.IOException;
@ -163,6 +164,12 @@ public abstract class AbstractPhysicsControl implements PhysicsControl, JmeClone
} }
@Deprecated
@Override
public Control cloneForSpatial(Spatial spatial) {
throw new UnsupportedOperationException();
}
@Override @Override
public void cloneFields( Cloner cloner, Object original ) { public void cloneFields( Cloner cloner, Object original ) {
this.spatial = cloner.clone(spatial); this.spatial = cloner.clone(spatial);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2012 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -48,9 +48,7 @@ import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager; import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort; import com.jme3.renderer.ViewPort;
import com.jme3.scene.Spatial; import com.jme3.scene.Spatial;
import com.jme3.scene.control.Control;
import com.jme3.util.TempVars; import com.jme3.util.TempVars;
import com.jme3.util.clone.Cloner;
import com.jme3.util.clone.JmeCloneable; import com.jme3.util.clone.JmeCloneable;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
@ -665,13 +663,6 @@ public class BetterCharacterControl extends AbstractPhysicsControl implements Ph
rigidBody.setUserObject(null); rigidBody.setUserObject(null);
} }
@Override
public Control cloneForSpatial(Spatial spatial) {
BetterCharacterControl control = new BetterCharacterControl(radius, height, mass);
control.setJumpForce(jumpForce);
return control;
}
@Override @Override
public Object jmeClone() { public Object jmeClone() {
BetterCharacterControl control = new BetterCharacterControl(radius, height, mass); BetterCharacterControl control = new BetterCharacterControl(radius, height, mass);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2012 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -89,21 +89,10 @@ public class CharacterControl extends PhysicsCharacter implements PhysicsControl
return spatial.getWorldTranslation(); return spatial.getWorldTranslation();
} }
@Deprecated
@Override @Override
public Control cloneForSpatial(Spatial spatial) { public Control cloneForSpatial(Spatial spatial) {
CharacterControl control = new CharacterControl(collisionShape, stepHeight); throw new UnsupportedOperationException();
control.setCcdMotionThreshold(getCcdMotionThreshold());
control.setCcdSweptSphereRadius(getCcdSweptSphereRadius());
control.setCollideWithGroups(getCollideWithGroups());
control.setCollisionGroup(getCollisionGroup());
control.setFallSpeed(getFallSpeed());
control.setGravity(getGravity());
control.setJumpSpeed(getJumpSpeed());
control.setMaxSlope(getMaxSlope());
control.setPhysicsLocation(getPhysicsLocation());
control.setUpAxis(getUpAxis());
control.setApplyPhysicsLocal(isApplyPhysicsLocal());
return control;
} }
@Override @Override

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2012 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -95,17 +95,10 @@ public class GhostControl extends PhysicsGhostObject implements PhysicsControl,
return spatial.getWorldRotation(); return spatial.getWorldRotation();
} }
@Deprecated
@Override @Override
public Control cloneForSpatial(Spatial spatial) { public Control cloneForSpatial(Spatial spatial) {
GhostControl control = new GhostControl(collisionShape); throw new UnsupportedOperationException();
control.setCcdMotionThreshold(getCcdMotionThreshold());
control.setCcdSweptSphereRadius(getCcdSweptSphereRadius());
control.setCollideWithGroups(getCollideWithGroups());
control.setCollisionGroup(getCollisionGroup());
control.setPhysicsLocation(getPhysicsLocation());
control.setPhysicsRotation(getPhysicsRotationMatrix());
control.setApplyPhysicsLocal(isApplyPhysicsLocal());
return control;
} }
@Override @Override

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2012 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -59,9 +59,7 @@ import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort; import com.jme3.renderer.ViewPort;
import com.jme3.scene.Node; import com.jme3.scene.Node;
import com.jme3.scene.Spatial; import com.jme3.scene.Spatial;
import com.jme3.scene.control.Control;
import com.jme3.util.TempVars; import com.jme3.util.TempVars;
import com.jme3.util.clone.Cloner;
import com.jme3.util.clone.JmeCloneable; import com.jme3.util.clone.JmeCloneable;
import java.io.IOException; import java.io.IOException;
import java.util.*; import java.util.*;
@ -73,7 +71,7 @@ import java.util.logging.Logger;
* use this control you need a model with an AnimControl and a * use this control you need a model with an AnimControl and a
* SkeletonControl.<br> This should be the case if you imported an animated * SkeletonControl.<br> This should be the case if you imported an animated
* model from Ogre or blender.<br> Note enabling/disabling the control * model from Ogre or blender.<br> Note enabling/disabling the control
* add/removes it from the physic space<br> <p> This control creates collision * add/removes it from the physics space<br> <p> This control creates collision
* shapes for each bones of the skeleton when you call * shapes for each bones of the skeleton when you call
* spatial.addControl(ragdollControl). <ul> <li>The shape is HullCollision shape * spatial.addControl(ragdollControl). <ul> <li>The shape is HullCollision shape
* based on the vertices associated with each bone and based on a tweakable * based on the vertices associated with each bone and based on a tweakable
@ -84,11 +82,11 @@ import java.util.logging.Logger;
* </ul> </p> <p> There are 2 modes for this control : <ul> <li><strong>The * </ul> </p> <p> There are 2 modes for this control : <ul> <li><strong>The
* kinematic modes :</strong><br> this is the default behavior, this means that * kinematic modes :</strong><br> this is the default behavior, this means that
* the collision shapes of the body are able to interact with physics enabled * the collision shapes of the body are able to interact with physics enabled
* objects. in this mode physic shapes follow the moovements of the animated * objects. in this mode physics shapes follow the motion of the animated
* skeleton (for example animated by a key framed animation) this mode is * skeleton (for example animated by a key framed animation) this mode is
* enabled by calling setKinematicMode(); </li> <li><strong>The ragdoll modes * enabled by calling setKinematicMode(); </li> <li><strong>The ragdoll modes
* :</strong><br> To enable this behavior, you need to call setRagdollMode() * :</strong><br> To enable this behavior, you need to call setRagdollMode()
* method. In this mode the charater is entirely controled by physics, so it * method. In this mode the character is entirely controlled by physics, so it
* will fall under the gravity and move if any force is applied to it. </li> * will fall under the gravity and move if any force is applied to it. </li>
* </ul> </p> * </ul> </p>
* *
@ -171,7 +169,7 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
} }
/** /**
* contruct a KinematicRagdollControl * construct a KinematicRagdollControl
*/ */
public KinematicRagdollControl() { public KinematicRagdollControl() {
baseRigidBody = new PhysicsRigidBody(new BoxCollisionShape(Vector3f.UNIT_XYZ.mult(0.1f)), 1); baseRigidBody = new PhysicsRigidBody(new BoxCollisionShape(Vector3f.UNIT_XYZ.mult(0.1f)), 1);
@ -201,7 +199,7 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
if(mode == Mode.IK){ if(mode == Mode.IK){
ikUpdate(tpf); ikUpdate(tpf);
} else if (mode == mode.Ragdoll && targetModel.getLocalTranslation().equals(modelPosition)) { } else if (mode == mode.Ragdoll && targetModel.getLocalTranslation().equals(modelPosition)) {
//if the ragdoll has the control of the skeleton, we update each bone with its position in physic world space. //if the ragdoll has the control of the skeleton, we update each bone with its position in physics world space.
ragDollUpdate(tpf); ragDollUpdate(tpf);
} else { } else {
kinematicUpdate(tpf); kinematicUpdate(tpf);
@ -217,12 +215,12 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
Vector3f position = vars.vect1; Vector3f position = vars.vect1;
//retrieving bone position in physic world space //retrieving bone position in physics world space
Vector3f p = link.rigidBody.getMotionState().getWorldLocation(); Vector3f p = link.rigidBody.getMotionState().getWorldLocation();
//transforming this position with inverse transforms of the model //transforming this position with inverse transforms of the model
targetModel.getWorldTransform().transformInverseVector(p, position); targetModel.getWorldTransform().transformInverseVector(p, position);
//retrieving bone rotation in physic world space //retrieving bone rotation in physics world space
Quaternion q = link.rigidBody.getMotionState().getWorldRotationQuat(); Quaternion q = link.rigidBody.getMotionState().getWorldRotationQuat();
//multiplying this rotation by the initialWorld rotation of the bone, //multiplying this rotation by the initialWorld rotation of the bone,
@ -255,7 +253,7 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
link.bone.setUserTransformsInModelSpace(position, tmpRot1); link.bone.setUserTransformsInModelSpace(position, tmpRot1);
} else { } else {
//boneList is not empty, this means some bones of the skeleton might not be associated with a collision shape. //boneList is not empty, this means some bones of the skeleton might not be associated with a collision shape.
//So we update them recusively //So we update them recursively
RagdollUtils.setTransform(link.bone, position, tmpRot1, false, boneList); RagdollUtils.setTransform(link.bone, position, tmpRot1, false, boneList);
} }
} }
@ -264,7 +262,7 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
} }
protected void kinematicUpdate(float tpf) { protected void kinematicUpdate(float tpf) {
//the ragdoll does not have the controll, so the keyframed animation updates the physic position of the physic bonces //the ragdoll does not have control, so the keyframed animation updates the physics position of the physics bonces
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
Quaternion tmpRot1 = vars.quat1; Quaternion tmpRot1 = vars.quat1;
Quaternion tmpRot2 = vars.quat2; Quaternion tmpRot2 = vars.quat2;
@ -420,7 +418,7 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
targetModel.getWorldRotation().mult(tmpRot1, tmpRot1); targetModel.getWorldRotation().mult(tmpRot1, tmpRot1);
tmpRot1.normalizeLocal(); tmpRot1.normalizeLocal();
//updating physic location/rotation of the physic bone //updating physics location/rotation of the physics bone
link.rigidBody.setPhysicsLocation(position); link.rigidBody.setPhysicsLocation(position);
link.rigidBody.setPhysicsRotation(tmpRot1); link.rigidBody.setPhysicsRotation(tmpRot1);
@ -707,9 +705,9 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
/** /**
* Enable or disable the ragdoll behaviour. if ragdollEnabled is true, the * Enable or disable the ragdoll behaviour. if ragdollEnabled is true, the
* character motion will only be powerd by physics else, the characted will * character motion will only be powered by physics else, the character will
* be animated by the keyframe animation, but will be able to physically * be animated by the keyframe animation, but will be able to physically
* interact with its physic environnement * interact with its physics environment
* *
* @param ragdollEnabled * @param ragdollEnabled
*/ */
@ -789,9 +787,9 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
} }
/** /**
* Set the control into Kinematic mode In theis mode, the collision shapes * Set the control into Kinematic mode In this mode, the collision shapes
* follow the movements of the skeleton, and can interact with physical * follow the movements of the skeleton, and can interact with physical
* environement * environment
*/ */
public void setKinematicMode() { public void setKinematicMode() {
if (mode != Mode.Kinematic) { if (mode != Mode.Kinematic) {
@ -820,7 +818,7 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
} }
/** /**
* retruns the mode of this control * returns the mode of this control
* *
* @return * @return
*/ */
@ -903,7 +901,7 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
} }
/** /**
* For internal use only specific render for the ragdoll(if debugging) * For internal use only specific render for the ragdoll (if debugging)
* *
* @param rm * @param rm
* @param vp * @param vp
@ -912,16 +910,6 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
public void render(RenderManager rm, ViewPort vp) { public void render(RenderManager rm, ViewPort vp) {
} }
@Override
public Control cloneForSpatial(Spatial spatial) {
KinematicRagdollControl control = new KinematicRagdollControl(preset, weightThreshold);
control.setMode(mode);
control.setRootMass(rootMass);
control.setWeightThreshold(weightThreshold);
control.setApplyPhysicsLocal(applyLocal);
return control;
}
@Override @Override
public Object jmeClone() { public Object jmeClone() {
KinematicRagdollControl control = new KinematicRagdollControl(preset, weightThreshold); KinematicRagdollControl control = new KinematicRagdollControl(preset, weightThreshold);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2012 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -53,7 +53,6 @@ import com.jme3.scene.shape.Box;
import com.jme3.scene.shape.Sphere; import com.jme3.scene.shape.Sphere;
import com.jme3.util.clone.Cloner; import com.jme3.util.clone.Cloner;
import com.jme3.util.clone.JmeCloneable; import com.jme3.util.clone.JmeCloneable;
import java.io.IOException; import java.io.IOException;
/** /**
@ -92,31 +91,10 @@ public class RigidBodyControl extends PhysicsRigidBody implements PhysicsControl
super(shape, mass); super(shape, mass);
} }
@Deprecated
@Override @Override
public Control cloneForSpatial(Spatial spatial) { public Control cloneForSpatial(Spatial spatial) {
RigidBodyControl control = new RigidBodyControl(collisionShape, mass); throw new UnsupportedOperationException();
control.setAngularFactor(getAngularFactor());
control.setAngularSleepingThreshold(getAngularSleepingThreshold());
control.setCcdMotionThreshold(getCcdMotionThreshold());
control.setCcdSweptSphereRadius(getCcdSweptSphereRadius());
control.setCollideWithGroups(getCollideWithGroups());
control.setCollisionGroup(getCollisionGroup());
control.setDamping(getLinearDamping(), getAngularDamping());
control.setFriction(getFriction());
control.setGravity(getGravity());
control.setKinematic(isKinematic());
control.setKinematicSpatial(isKinematicSpatial());
control.setLinearSleepingThreshold(getLinearSleepingThreshold());
control.setPhysicsLocation(getPhysicsLocation(null));
control.setPhysicsRotation(getPhysicsRotationMatrix(null));
control.setRestitution(getRestitution());
if (mass > 0) {
control.setAngularVelocity(getAngularVelocity());
control.setLinearVelocity(getLinearVelocity());
}
control.setApplyPhysicsLocal(isApplyPhysicsLocal());
return control;
} }
@Override @Override

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2012 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -43,7 +43,6 @@ import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f; import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager; import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort; import com.jme3.renderer.ViewPort;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial; import com.jme3.scene.Spatial;
import com.jme3.scene.control.Control; import com.jme3.scene.control.Control;
import com.jme3.util.clone.Cloner; import com.jme3.util.clone.Cloner;
@ -108,54 +107,10 @@ public class VehicleControl extends PhysicsVehicle implements PhysicsControl, Jm
return spatial.getWorldRotation(); return spatial.getWorldRotation();
} }
@Deprecated
@Override @Override
public Control cloneForSpatial(Spatial spatial) { public Control cloneForSpatial(Spatial spatial) {
VehicleControl control = new VehicleControl(collisionShape, mass); throw new UnsupportedOperationException();
control.setAngularFactor(getAngularFactor());
control.setAngularSleepingThreshold(getAngularSleepingThreshold());
control.setAngularVelocity(getAngularVelocity());
control.setCcdMotionThreshold(getCcdMotionThreshold());
control.setCcdSweptSphereRadius(getCcdSweptSphereRadius());
control.setCollideWithGroups(getCollideWithGroups());
control.setCollisionGroup(getCollisionGroup());
control.setDamping(getLinearDamping(), getAngularDamping());
control.setFriction(getFriction());
control.setGravity(getGravity());
control.setKinematic(isKinematic());
control.setLinearSleepingThreshold(getLinearSleepingThreshold());
control.setLinearVelocity(getLinearVelocity());
control.setPhysicsLocation(getPhysicsLocation());
control.setPhysicsRotation(getPhysicsRotationMatrix());
control.setRestitution(getRestitution());
control.setFrictionSlip(getFrictionSlip());
control.setMaxSuspensionTravelCm(getMaxSuspensionTravelCm());
control.setSuspensionStiffness(getSuspensionStiffness());
control.setSuspensionCompression(tuning.suspensionCompression);
control.setSuspensionDamping(tuning.suspensionDamping);
control.setMaxSuspensionForce(getMaxSuspensionForce());
for (Iterator<VehicleWheel> it = wheels.iterator(); it.hasNext();) {
VehicleWheel wheel = it.next();
VehicleWheel newWheel = control.addWheel(wheel.getLocation(), wheel.getDirection(), wheel.getAxle(), wheel.getRestLength(), wheel.getRadius(), wheel.isFrontWheel());
newWheel.setFrictionSlip(wheel.getFrictionSlip());
newWheel.setMaxSuspensionTravelCm(wheel.getMaxSuspensionTravelCm());
newWheel.setSuspensionStiffness(wheel.getSuspensionStiffness());
newWheel.setWheelsDampingCompression(wheel.getWheelsDampingCompression());
newWheel.setWheelsDampingRelaxation(wheel.getWheelsDampingRelaxation());
newWheel.setMaxSuspensionForce(wheel.getMaxSuspensionForce());
//TODO: bad way finding children!
if (spatial instanceof Node) {
Node node = (Node) spatial;
Spatial wheelSpat = node.getChild(wheel.getWheelSpatial().getName());
if (wheelSpat != null) {
newWheel.setWheelSpatial(wheelSpat);
}
}
}
control.setApplyPhysicsLocal(isApplyPhysicsLocal());
return control;
} }
@Override @Override

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2012 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -123,7 +123,7 @@ public class RagdollUtils {
/** /**
* Create a hull collision shape from linked vertices to this bone. * Create a hull collision shape from linked vertices to this bone.
* Vertices have to be previoulsly gathered in a map using buildPointMap method * Vertices have to be previously gathered in a map using buildPointMap method
* *
* @param pointsMap * @param pointsMap
* @param boneIndices * @param boneIndices
@ -160,7 +160,7 @@ public class RagdollUtils {
return new HullCollisionShape(p); return new HullCollisionShape(p);
} }
//retruns the list of bone indices of the given bone and its child(if they are not in the boneList) //returns the list of bone indices of the given bone and its child (if they are not in the boneList)
public static List<Integer> getBoneIndices(Bone bone, Skeleton skeleton, Set<String> boneList) { public static List<Integer> getBoneIndices(Bone bone, Skeleton skeleton, Set<String> boneList) {
List<Integer> list = new LinkedList<Integer>(); List<Integer> list = new LinkedList<Integer>();
if (boneList.isEmpty()) { if (boneList.isEmpty()) {
@ -266,7 +266,7 @@ public class RagdollUtils {
/** /**
* Updates a bone position and rotation. * Updates a bone position and rotation.
* if the child bones are not in the bone list this means, they are not associated with a physic shape. * if the child bones are not in the bone list this means, they are not associated with a physics shape.
* So they have to be updated * So they have to be updated
* @param bone the bone * @param bone the bone
* @param pos the position * @param pos the position

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2012 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -235,7 +235,7 @@ public class PhysicsSpace {
// collides = (bp1.collisionFilterGroup & bp.collisionFilterMask) != 0; // collides = (bp1.collisionFilterGroup & bp.collisionFilterMask) != 0;
// } // }
// if (collides) { // if (collides) {
// assert (bp.clientObject instanceof com.bulletphysics.collision.dispatch.CollisionObject && bp.clientObject instanceof com.bulletphysics.collision.dispatch.CollisionObject); // assert (bp.clientObject instanceof com.bulletphysics.collision.dispatch.CollisionObject && bp1.clientObject instanceof com.bulletphysics.collision.dispatch.CollisionObject);
// com.bulletphysics.collision.dispatch.CollisionObject colOb = (com.bulletphysics.collision.dispatch.CollisionObject) bp.clientObject; // com.bulletphysics.collision.dispatch.CollisionObject colOb = (com.bulletphysics.collision.dispatch.CollisionObject) bp.clientObject;
// com.bulletphysics.collision.dispatch.CollisionObject colOb1 = (com.bulletphysics.collision.dispatch.CollisionObject) bp1.clientObject; // com.bulletphysics.collision.dispatch.CollisionObject colOb1 = (com.bulletphysics.collision.dispatch.CollisionObject) bp1.clientObject;
// assert (colOb.getUserPointer() != null && colOb1.getUserPointer() != null); // assert (colOb.getUserPointer() != null && colOb1.getUserPointer() != null);
@ -954,7 +954,7 @@ public class PhysicsSpace {
* determinism in physics. For example a maximum number of 2 can compensate * determinism in physics. For example a maximum number of 2 can compensate
* for framerates as low as 30fps when the physics has the default accuracy * for framerates as low as 30fps when the physics has the default accuracy
* of 60 fps. Note that setting this value too high can make the physics * of 60 fps. Note that setting this value too high can make the physics
* drive down its own fps in case its overloaded. * drive down its own fps in case it's overloaded.
* *
* @param steps The maximum number of extra steps, default is 4. * @param steps The maximum number of extra steps, default is 4.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2012 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -96,7 +96,7 @@ public abstract class PhysicsCollisionObject implements Savable {
* Sets the collision group number for this physics object. <br> * Sets the collision group number for this physics object. <br>
* The groups are integer bit masks and some pre-made variables are available in CollisionObject. * The groups are integer bit masks and some pre-made variables are available in CollisionObject.
* All physics objects are by default in COLLISION_GROUP_01.<br> * All physics objects are by default in COLLISION_GROUP_01.<br>
* Two object will collide when <b>one</b> of the partys has the * Two object will collide when <b>one</b> of the parties has the
* collisionGroup of the other in its collideWithGroups set. * collisionGroup of the other in its collideWithGroups set.
* @param collisionGroup the collisionGroup to set * @param collisionGroup the collisionGroup to set
*/ */
@ -109,7 +109,7 @@ public abstract class PhysicsCollisionObject implements Savable {
/** /**
* Add a group that this object will collide with.<br> * Add a group that this object will collide with.<br>
* Two object will collide when <b>one</b> of the partys has the * Two object will collide when <b>one</b> of the parties has the
* collisionGroup of the other in its collideWithGroups set.<br> * collisionGroup of the other in its collideWithGroups set.<br>
* @param collisionGroup * @param collisionGroup
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2012 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -44,7 +44,7 @@ import java.util.logging.Logger;
/** /**
* <i>From bullet manual:</i><br> * <i>From bullet manual:</i><br>
* To create ragdolls, the conve twist constraint is very useful for limbs like the upper arm. * To create ragdolls, the cone twist constraint is very useful for limbs like the upper arm.
* It is a special point to point constraint that adds cone and twist axis limits. * It is a special point to point constraint that adds cone and twist axis limits.
* The x-axis serves as twist axis. * The x-axis serves as twist axis.
* @author normenhansen * @author normenhansen

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2012 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -121,7 +121,7 @@ public class HingeJoint extends PhysicsJoint {
* @param high the high limit in radians. * @param high the high limit in radians.
* @param _softness the factor at which the velocity error correction starts operating,i.e a softness of 0.9 means that the vel. corr starts at 90% of the limit range. * @param _softness the factor at which the velocity error correction starts operating,i.e a softness of 0.9 means that the vel. corr starts at 90% of the limit range.
* @param _biasFactor the magnitude of the position correction. It tells you how strictly the position error (drift ) is corrected. * @param _biasFactor the magnitude of the position correction. It tells you how strictly the position error (drift ) is corrected.
* @param _relaxationFactor the rate at which velocity errors are corrected. This can be seen as the strength of the limits. A low value will make the the limits more spongy. * @param _relaxationFactor the rate at which velocity errors are corrected. This can be seen as the strength of the limits. A low value will make the limits more spongy.
*/ */
public void setLimit(float low, float high, float _softness, float _biasFactor, float _relaxationFactor) { public void setLimit(float low, float high, float _softness, float _biasFactor, float _relaxationFactor) {
biasFactor = _biasFactor; biasFactor = _biasFactor;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2012 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -265,7 +265,7 @@ public class PhysicsRigidBody extends PhysicsCollisionObject {
// } // }
/** /**
* Sets the node to kinematic mode. in this mode the node is not affected by physics * Sets the node to kinematic mode. in this mode the node is not affected by physics
* but affects other physics objects. Iits kinetic force is calculated by the amount * but affects other physics objects. Its kinetic force is calculated by the amount
* of movement it is exposed to and its weight. * of movement it is exposed to and its weight.
* @param kinematic * @param kinematic
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2012 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -283,8 +283,8 @@ public class PhysicsVehicle extends PhysicsRigidBody {
} }
/** /**
* This vaue caps the maximum suspension force, raise this above the default 6000 if your suspension cannot * This value caps the maximum suspension force, raise this above the default 6000 if your suspension cannot
* handle the weight of your vehcile. * handle the weight of your vehicle.
* @param maxSuspensionForce * @param maxSuspensionForce
*/ */
public void setMaxSuspensionForce(float maxSuspensionForce) { public void setMaxSuspensionForce(float maxSuspensionForce) {
@ -292,8 +292,8 @@ public class PhysicsVehicle extends PhysicsRigidBody {
} }
/** /**
* This vaue caps the maximum suspension force, raise this above the default 6000 if your suspension cannot * This value caps the maximum suspension force, raise this above the default 6000 if your suspension cannot
* handle the weight of your vehcile. * handle the weight of your vehicle.
* @param wheel * @param wheel
* @param maxSuspensionForce * @param maxSuspensionForce
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2012 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -242,7 +242,7 @@ public class VehicleWheel implements Savable {
/** /**
* The maximum suspension force, raise this above the default 6000 if your suspension cannot * The maximum suspension force, raise this above the default 6000 if your suspension cannot
* handle the weight of your vehcile. * handle the weight of your vehicle.
* @param maxSuspensionTravelCm * @param maxSuspensionTravelCm
*/ */
public void setMaxSuspensionForce(float maxSuspensionForce) { public void setMaxSuspensionForce(float maxSuspensionForce) {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2012 jMonkeyEngine * Copyright (c) 2009-2017 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -35,6 +35,7 @@ import com.jme3.bullet.collision.shapes.CollisionShape;
import com.jme3.bullet.collision.shapes.CompoundCollisionShape; import com.jme3.bullet.collision.shapes.CompoundCollisionShape;
import com.jme3.bullet.collision.shapes.infos.ChildCollisionShape; import com.jme3.bullet.collision.shapes.infos.ChildCollisionShape;
import com.jme3.math.Matrix3f; import com.jme3.math.Matrix3f;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry; import com.jme3.scene.Geometry;
import com.jme3.scene.Mesh; import com.jme3.scene.Mesh;
import com.jme3.scene.Node; import com.jme3.scene.Node;
@ -111,9 +112,16 @@ public class DebugShapeFactory {
public static Mesh getDebugMesh(CollisionShape shape) { public static Mesh getDebugMesh(CollisionShape shape) {
Mesh mesh = new Mesh(); Mesh mesh = new Mesh();
mesh = new Mesh();
DebugMeshCallback callback = new DebugMeshCallback(); DebugMeshCallback callback = new DebugMeshCallback();
/*
* Populate the mesh based on an unscaled shape;
* the shape's scale will be applied later, to the geometry.
*/
Vector3f savedScale = shape.getScale().clone();
shape.setScale(Vector3f.UNIT_XYZ);
getVertices(shape.getObjectId(), callback); getVertices(shape.getObjectId(), callback);
shape.setScale(savedScale);
mesh.setBuffer(Type.Position, 3, callback.getVertices()); mesh.setBuffer(Type.Position, 3, callback.getVertices());
mesh.getFloatBuffer(Type.Position).clear(); mesh.getFloatBuffer(Type.Position).clear();
return mesh; return mesh;

View File

@ -15,7 +15,7 @@ import java.lang.annotation.Target;
* annotations of the same name at a single location. * annotations of the same name at a single location.
* *
* Example: * Example:
* <!-- &nbsp; is a hack that prevents @ from being the first charater on the line, which confuses Javadoc --> * <!-- &nbsp; is a hack that prevents @ from being the first character on the line, which confuses Javadoc -->
* <code><pre> * <code><pre>
* &nbsp; @DefaultQualifiers({ * &nbsp; @DefaultQualifiers({
* &nbsp; @DefaultQualifier("NonNull"), * &nbsp; @DefaultQualifier("NonNull"),

View File

@ -68,7 +68,11 @@ public final class AnimChannel {
private float blendAmount = 1f; private float blendAmount = 1f;
private float blendRate = 0; private float blendRate = 0;
AnimChannel(AnimControl control){ public AnimChannel(){
}
public AnimChannel(AnimControl control){
this.control = control; this.control = control;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2012 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -34,19 +34,16 @@ package com.jme3.animation;
import com.jme3.export.*; import com.jme3.export.*;
import com.jme3.renderer.RenderManager; import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort; import com.jme3.renderer.ViewPort;
import com.jme3.scene.Mesh;
import com.jme3.scene.Spatial; import com.jme3.scene.Spatial;
import com.jme3.scene.control.AbstractControl; import com.jme3.scene.control.AbstractControl;
import com.jme3.scene.control.Control; import com.jme3.util.TempVars;
import com.jme3.util.clone.Cloner; import com.jme3.util.clone.Cloner;
import com.jme3.util.clone.JmeCloneable; import com.jme3.util.clone.JmeCloneable;
import com.jme3.util.TempVars;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
/** /**
* <code>AnimControl</code> is a Spatial control that allows manipulation * <code>AnimControl</code> is a Spatial control that allows manipulation
@ -108,32 +105,6 @@ public final class AnimControl extends AbstractControl implements Cloneable, Jme
public AnimControl() { public AnimControl() {
} }
/**
* Internal use only.
*/
@Override
public Control cloneForSpatial(Spatial spatial) {
try {
AnimControl clone = (AnimControl) super.clone();
clone.spatial = spatial;
clone.channels = new ArrayList<AnimChannel>();
clone.listeners = new ArrayList<AnimEventListener>();
if (skeleton != null) {
clone.skeleton = new Skeleton(skeleton);
}
// animationMap is cloned, but only ClonableTracks will be cloned as they need a reference to a cloned spatial
for (Entry<String, Animation> animEntry : animationMap.entrySet()) {
clone.animationMap.put(animEntry.getKey(), animEntry.getValue().cloneForSpatial(spatial));
}
return clone;
} catch (CloneNotSupportedException ex) {
throw new AssertionError();
}
}
@Override @Override
public Object jmeClone() { public Object jmeClone() {
AnimControl clone = (AnimControl) super.jmeClone(); AnimControl clone = (AnimControl) super.jmeClone();

View File

@ -31,17 +31,15 @@
*/ */
package com.jme3.animation; package com.jme3.animation;
import static com.jme3.animation.LoopMode.Cycle;
import static com.jme3.animation.LoopMode.DontLoop;
import static com.jme3.animation.LoopMode.Loop;
/** /**
* *
* @author Nehon * @author Nehon
*/ */
public class AnimationUtils { public class AnimationUtils {
public AnimationUtils(){
}
/** /**
* Clamps the time according to duration and loopMode * Clamps the time according to duration and loopMode
* @param time * @param time
@ -50,7 +48,7 @@ public class AnimationUtils {
* @return * @return
*/ */
public static float clampWrapTime(float time, float duration, LoopMode loopMode){ public static float clampWrapTime(float time, float duration, LoopMode loopMode){
if (time == 0) { if (time == 0 || duration == 0) {
return 0; // prevent division by 0 errors return 0; // prevent division by 0 errors
} }
switch (loopMode) { switch (loopMode) {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2017 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -32,15 +32,15 @@
package com.jme3.animation; package com.jme3.animation;
import com.jme3.export.*; import com.jme3.export.*;
import com.jme3.material.MatParamOverride;
import com.jme3.math.*; import com.jme3.math.*;
import com.jme3.scene.Geometry; import com.jme3.scene.*;
import com.jme3.scene.Mesh; import com.jme3.shader.VarType;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.util.SafeArrayList; import com.jme3.util.SafeArrayList;
import com.jme3.util.TempVars; import com.jme3.util.TempVars;
import com.jme3.util.clone.JmeCloneable;
import com.jme3.util.clone.Cloner; import com.jme3.util.clone.Cloner;
import com.jme3.util.clone.JmeCloneable;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
@ -550,7 +550,7 @@ public final class Bone implements Savable, JmeCloneable {
} }
/** /**
* Updates world transforms for this bone and it's children. * Updates world transforms for this bone and its children.
*/ */
public final void update() { public final void update() {
this.updateModelTransforms(); this.updateModelTransforms();
@ -590,7 +590,7 @@ public final class Bone implements Savable, JmeCloneable {
} }
/** /**
* Reset the bone and it's children to bind pose. * Reset the bone and its children to bind pose.
*/ */
final void reset() { final void reset() {
if (!userControl) { if (!userControl) {
@ -677,7 +677,7 @@ public final class Bone implements Savable, JmeCloneable {
modelPos.set(translation); modelPos.set(translation);
modelRot.set(rotation); modelRot.set(rotation);
//if there is an attached Node we need to set it's local transforms too. //if there is an attached Node we need to set its local transforms too.
if(attachNode != null){ if(attachNode != null){
attachNode.setLocalTranslation(translation); attachNode.setLocalTranslation(translation);
attachNode.setLocalRotation(rotation); attachNode.setLocalRotation(rotation);
@ -723,6 +723,8 @@ public final class Bone implements Savable, JmeCloneable {
if (attachNode == null) { if (attachNode == null) {
attachNode = new Node(name + "_attachnode"); attachNode = new Node(name + "_attachnode");
attachNode.setUserData("AttachedBone", this); attachNode.setUserData("AttachedBone", this);
//We don't want the node to have a numBone set by a parent node so we force it to null
attachNode.addMatParamOverride(new MatParamOverride(VarType.Int, "NumberOfBones", null));
} }
return attachNode; return attachNode;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2012 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -35,6 +35,8 @@ import com.jme3.export.*;
import com.jme3.math.Quaternion; import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f; import com.jme3.math.Vector3f;
import com.jme3.util.TempVars; import com.jme3.util.TempVars;
import com.jme3.util.clone.Cloner;
import com.jme3.util.clone.JmeCloneable;
import java.io.IOException; import java.io.IOException;
import java.util.BitSet; import java.util.BitSet;
@ -43,10 +45,10 @@ import java.util.BitSet;
* *
* @author Kirill Vainer * @author Kirill Vainer
*/ */
public final class BoneTrack implements Track { public final class BoneTrack implements JmeCloneable, Track {
/** /**
* Bone index in the skeleton which this track effects. * Bone index in the skeleton which this track affects.
*/ */
private int targetBoneIndex; private int targetBoneIndex;
@ -138,16 +140,23 @@ public final class BoneTrack implements Track {
/** /**
* Set the translations and rotations for this bone track * Set the translations and rotations for this bone track
* @param times a float array with the time of each frame *
* @param translations the translation of the bone for each frame * @param times the time of each frame, measured from the start of the track
* @param rotations the rotation of the bone for each frame * (not null, length&gt;0)
* @param translations the translation of the bone for each frame (not null,
* same length as times)
* @param rotations the rotation of the bone for each frame (not null, same
* length as times)
*/ */
public void setKeyframes(float[] times, Vector3f[] translations, Quaternion[] rotations) { public void setKeyframes(float[] times, Vector3f[] translations, Quaternion[] rotations) {
if (times.length == 0) { if (times.length == 0) {
throw new RuntimeException("BoneTrack with no keyframes!"); throw new RuntimeException("BoneTrack with no keyframes!");
} }
assert times.length == translations.length && times.length == rotations.length; assert translations != null;
assert times.length == translations.length;
assert rotations != null;
assert times.length == rotations.length;
this.times = times; this.times = times;
this.translations = new CompactVector3Array(); this.translations = new CompactVector3Array();
@ -160,15 +169,19 @@ public final class BoneTrack implements Track {
/** /**
* Set the translations, rotations and scales for this bone track * Set the translations, rotations and scales for this bone track
* @param times a float array with the time of each frame *
* @param translations the translation of the bone for each frame * @param times the time of each frame, measured from the start of the track
* @param rotations the rotation of the bone for each frame * (not null, length&gt;0)
* @param scales the scale of the bone for each frame * @param translations the translation of the bone for each frame (not null,
* same length as times)
* @param rotations the rotation of the bone for each frame (not null, same
* length as times)
* @param scales the scale of the bone for each frame (ignored if null)
*/ */
public void setKeyframes(float[] times, Vector3f[] translations, Quaternion[] rotations, Vector3f[] scales) { public void setKeyframes(float[] times, Vector3f[] translations, Quaternion[] rotations, Vector3f[] scales) {
this.setKeyframes(times, translations, rotations); this.setKeyframes(times, translations, rotations);
assert times.length == scales.length;
if (scales != null) { if (scales != null) {
assert times.length == scales.length;
this.scales = new CompactVector3Array(); this.scales = new CompactVector3Array();
this.scales.add(scales); this.scales.add(scales);
this.scales.freeze(); this.scales.freeze();
@ -263,29 +276,44 @@ public final class BoneTrack implements Track {
} }
/** /**
* This method creates a clone of the current object. * Create a deep clone of this track.
* @return a clone of the current object *
* @return a new track
*/ */
@Override @Override
public BoneTrack clone() { public BoneTrack clone() {
int tablesLength = times.length; return Cloner.deepClone(this);
float[] times = this.times.clone();
Vector3f[] sourceTranslations = this.getTranslations();
Quaternion[] sourceRotations = this.getRotations();
Vector3f[] sourceScales = this.getScales();
Vector3f[] translations = new Vector3f[tablesLength];
Quaternion[] rotations = new Quaternion[tablesLength];
Vector3f[] scales = new Vector3f[tablesLength];
for (int i = 0; i < tablesLength; ++i) {
translations[i] = sourceTranslations[i].clone();
rotations[i] = sourceRotations[i].clone();
scales[i] = sourceScales != null ? sourceScales[i].clone() : new Vector3f(1.0f, 1.0f, 1.0f);
} }
// Need to use the constructor here because of the final fields used in this class /**
return new BoneTrack(targetBoneIndex, times, translations, rotations, scales); * Create a shallow clone for the JME cloner.
*
* @return a new track
*/
@Override
public BoneTrack jmeClone() {
try {
return (BoneTrack) super.clone();
} catch (CloneNotSupportedException exception) {
throw new RuntimeException("Can't clone track", exception);
}
}
/**
* Callback from {@link com.jme3.util.clone.Cloner} to convert this
* shallow-cloned track into a deep-cloned one, using the specified cloner
* to resolve copied fields.
*
* @param cloner the cloner currently cloning this control (not null)
* @param original the track from which this track was shallow-cloned
* (unused)
*/
@Override
public void cloneFields(Cloner cloner, Object original) {
translations = cloner.clone(translations);
rotations = cloner.clone(rotations);
scales = cloner.clone(scales);
times = cloner.clone(times);
} }
@Override @Override

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2012 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -31,6 +31,8 @@
*/ */
package com.jme3.animation; package com.jme3.animation;
import com.jme3.util.clone.Cloner;
import com.jme3.util.clone.JmeCloneable;
import java.lang.reflect.Array; import java.lang.reflect.Array;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -40,7 +42,7 @@ import java.util.Map;
* @author Lim, YongHoon * @author Lim, YongHoon
* @param <T> * @param <T>
*/ */
public abstract class CompactArray<T> { public abstract class CompactArray<T> implements JmeCloneable {
private Map<T, Integer> indexPool = new HashMap<T, Integer>(); private Map<T, Integer> indexPool = new HashMap<T, Integer>();
protected int[] index; protected int[] index;
@ -68,6 +70,7 @@ public abstract class CompactArray<T> {
* They are serialized automatically when get() method is called. * They are serialized automatically when get() method is called.
* @param objArray * @param objArray
*/ */
@SuppressWarnings("unchecked")
public void add(T... objArray) { public void add(T... objArray) {
if (objArray == null || objArray.length == 0) { if (objArray == null || objArray.length == 0) {
return; return;
@ -186,10 +189,11 @@ public abstract class CompactArray<T> {
} }
/** /**
* retrun an array of indices for the given objects * Return an array of indices for the given objects
* @param objArray * @param objArray
* @return * @return
*/ */
@SuppressWarnings("unchecked")
public final int[] getIndex(T... objArray) { public final int[] getIndex(T... objArray) {
int[] index = new int[objArray.length]; int[] index = new int[objArray.length];
for (int i = 0; i < index.length; i++) { for (int i = 0; i < index.length; i++) {
@ -228,6 +232,7 @@ public abstract class CompactArray<T> {
* decompress and return object array * decompress and return object array
* @return decompress and return object array * @return decompress and return object array
*/ */
@SuppressWarnings("unchecked")
public final T[] toObjectArray() { public final T[] toObjectArray() {
try { try {
T[] compactArr = (T[]) Array.newInstance(getElementClass(), getSerializedSize() / getTupleSize()); T[] compactArr = (T[]) Array.newInstance(getElementClass(), getSerializedSize() / getTupleSize());
@ -247,6 +252,47 @@ public abstract class CompactArray<T> {
} }
} }
/**
* Create a deep clone of this array.
*
* @return a new array
* @throws java.lang.CloneNotSupportedException
*/
@Override
public Object clone() throws CloneNotSupportedException {
return Cloner.deepClone(this);
}
/**
* Create a shallow clone for the JME cloner.
*
* @return a new array
*/
@Override
public Object jmeClone() {
try {
return super.clone();
} catch (CloneNotSupportedException exception) {
throw new RuntimeException("Can't clone array", exception);
}
}
/**
* Callback from {@link com.jme3.util.clone.Cloner} to convert this
* shallow-cloned array into a deep-cloned one, using the specified cloner
* to resolve copied fields.
*
* @param cloner the cloner currently cloning this control (not null)
* @param original the array from which this array was shallow-cloned
* (unused)
*/
@Override
public void cloneFields(Cloner cloner, Object original) {
indexPool = cloner.clone(indexPool);
index = cloner.clone(index);
array = cloner.clone(array);
}
/** /**
* serialize object * serialize object
* @param compactIndex compacted object index * @param compactIndex compacted object index

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2012 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -42,18 +42,16 @@ import com.jme3.scene.Node;
import com.jme3.scene.Spatial; import com.jme3.scene.Spatial;
import com.jme3.scene.Spatial.CullHint; import com.jme3.scene.Spatial.CullHint;
import com.jme3.scene.control.AbstractControl; import com.jme3.scene.control.AbstractControl;
import com.jme3.scene.control.Control;
import com.jme3.util.TempVars; import com.jme3.util.TempVars;
import com.jme3.util.clone.Cloner; import com.jme3.util.clone.Cloner;
import com.jme3.util.clone.JmeCloneable;
import java.io.IOException; import java.io.IOException;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
/** /**
* EffectTrack is a track to add to an existing animation, to emit particles * EffectTrack is a track to add to an existing animation, to emit particles
* during animations for example : exhausts, dust raised by foot steps, shock * during animations for example: exhaust, dust raised by footsteps, shock
* waves, lightnings etc... * waves, lightning, etc...
* *
* usage is * usage is
* <pre> * <pre>
@ -62,9 +60,9 @@ import java.util.logging.Logger;
* control.getAnim("TheAnim").addTrack(track); * control.getAnim("TheAnim").addTrack(track);
* </pre> * </pre>
* *
* if the emitter has emits 0 particles per seconds emmitAllPArticles will be * if the emitter emits 0 particles per second, emitAllPArticles will be
* called on it at time 0 + startOffset. if it he it has more it will start * called on it at time 0 + startOffset. if it has more it will start
* emit normally at time 0 + startOffset. * emitting normally at time 0 + startOffset.
* *
* *
* @author Nehon * @author Nehon
@ -132,19 +130,6 @@ public class EffectTrack implements ClonableTrack {
@Override @Override
protected void controlRender(RenderManager rm, ViewPort vp) { protected void controlRender(RenderManager rm, ViewPort vp) {
} }
@Override
public Control cloneForSpatial(Spatial spatial) {
KillParticleControl c = new KillParticleControl();
//this control should be removed as it shouldn't have been persisted in the first place
//In the quest to find the less hackish solution to achieve this,
//making it remove itself from the spatial in the first update loop when loaded was the less bad.
c.remove = true;
c.setSpatial(spatial);
return c;
}
}; };
//Anim listener that stops the Emmitter when the animation is finished or changed. //Anim listener that stops the Emmitter when the animation is finished or changed.
@ -213,7 +198,7 @@ public class EffectTrack implements ClonableTrack {
control.addListener(new OnEndListener()); control.addListener(new OnEndListener());
initialized = true; initialized = true;
} }
//checking fo time to trigger the effect //checking for time to trigger the effect
if (!emitted && time >= startOffset) { if (!emitted && time >= startOffset) {
emitted = true; emitted = true;
emitter.setCullHint(CullHint.Dynamic); emitter.setCullHint(CullHint.Dynamic);
@ -430,7 +415,7 @@ public class EffectTrack implements ClonableTrack {
*/ */
public void write(JmeExporter ex) throws IOException { public void write(JmeExporter ex) throws IOException {
OutputCapsule out = ex.getCapsule(this); OutputCapsule out = ex.getCapsule(this);
//reseting the particle emission rate on the emitter before saving. //reset the particle emission rate on the emitter before saving.
emitter.setParticlesPerSec(particlesPerSeconds); emitter.setParticlesPerSec(particlesPerSeconds);
out.write(emitter, "emitter", null); out.write(emitter, "emitter", null);
out.write(particlesPerSeconds, "particlesPerSeconds", 0); out.write(particlesPerSeconds, "particlesPerSeconds", 0);
@ -449,7 +434,7 @@ public class EffectTrack implements ClonableTrack {
public void read(JmeImporter im) throws IOException { public void read(JmeImporter im) throws IOException {
InputCapsule in = im.getCapsule(this); InputCapsule in = im.getCapsule(this);
this.particlesPerSeconds = in.readFloat("particlesPerSeconds", 0); this.particlesPerSeconds = in.readFloat("particlesPerSeconds", 0);
//reading the emitter even if the track will then reference its cloned counter part if it's loaded with the assetManager. //reading the emitter even if the track will then reference its cloned counterpart if it's loaded with the assetManager.
//This also avoid null pointer exception if the model is not loaded via the AssetManager. //This also avoid null pointer exception if the model is not loaded via the AssetManager.
emitter = (ParticleEmitter) in.readSavable("emitter", null); emitter = (ParticleEmitter) in.readSavable("emitter", null);
emitter.setParticlesPerSec(0); emitter.setParticlesPerSec(0);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2012 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -53,7 +53,7 @@ public final class Skeleton implements Savable, JmeCloneable {
private Bone[] boneList; private Bone[] boneList;
/** /**
* Contains the skinning matrices, multiplying it by a vertex effected by a bone * Contains the skinning matrices, multiplying it by a vertex affected by a bone
* will cause it to go to the animated position. * will cause it to go to the animated position.
*/ */
private transient Matrix4f[] skinningMatrixes; private transient Matrix4f[] skinningMatrixes;
@ -169,7 +169,7 @@ public final class Skeleton implements Savable, JmeCloneable {
} }
/** /**
* Saves the current skeleton state as it's binding pose. * Saves the current skeleton state as its binding pose.
*/ */
public void setBindingPose() { public void setBindingPose() {
for (int i = rootBones.length - 1; i >= 0; i--) { for (int i = rootBones.length - 1; i >= 0; i--) {
@ -304,6 +304,7 @@ public final class Skeleton implements Savable, JmeCloneable {
createSkinningMatrices(); createSkinningMatrices();
for (Bone rootBone : rootBones) { for (Bone rootBone : rootBones) {
rootBone.reset();
rootBone.update(); rootBone.update();
rootBone.setBindingPose(); rootBone.setBindingPose();
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2017 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -35,21 +35,18 @@ import com.jme3.export.*;
import com.jme3.material.MatParamOverride; import com.jme3.material.MatParamOverride;
import com.jme3.math.FastMath; import com.jme3.math.FastMath;
import com.jme3.math.Matrix4f; import com.jme3.math.Matrix4f;
import com.jme3.renderer.RenderManager; import com.jme3.renderer.*;
import com.jme3.renderer.RendererException;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.*; import com.jme3.scene.*;
import com.jme3.scene.VertexBuffer.Type; import com.jme3.scene.VertexBuffer.Type;
import com.jme3.scene.control.AbstractControl; import com.jme3.scene.control.AbstractControl;
import com.jme3.scene.control.Control;
import com.jme3.scene.mesh.IndexBuffer; import com.jme3.scene.mesh.IndexBuffer;
import com.jme3.shader.VarType; import com.jme3.shader.VarType;
import com.jme3.util.*; import com.jme3.util.SafeArrayList;
import com.jme3.util.TempVars;
import com.jme3.util.clone.Cloner; import com.jme3.util.clone.Cloner;
import com.jme3.util.clone.JmeCloneable; import com.jme3.util.clone.JmeCloneable;
import java.io.IOException; import java.io.IOException;
import java.nio.Buffer; import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer; import java.nio.FloatBuffer;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
@ -145,6 +142,12 @@ public class SkeletonControl extends AbstractControl implements Cloneable, JmeCl
} }
private boolean testHardwareSupported(RenderManager rm) { private boolean testHardwareSupported(RenderManager rm) {
//Only 255 bones max supported with hardware skinning
if (skeleton.getBoneCount() > 255) {
return false;
}
switchToHardware(); switchToHardware();
try { try {
@ -158,7 +161,7 @@ public class SkeletonControl extends AbstractControl implements Cloneable, JmeCl
/** /**
* Specifies if hardware skinning is preferred. If it is preferred and * Specifies if hardware skinning is preferred. If it is preferred and
* supported by GPU, it shall be enabled, if its not preferred, or not * supported by GPU, it shall be enabled, if it's not preferred, or not
* supported by GPU, then it shall be disabled. * supported by GPU, then it shall be disabled.
* *
* @param preferred * @param preferred
@ -326,7 +329,7 @@ public class SkeletonControl extends AbstractControl implements Cloneable, JmeCl
bpb.clear(); bpb.clear();
bnb.clear(); bnb.clear();
//reseting bind tangents if there is a bind tangent buffer //reset bind tangents if there is a bind tangent buffer
VertexBuffer bindTangents = mesh.getBuffer(Type.BindPoseTangent); VertexBuffer bindTangents = mesh.getBuffer(Type.BindPoseTangent);
if (bindTangents != null) { if (bindTangents != null) {
VertexBuffer tangents = mesh.getBuffer(Type.Tangent); VertexBuffer tangents = mesh.getBuffer(Type.Tangent);
@ -344,47 +347,6 @@ public class SkeletonControl extends AbstractControl implements Cloneable, JmeCl
} }
} }
@Override
public Control cloneForSpatial(Spatial spatial) {
Node clonedNode = (Node) spatial;
SkeletonControl clone = new SkeletonControl();
AnimControl ctrl = spatial.getControl(AnimControl.class);
if (ctrl != null) {
// AnimControl is responsible for cloning the skeleton, not
// SkeletonControl.
clone.skeleton = ctrl.getSkeleton();
} else {
// If there's no AnimControl, create the clone ourselves.
clone.skeleton = new Skeleton(skeleton);
}
clone.hwSkinningDesired = this.hwSkinningDesired;
clone.hwSkinningEnabled = this.hwSkinningEnabled;
clone.hwSkinningSupported = this.hwSkinningSupported;
clone.hwSkinningTested = this.hwSkinningTested;
clone.setSpatial(clonedNode);
// Fix attachments for the cloned node
for (int i = 0; i < clonedNode.getQuantity(); i++) {
// go through attachment nodes, apply them to correct bone
Spatial child = clonedNode.getChild(i);
if (child instanceof Node) {
Node clonedAttachNode = (Node) child;
Bone originalBone = (Bone) clonedAttachNode.getUserData("AttachedBone");
if (originalBone != null) {
Bone clonedBone = clone.skeleton.getBone(originalBone.getName());
clonedAttachNode.setUserData("AttachedBone", clonedBone);
clonedBone.setAttachmentsNode(clonedAttachNode);
}
}
}
return clone;
}
@Override @Override
public Object jmeClone() { public Object jmeClone() {
return super.jmeClone(); return super.jmeClone();

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2012 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -41,16 +41,14 @@ import com.jme3.scene.Spatial;
import com.jme3.util.TempVars; import com.jme3.util.TempVars;
import com.jme3.util.clone.Cloner; import com.jme3.util.clone.Cloner;
import com.jme3.util.clone.JmeCloneable; import com.jme3.util.clone.JmeCloneable;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays;
/** /**
* This class represents the track for spatial animation. * This class represents the track for spatial animation.
* *
* @author Marcin Roguski (Kaelthas) * @author Marcin Roguski (Kaelthas)
*/ */
public class SpatialTrack implements Track, JmeCloneable { public class SpatialTrack implements JmeCloneable, Track {
/** /**
* Translations of the track. * Translations of the track.
@ -250,9 +248,16 @@ public class SpatialTrack implements Track, JmeCloneable {
return times == null ? 0 : times[times.length - 1] - times[0]; return times == null ? 0 : times[times.length - 1] - times[0];
} }
/**
* Create a clone with the same track spatial.
*
* @return a new track
*/
@Override @Override
public Track clone() { public SpatialTrack clone() {
return (Track) jmeClone(); Cloner cloner = new Cloner();
cloner.setClonedValue(trackSpatial, trackSpatial);
return cloner.clone(this);
} }
@Override @Override
@ -268,22 +273,36 @@ public class SpatialTrack implements Track, JmeCloneable {
return trackSpatial; return trackSpatial;
} }
/**
* Create a shallow clone for the JME cloner.
*
* @return a new track
*/
@Override @Override
public Object jmeClone() { public SpatialTrack jmeClone() {
int tablesLength = times.length; try {
return (SpatialTrack) super.clone();
float[] timesCopy = this.times.clone(); } catch (CloneNotSupportedException exception) {
Vector3f[] translationsCopy = this.getTranslations() == null ? null : Arrays.copyOf(this.getTranslations(), tablesLength); throw new RuntimeException("Can't clone track", exception);
Quaternion[] rotationsCopy = this.getRotations() == null ? null : Arrays.copyOf(this.getRotations(), tablesLength); }
Vector3f[] scalesCopy = this.getScales() == null ? null : Arrays.copyOf(this.getScales(), tablesLength);
//need to use the constructor here because of the final fields used in this class
return new SpatialTrack(timesCopy, translationsCopy, rotationsCopy, scalesCopy);
} }
/**
* Callback from {@link com.jme3.util.clone.Cloner} to convert this
* shallow-cloned track into a deep-cloned one, using the specified cloner
* to resolve copied fields.
*
* @param cloner the cloner currently cloning this control (not null)
* @param original the track from which this track was shallow-cloned
* (unused)
*/
@Override @Override
public void cloneFields(Cloner cloner, Object original) { public void cloneFields(Cloner cloner, Object original) {
this.trackSpatial = cloner.clone(((SpatialTrack) original).trackSpatial); translations = cloner.clone(translations);
rotations = cloner.clone(rotations);
scales = cloner.clone(scales);
trackSpatial = cloner.clone(trackSpatial);
times = cloner.clone(times);
} }
@Override @Override

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2012 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -45,8 +45,8 @@ public interface Track extends Savable, Cloneable {
* *
* @param time The time in the animation * @param time The time in the animation
* @param weight The weight from 0 to 1 on how much to apply the track * @param weight The weight from 0 to 1 on how much to apply the track
* @param control The control which the track should effect * @param control The control which the track should affect
* @param channel The channel which the track should effect * @param channel The channel which the track should affect
*/ */
public void setTime(float time, float weight, AnimControl control, AnimChannel channel, TempVars vars); public void setTime(float time, float weight, AnimControl control, AnimChannel channel, TempVars vars);

View File

@ -59,6 +59,8 @@ public class DetailedProfilerState extends BaseAppState {
private ColorRGBA dimmedOrange = ColorRGBA.Orange.mult(0.7f); private ColorRGBA dimmedOrange = ColorRGBA.Orange.mult(0.7f);
private ColorRGBA dimmedRed = ColorRGBA.Red.mult(0.7f); private ColorRGBA dimmedRed = ColorRGBA.Red.mult(0.7f);
private ProfilerInputListener inputListener = new ProfilerInputListener();
public DetailedProfilerState() { public DetailedProfilerState() {
} }
@ -119,23 +121,17 @@ public class DetailedProfilerState extends BaseAppState {
if (inputManager != null) { if (inputManager != null) {
inputManager.addMapping(TOGGLE_KEY, new KeyTrigger(KeyInput.KEY_F6)); inputManager.addMapping(TOGGLE_KEY, new KeyTrigger(KeyInput.KEY_F6));
inputManager.addMapping(CLICK_KEY, new MouseButtonTrigger(MouseInput.BUTTON_LEFT)); inputManager.addMapping(CLICK_KEY, new MouseButtonTrigger(MouseInput.BUTTON_LEFT));
inputManager.addListener(new ActionListener() { inputManager.addListener(inputListener, TOGGLE_KEY, CLICK_KEY);
@Override
public void onAction(String name, boolean isPressed, float tpf) {
if (name.equals(TOGGLE_KEY) && isPressed) {
setEnabled(!isEnabled());
}
if (isEnabled() && name.equals(CLICK_KEY) && isPressed) {
handleClick(inputManager.getCursorPosition());
}
}
}, TOGGLE_KEY, CLICK_KEY);
} }
} }
@Override @Override
protected void cleanup(Application app) { protected void cleanup(Application app) {
ui.detachAllChildren();
InputManager manager = getApplication().getInputManager();
manager.deleteMapping(TOGGLE_KEY);
manager.deleteMapping(CLICK_KEY);
manager.removeListener(inputListener);
} }
@Override @Override
@ -441,8 +437,18 @@ public class DetailedProfilerState extends BaseAppState {
public String toString() { public String toString() {
return label.getText() + " - " + df.format(getMsFromNs(cpuValue)) + "ms / " + df.format(getMsFromNs(gpuValue)) + "ms"; return label.getText() + " - " + df.format(getMsFromNs(cpuValue)) + "ms / " + df.format(getMsFromNs(gpuValue)) + "ms";
} }
}
private class ProfilerInputListener implements ActionListener {
@Override
public void onAction(String name, boolean isPressed, float tpf) {
if (name.equals(TOGGLE_KEY) && isPressed) {
setEnabled(!isEnabled());
}
if (isEnabled() && name.equals(CLICK_KEY) && isPressed) {
handleClick(getApplication().getInputManager().getCursorPosition());
}
}
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2012 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -117,9 +117,10 @@ public class StatsView extends Node implements Control, JmeCloneable {
//statistics.clearFrame(); //statistics.clearFrame();
} }
@Deprecated
@Override @Override
public Control cloneForSpatial(Spatial spatial) { public Control cloneForSpatial(Spatial spatial) {
return (Control) spatial; throw new UnsupportedOperationException();
} }
@Override @Override

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2012 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -80,10 +80,10 @@ public class ScreenshotAppState extends AbstractAppState implements ActionListen
/** /**
* This constructor allows you to specify the output file path of the screenshot. * This constructor allows you to specify the output file path of the screenshot.
* Include the seperator at the end of the path. * Include the separator at the end of the path.
* Use an emptry string to use the application folder. Use NULL to use the system * Use an empty string to use the application folder. Use NULL to use the system
* default storage folder. * default storage folder.
* @param filePath The screenshot file path to use. Include the seperator at the end of the path. * @param filePath The screenshot file path to use. Include the separator at the end of the path.
*/ */
public ScreenshotAppState(String filePath) { public ScreenshotAppState(String filePath) {
this.filePath = filePath; this.filePath = filePath;
@ -91,11 +91,11 @@ public class ScreenshotAppState extends AbstractAppState implements ActionListen
/** /**
* This constructor allows you to specify the output file path of the screenshot. * This constructor allows you to specify the output file path of the screenshot.
* Include the seperator at the end of the path. * Include the separator at the end of the path.
* Use an emptry string to use the application folder. Use NULL to use the system * Use an empty string to use the application folder. Use NULL to use the system
* default storage folder. * default storage folder.
* @param filePath The screenshot file path to use. Include the seperator at the end of the path. * @param filePath The screenshot file path to use. Include the separator at the end of the path.
* @param fileName The name of the file to save the screeshot as. * @param fileName The name of the file to save the screenshot as.
*/ */
public ScreenshotAppState(String filePath, String fileName) { public ScreenshotAppState(String filePath, String fileName) {
this.filePath = filePath; this.filePath = filePath;
@ -105,10 +105,10 @@ public class ScreenshotAppState extends AbstractAppState implements ActionListen
/** /**
* This constructor allows you to specify the output file path of the screenshot and * This constructor allows you to specify the output file path of the screenshot and
* a base index for the shot index. * a base index for the shot index.
* Include the seperator at the end of the path. * Include the separator at the end of the path.
* Use an emptry string to use the application folder. Use NULL to use the system * Use an empty string to use the application folder. Use NULL to use the system
* default storage folder. * default storage folder.
* @param filePath The screenshot file path to use. Include the seperator at the end of the path. * @param filePath The screenshot file path to use. Include the separator at the end of the path.
* @param shotIndex The base index for screen shots. The first screen shot will have * @param shotIndex The base index for screen shots. The first screen shot will have
* shotIndex + 1 appended, the next shotIndex + 2, and so on. * shotIndex + 1 appended, the next shotIndex + 2, and so on.
*/ */
@ -120,11 +120,11 @@ public class ScreenshotAppState extends AbstractAppState implements ActionListen
/** /**
* This constructor allows you to specify the output file path of the screenshot and * This constructor allows you to specify the output file path of the screenshot and
* a base index for the shot index. * a base index for the shot index.
* Include the seperator at the end of the path. * Include the separator at the end of the path.
* Use an emptry string to use the application folder. Use NULL to use the system * Use an empty string to use the application folder. Use NULL to use the system
* default storage folder. * default storage folder.
* @param filePath The screenshot file path to use. Include the seperator at the end of the path. * @param filePath The screenshot file path to use. Include the separator at the end of the path.
* @param fileName The name of the file to save the screeshot as. * @param fileName The name of the file to save the screenshot as.
* @param shotIndex The base index for screen shots. The first screen shot will have * @param shotIndex The base index for screen shots. The first screen shot will have
* shotIndex + 1 appended, the next shotIndex + 2, and so on. * shotIndex + 1 appended, the next shotIndex + 2, and so on.
*/ */
@ -136,10 +136,10 @@ public class ScreenshotAppState extends AbstractAppState implements ActionListen
/** /**
* Set the file path to store the screenshot. * Set the file path to store the screenshot.
* Include the seperator at the end of the path. * Include the separator at the end of the path.
* Use an emptry string to use the application folder. Use NULL to use the system * Use an empty string to use the application folder. Use NULL to use the system
* default storage folder. * default storage folder.
* @param filePath File path to use to store the screenshot. Include the seperator at the end of the path. * @param filePath File path to use to store the screenshot. Include the separator at the end of the path.
*/ */
public void setFilePath(String filePath) { public void setFilePath(String filePath) {
this.filePath = filePath; this.filePath = filePath;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2012 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -217,7 +217,7 @@ public interface AssetManager {
* Load an asset from a key, the asset will be located * Load an asset from a key, the asset will be located
* by one of the {@link AssetLocator} implementations provided in the * by one of the {@link AssetLocator} implementations provided in the
* {@link AssetManager#registerLocator(java.lang.String, java.lang.Class) } * {@link AssetManager#registerLocator(java.lang.String, java.lang.Class) }
* call. If located successfully, it will be loaded via the the appropriate * call. If located successfully, it will be loaded via the appropriate
* {@link AssetLoader} implementation based on the file's extension, as * {@link AssetLoader} implementation based on the file's extension, as
* specified in the call * specified in the call
* {@link AssetManager#registerLoader(java.lang.Class, java.lang.String[]) }. * {@link AssetManager#registerLoader(java.lang.Class, java.lang.String[]) }.

View File

@ -32,6 +32,7 @@
package com.jme3.asset; package com.jme3.asset;
import com.jme3.asset.cache.AssetCache; import com.jme3.asset.cache.AssetCache;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
@ -279,9 +280,9 @@ final class ImplHandler {
// Synchronized access must be used for any ops on classToLoaderMap // Synchronized access must be used for any ops on classToLoaderMap
// Find the loader ImplThreadLocal for this class // Find the loader ImplThreadLocal for this class
synchronized (classToLoaderMap){ synchronized (classToLoaderMap){
ImplThreadLocal local = classToLoaderMap.get(loaderType);
// Remove it from the class->loader map // Remove it from the class->loader map
classToLoaderMap.remove(loaderType); ImplThreadLocal local = classToLoaderMap.remove(loaderType);
if (local == null) return;
// Remove it from the extension->loader map // Remove it from the extension->loader map
for (String extension : local.getExtensions()){ for (String extension : local.getExtensions()){
extensionToLoaderMap.remove(extension); extensionToLoaderMap.remove(extension);

View File

@ -112,11 +112,10 @@ public class WeakRefCloneAssetCache implements AssetCache {
// might not even have this asset anymore, it is OK. // might not even have this asset anymore, it is OK.
if (smartCache.remove(key) != null){ if (smartCache.remove(key) != null){
removedAssets ++; removedAssets ++;
//System.out.println("WeakRefAssetCache: The asset " + ref.assetKey + " was purged from the cache");
} }
} }
if (removedAssets >= 1) { if (removedAssets >= 1) {
logger.log(Level.FINE, "WeakRefAssetCache: {0} assets were purged from the cache.", removedAssets); logger.log(Level.FINE, "WeakRefCloneAssetCache: {0} assets were purged from the cache.", removedAssets);
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2012, 2016 jMonkeyEngine * Copyright (c) 2009-2012, 2016, 2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -221,7 +221,7 @@ public class AudioNode extends Node implements AudioSource {
/** /**
* Start playing an instance of this audio. This method can be used * Start playing an instance of this audio. This method can be used
* to play the same <code>AudioNode</code> multiple times. Note * to play the same <code>AudioNode</code> multiple times. Note
* that changes to the parameters of this AudioNode will not effect the * that changes to the parameters of this AudioNode will not affect the
* instances already playing. * instances already playing.
*/ */
public void playInstance(){ public void playInstance(){
@ -278,8 +278,8 @@ public class AudioNode extends Node implements AudioSource {
* the dry filter will only influence the "dry" portion of the audio, * the dry filter will only influence the "dry" portion of the audio,
* e.g. not the reverberated parts of the AudioNode playing. * e.g. not the reverberated parts of the AudioNode playing.
* *
* See the relevent documentation for the {@link Filter} to determine * See the relevant documentation for the {@link Filter} to determine the
* the effect. * effect.
* *
* @param dryFilter The filter to set, or null to disable dry filter. * @param dryFilter The filter to set, or null to disable dry filter.
*/ */
@ -692,7 +692,7 @@ public class AudioNode extends Node implements AudioSource {
/** /**
* Set the audio node as positional. * Set the audio node as positional.
* The position, velocity, and distance parameters effect positional * The position, velocity, and distance parameters affect positional
* audio nodes. Set to false if the audio node should play in "headspace". * audio nodes. Set to false if the audio node should play in "headspace".
* *
* @param positional True if the audio node should be positional, otherwise * @param positional True if the audio node should be positional, otherwise

View File

@ -12,37 +12,37 @@ public interface AL {
/** /**
* Boolean False. * Boolean False.
*/ */
static final int AL_FALSE = 0; public static final int AL_FALSE = 0;
/** /**
* Boolean True. * Boolean True.
*/ */
static final int AL_TRUE = 1; public static final int AL_TRUE = 1;
/* "no distance model" or "no buffer" */ /* "no distance model" or "no buffer" */
static final int AL_NONE = 0; public static final int AL_NONE = 0;
/** /**
* Indicate Source has relative coordinates. * Indicate Source has relative coordinates.
*/ */
static final int AL_SOURCE_RELATIVE = 0x202; public static final int AL_SOURCE_RELATIVE = 0x202;
/** /**
* Directional source, inner cone angle, in degrees. Range: [0-360] Default: * Directional source, inner cone angle, in degrees. Range: [0-360] Default:
* 360 * 360
*/ */
static final int AL_CONE_INNER_ANGLE = 0x1001; public static final int AL_CONE_INNER_ANGLE = 0x1001;
/** /**
* Directional source, outer cone angle, in degrees. Range: [0-360] Default: * Directional source, outer cone angle, in degrees. Range: [0-360] Default:
* 360 * 360
*/ */
static final int AL_CONE_OUTER_ANGLE = 0x1002; public static final int AL_CONE_OUTER_ANGLE = 0x1002;
/** /**
* Specify the pitch to be applied at source. Range: [0.5-2.0] Default: 1.0 * Specify the pitch to be applied at source. Range: [0.5-2.0] Default: 1.0
*/ */
static final int AL_PITCH = 0x1003; public static final int AL_PITCH = 0x1003;
/** /**
* Specify the current location in three dimensional space. OpenAL, like * Specify the current location in three dimensional space. OpenAL, like
@ -52,84 +52,84 @@ public interface AL {
* coordinate system, flip the sign on the Z coordinate. Listener position * coordinate system, flip the sign on the Z coordinate. Listener position
* is always in the world coordinate system. * is always in the world coordinate system.
*/ */
static final int AL_POSITION = 0x1004; public static final int AL_POSITION = 0x1004;
/** /**
* Specify the current direction. * Specify the current direction.
*/ */
static final int AL_DIRECTION = 0x1005; public static final int AL_DIRECTION = 0x1005;
/** /**
* Specify the current velocity in three dimensional space. * Specify the current velocity in three dimensional space.
*/ */
static final int AL_VELOCITY = 0x1006; public static final int AL_VELOCITY = 0x1006;
/** /**
* Indicate whether source is looping. Type: ALboolean? Range: [AL_TRUE, * Indicate whether source is looping. Type: ALboolean? Range: [AL_TRUE,
* AL_FALSE] Default: FALSE. * AL_FALSE] Default: FALSE.
*/ */
static final int AL_LOOPING = 0x1007; public static final int AL_LOOPING = 0x1007;
/** /**
* Indicate the buffer to provide sound samples. Type: ALuint. Range: any * Indicate the buffer to provide sound samples. Type: ALuint. Range: any
* valid Buffer id. * valid Buffer id.
*/ */
static final int AL_BUFFER = 0x1009; public static final int AL_BUFFER = 0x1009;
/** /**
* Indicate the gain (volume amplification) applied. Type: ALfloat. Range: * Indicate the gain (volume amplification) applied. Type: ALfloat. Range:
* ]0.0- ] A value of 1.0 means un-attenuated/unchanged. Each division by 2 * ]0.0- ] A value of 1.0 means un-attenuated/unchanged. Each division by 2
* equals an attenuation of -6dB. Each multiplicaton with 2 equals an * equals an attenuation of -6dB. Each multiplication by 2 equals an
* amplification of +6dB. A value of 0.0 is meaningless with respect to a * amplification of +6dB. A value of 0.0 is meaningless with respect to a
* logarithmic scale; it is interpreted as zero volume - the channel is * logarithmic scale; it is interpreted as zero volume - the channel is
* effectively disabled. * effectively disabled.
*/ */
static final int AL_GAIN = 0x100A; public static final int AL_GAIN = 0x100A;
/* /*
* Indicate minimum source attenuation * Indicate minimum source attenuation
* Type: ALfloat * Type: ALfloat
* Range: [0.0 - 1.0] * Range: [0.0 - 1.0]
* *
* Logarthmic * Logarithmic
*/ */
static final int AL_MIN_GAIN = 0x100D; public static final int AL_MIN_GAIN = 0x100D;
/** /**
* Indicate maximum source attenuation Type: ALfloat Range: [0.0 - 1.0] * Indicate maximum source attenuation Type: ALfloat Range: [0.0 - 1.0]
* *
* Logarthmic * Logarithmic
*/ */
static final int AL_MAX_GAIN = 0x100E; public static final int AL_MAX_GAIN = 0x100E;
/** /**
* Indicate listener orientation. * Indicate listener orientation.
* *
* at/up * at/up
*/ */
static final int AL_ORIENTATION = 0x100F; public static final int AL_ORIENTATION = 0x100F;
/** /**
* Source state information. * Source state information.
*/ */
static final int AL_SOURCE_STATE = 0x1010; public static final int AL_SOURCE_STATE = 0x1010;
static final int AL_INITIAL = 0x1011; public static final int AL_INITIAL = 0x1011;
static final int AL_PLAYING = 0x1012; public static final int AL_PLAYING = 0x1012;
static final int AL_PAUSED = 0x1013; public static final int AL_PAUSED = 0x1013;
static final int AL_STOPPED = 0x1014; public static final int AL_STOPPED = 0x1014;
/** /**
* Buffer Queue params * Buffer Queue params
*/ */
static final int AL_BUFFERS_QUEUED = 0x1015; public static final int AL_BUFFERS_QUEUED = 0x1015;
static final int AL_BUFFERS_PROCESSED = 0x1016; public static final int AL_BUFFERS_PROCESSED = 0x1016;
/** /**
* Source buffer position information * Source buffer position information
*/ */
static final int AL_SEC_OFFSET = 0x1024; public static final int AL_SEC_OFFSET = 0x1024;
static final int AL_SAMPLE_OFFSET = 0x1025; public static final int AL_SAMPLE_OFFSET = 0x1025;
static final int AL_BYTE_OFFSET = 0x1026; public static final int AL_BYTE_OFFSET = 0x1026;
/* /*
* Source type (Static, Streaming or undetermined) * Source type (Static, Streaming or undetermined)
@ -137,38 +137,38 @@ public interface AL {
* Source is Streaming if one or more Buffers have been attached using alSourceQueueBuffers * Source is Streaming if one or more Buffers have been attached using alSourceQueueBuffers
* Source is undetermined when it has the NULL buffer attached * Source is undetermined when it has the NULL buffer attached
*/ */
static final int AL_SOURCE_TYPE = 0x1027; public static final int AL_SOURCE_TYPE = 0x1027;
static final int AL_STATIC = 0x1028; public static final int AL_STATIC = 0x1028;
static final int AL_STREAMING = 0x1029; public static final int AL_STREAMING = 0x1029;
static final int AL_UNDETERMINED = 0x1030; public static final int AL_UNDETERMINED = 0x1030;
/** /**
* Sound samples: format specifier. * Sound samples: format specifier.
*/ */
static final int AL_FORMAT_MONO8 = 0x1100; public static final int AL_FORMAT_MONO8 = 0x1100;
static final int AL_FORMAT_MONO16 = 0x1101; public static final int AL_FORMAT_MONO16 = 0x1101;
static final int AL_FORMAT_STEREO8 = 0x1102; public static final int AL_FORMAT_STEREO8 = 0x1102;
static final int AL_FORMAT_STEREO16 = 0x1103; public static final int AL_FORMAT_STEREO16 = 0x1103;
/** /**
* source specific reference distance Type: ALfloat Range: 0.0 - +inf * source specific reference distance Type: ALfloat Range: 0.0 - +inf
* *
* At 0.0, no distance attenuation occurs. Default is 1.0. * At 0.0, no distance attenuation occurs. Default is 1.0.
*/ */
static final int AL_REFERENCE_DISTANCE = 0x1020; public static final int AL_REFERENCE_DISTANCE = 0x1020;
/** /**
* source specific rolloff factor Type: ALfloat Range: 0.0 - +inf * source specific rolloff factor Type: ALfloat Range: 0.0 - +inf
* *
*/ */
static final int AL_ROLLOFF_FACTOR = 0x1021; public static final int AL_ROLLOFF_FACTOR = 0x1021;
/** /**
* Directional source, outer cone gain. * Directional source, outer cone gain.
* *
* Default: 0.0 Range: [0.0 - 1.0] Logarithmic * Default: 0.0 Range: [0.0 - 1.0] Logarithmic
*/ */
static final int AL_CONE_OUTER_GAIN = 0x1022; public static final int AL_CONE_OUTER_GAIN = 0x1022;
/** /**
* Indicate distance above which sources are not attenuated using the * Indicate distance above which sources are not attenuated using the
@ -176,64 +176,64 @@ public interface AL {
* *
* Default: +inf Type: ALfloat Range: 0.0 - +inf * Default: +inf Type: ALfloat Range: 0.0 - +inf
*/ */
static final int AL_MAX_DISTANCE = 0x1023; public static final int AL_MAX_DISTANCE = 0x1023;
/** /**
* Sound samples: frequency, in units of Hertz [Hz]. This is the number of * Sound samples: frequency, in units of Hertz [Hz]. This is the number of
* samples per second. Half of the sample frequency marks the maximum * samples per second. Half of the sample frequency marks the maximum
* significant frequency component. * significant frequency component.
*/ */
static final int AL_FREQUENCY = 0x2001; public static final int AL_FREQUENCY = 0x2001;
static final int AL_BITS = 0x2002; public static final int AL_BITS = 0x2002;
static final int AL_CHANNELS = 0x2003; public static final int AL_CHANNELS = 0x2003;
static final int AL_SIZE = 0x2004; public static final int AL_SIZE = 0x2004;
/** /**
* Buffer state. * Buffer state.
* *
* Not supported for public use (yet). * Not supported for public use (yet).
*/ */
static final int AL_UNUSED = 0x2010; public static final int AL_UNUSED = 0x2010;
static final int AL_PENDING = 0x2011; public static final int AL_PENDING = 0x2011;
static final int AL_PROCESSED = 0x2012; public static final int AL_PROCESSED = 0x2012;
/** /**
* Errors: No Error. * Errors: No Error.
*/ */
static final int AL_NO_ERROR = 0; public static final int AL_NO_ERROR = 0;
/** /**
* Invalid Name paramater passed to AL call. * Invalid Name parameter passed to AL call.
*/ */
static final int AL_INVALID_NAME = 0xA001; public static final int AL_INVALID_NAME = 0xA001;
/** /**
* Invalid parameter passed to AL call. * Invalid parameter passed to AL call.
*/ */
static final int AL_INVALID_ENUM = 0xA002; public static final int AL_INVALID_ENUM = 0xA002;
/** /**
* Invalid enum parameter value. * Invalid enum parameter value.
*/ */
static final int AL_INVALID_VALUE = 0xA003; public static final int AL_INVALID_VALUE = 0xA003;
/** /**
* Illegal call. * Illegal call.
*/ */
static final int AL_INVALID_OPERATION = 0xA004; public static final int AL_INVALID_OPERATION = 0xA004;
/** /**
* No mojo. * No mojo.
*/ */
static final int AL_OUT_OF_MEMORY = 0xA005; public static final int AL_OUT_OF_MEMORY = 0xA005;
/** /**
* Context strings: Vendor Name. * Context strings: Vendor Name.
*/ */
static final int AL_VENDOR = 0xB001; public static final int AL_VENDOR = 0xB001;
static final int AL_VERSION = 0xB002; public static final int AL_VERSION = 0xB002;
static final int AL_RENDERER = 0xB003; public static final int AL_RENDERER = 0xB003;
static final int AL_EXTENSIONS = 0xB004; public static final int AL_EXTENSIONS = 0xB004;
/** /**
* Global tweakage. * Global tweakage.
@ -241,56 +241,241 @@ public interface AL {
/** /**
* Doppler scale. Default 1.0 * Doppler scale. Default 1.0
*/ */
static final int AL_DOPPLER_FACTOR = 0xC000; public static final int AL_DOPPLER_FACTOR = 0xC000;
/** /**
* Tweaks speed of propagation. * Tweaks speed of propagation.
*/ */
static final int AL_DOPPLER_VELOCITY = 0xC001; public static final int AL_DOPPLER_VELOCITY = 0xC001;
/** /**
* Speed of Sound in units per second * Speed of Sound in units per second
*/ */
static final int AL_SPEED_OF_SOUND = 0xC003; public static final int AL_SPEED_OF_SOUND = 0xC003;
/** /**
* Distance models * Distance models
* *
* used in conjunction with DistanceModel * used in conjunction with DistanceModel
* *
* implicit: NONE, which disances distance attenuation. * implicit: NONE, which disables distance attenuation.
*/ */
static final int AL_DISTANCE_MODEL = 0xD000; public static final int AL_DISTANCE_MODEL = 0xD000;
static final int AL_INVERSE_DISTANCE = 0xD001; public static final int AL_INVERSE_DISTANCE = 0xD001;
static final int AL_INVERSE_DISTANCE_CLAMPED = 0xD002; public static final int AL_INVERSE_DISTANCE_CLAMPED = 0xD002;
static final int AL_LINEAR_DISTANCE = 0xD003; public static final int AL_LINEAR_DISTANCE = 0xD003;
static final int AL_LINEAR_DISTANCE_CLAMPED = 0xD004; public static final int AL_LINEAR_DISTANCE_CLAMPED = 0xD004;
static final int AL_EXPONENT_DISTANCE = 0xD005; public static final int AL_EXPONENT_DISTANCE = 0xD005;
static final int AL_EXPONENT_DISTANCE_CLAMPED = 0xD006; public static final int AL_EXPONENT_DISTANCE_CLAMPED = 0xD006;
//
///* Listener parameter value ranges and defaults. */ //
//#define AL_MIN_METERS_PER_UNIT FLT_MIN ///* Listener parameter value ranges and defaults. */
//#define AL_MAX_METERS_PER_UNIT FLT_MAX //#define AL_MIN_METERS_PER_UNIT FLT_MIN
//#define AL_DEFAULT_METERS_PER_UNIT (1.0f) //#define AL_MAX_METERS_PER_UNIT FLT_MAX
//#define AL_DEFAULT_METERS_PER_UNIT (1.0f)
public String alGetString(int parameter); public String alGetString(int parameter);
/**
* Requests a number of source names.
*
* @return the number of source names.
*/
public int alGenSources(); public int alGenSources();
/**
* Obtains error information.
* <p>
* <p>Each detectable error is assigned a numeric code. When an error is detected by AL, a flag is set and the error code is recorded. Further errors, if they
* occur, do not affect this recorded code. When alGetError is called, the code is returned and the flag is cleared, so that a further error will again
* record its code. If a call to alGetError returns AL_NO_ERROR then there has been no detectable error since the last call to alGetError (or since the AL
* was initialized).</p>
* <p>
* <p>Error codes can be mapped to strings. The alGetString function returns a pointer to a constant (literal) string that is identical to the identifier used
* for the enumeration value, as defined in the specification.</p>
*/
public int alGetError(); public int alGetError();
/**
* Requests the deletion of a number of sources.
*
* @param numSources the number of sources.
* @param sources the sources to delete.
*/
public void alDeleteSources(int numSources, IntBuffer sources); public void alDeleteSources(int numSources, IntBuffer sources);
/**
* Requests a number of buffer names.
*
* @param numBuffers the number of buffers.
* @param buffers the buffer that will receive the buffer names.
*/
public void alGenBuffers(int numBuffers, IntBuffer buffers); public void alGenBuffers(int numBuffers, IntBuffer buffers);
/**
* Requests the deletion of a number of buffers.
*
* @param numBuffers the number of buffers.
* @param buffers the buffers to delete.
*/
public void alDeleteBuffers(int numBuffers, IntBuffer buffers); public void alDeleteBuffers(int numBuffers, IntBuffer buffers);
/**
* Sets the source state to AL_STOPPED.
* <p>
* <p>alSourceStop applied to an AL_INITIAL source is a legal NOP. alSourceStop applied to a AL_PLAYING source will change its state to AL_STOPPED. The source
* is exempt from processing, its current state is preserved. alSourceStop applied to a AL_PAUSED source will change its state to AL_STOPPED, with the same
* consequences as on a AL_PLAYING source. alSourceStop applied to a AL_STOPPED source is a legal NOP.</p>
*
* @param source the source to stop.
*/
public void alSourceStop(int source); public void alSourceStop(int source);
/**
* Integer version of {@link #alSourcef Sourcef}.
*
* @param source the source to modify.
* @param param the parameter to modify.
* @param value the parameter value.
*/
public void alSourcei(int source, int param, int value); public void alSourcei(int source, int param, int value);
/**
* Sets the sample data of the specified buffer.
* <p>
* <p>The data specified is copied to an internal software, or if possible, hardware buffer. The implementation is free to apply decompression, conversion,
* resampling, and filtering as needed.</p>
* <p>
* <p>8-bit data is expressed as an unsigned value over the range 0 to 255, 128 being an audio output level of zero.</p>
* <p>
* <p>16-bit data is expressed as a signed value over the range -32768 to 32767, 0 being an audio output level of zero. Byte order for 16-bit values is
* determined by the native format of the CPU.</p>
* <p>
* <p>Stereo data is expressed in an interleaved format, left channel sample followed by the right channel sample.</p>
* <p>
* <p>Buffers containing audio data with more than one channel will be played without 3D spatialization features these formats are normally used for
* background music.</p>
*
* @param buffer the buffer to modify.
* @param format the data format. One of:<br><table><tr><td>{@link #AL_FORMAT_MONO8 FORMAT_MONO8}</td><td>{@link #AL_FORMAT_MONO16 FORMAT_MONO16}</td><td>{@link #AL_FORMAT_STEREO8 FORMAT_STEREO8}</td><td>{@link #AL_FORMAT_STEREO16 FORMAT_STEREO16}</td></tr></table>
* @param data the sample data.
* @param frequency the data frequency.
*/
public void alBufferData(int buffer, int format, ByteBuffer data, int size, int frequency); public void alBufferData(int buffer, int format, ByteBuffer data, int size, int frequency);
/**
* Sets the source state to AL_PLAYING.
* <p>
* <p>alSourcePlay applied to an AL_INITIAL source will promote the source to AL_PLAYING, thus the data found in the buffer will be fed into the processing,
* starting at the beginning. alSourcePlay applied to a AL_PLAYING source will restart the source from the beginning. It will not affect the configuration,
* and will leave the source in AL_PLAYING state, but reset the sampling offset to the beginning. alSourcePlay applied to a AL_PAUSED source will resume
* processing using the source state as preserved at the alSourcePause operation. alSourcePlay applied to a AL_STOPPED source will propagate it to
* AL_INITIAL then to AL_PLAYING immediately.</p>
*
* @param source the source to play.
*/
public void alSourcePlay(int source); public void alSourcePlay(int source);
/**
* Sets the source state to AL_PAUSED.
* <p>
* <p>alSourcePause applied to an AL_INITIAL source is a legal NOP. alSourcePause applied to a AL_PLAYING source will change its state to AL_PAUSED. The
* source is exempt from processing, its current state is preserved. alSourcePause applied to a AL_PAUSED source is a legal NOP. alSourcePause applied to a
* AL_STOPPED source is a legal NOP.</p>
*
* @param source the source to pause.
*/
public void alSourcePause(int source); public void alSourcePause(int source);
/**
* Sets the float value of a source parameter.
*
* @param source the source to modify.
* @param param the parameter to modify. One of:<br><table><tr><td>{@link #AL_CONE_INNER_ANGLE CONE_INNER_ANGLE}</td><td>{@link #AL_CONE_OUTER_ANGLE CONE_OUTER_ANGLE}</td><td>{@link #AL_PITCH PITCH}</td><td>{@link #AL_DIRECTION DIRECTION}</td><td>{@link #AL_LOOPING LOOPING}</td><td>{@link #AL_BUFFER BUFFER}</td><td>{@link #AL_SOURCE_STATE SOURCE_STATE}</td></tr><tr><td>{@link #AL_CONE_OUTER_GAIN CONE_OUTER_GAIN}</td><td>{@link #AL_SOURCE_TYPE SOURCE_TYPE}</td><td>{@link #AL_POSITION POSITION}</td><td>{@link #AL_VELOCITY VELOCITY}</td><td>{@link #AL_GAIN GAIN}</td><td>{@link #AL_REFERENCE_DISTANCE REFERENCE_DISTANCE}</td><td>{@link #AL_ROLLOFF_FACTOR ROLLOFF_FACTOR}</td></tr><tr><td>{@link #AL_MAX_DISTANCE MAX_DISTANCE}</td></tr></table>
* @param value the parameter value.
*/
public void alSourcef(int source, int param, float value); public void alSourcef(int source, int param, float value);
/**
* Sets the 3 dimensional values of a source parameter.
*
* @param source the source to modify.
* @param param the parameter to modify. One of:<br><table><tr><td>{@link #AL_CONE_INNER_ANGLE CONE_INNER_ANGLE}</td><td>{@link #AL_CONE_OUTER_ANGLE CONE_OUTER_ANGLE}</td><td>{@link #AL_PITCH PITCH}</td><td>{@link #AL_DIRECTION DIRECTION}</td><td>{@link #AL_LOOPING LOOPING}</td><td>{@link #AL_BUFFER BUFFER}</td><td>{@link #AL_SOURCE_STATE SOURCE_STATE}</td></tr><tr><td>{@link #AL_CONE_OUTER_GAIN CONE_OUTER_GAIN}</td><td>{@link #AL_SOURCE_TYPE SOURCE_TYPE}</td><td>{@link #AL_POSITION POSITION}</td><td>{@link #AL_VELOCITY VELOCITY}</td><td>{@link #AL_GAIN GAIN}</td><td>{@link #AL_REFERENCE_DISTANCE REFERENCE_DISTANCE}</td><td>{@link #AL_ROLLOFF_FACTOR ROLLOFF_FACTOR}</td></tr><tr><td>{@link #AL_MAX_DISTANCE MAX_DISTANCE}</td></tr></table>
* @param value1 the first parameter value.
* @param value2 the second parameter value.
* @param value3 the third parameter value.
*/
public void alSource3f(int source, int param, float value1, float value2, float value3); public void alSource3f(int source, int param, float value1, float value2, float value3);
/**
* Returns the integer value of the specified source parameter.
*
* @param source the source to query.
* @param param the parameter to query. One of:<br><table><tr><td>{@link #AL_CONE_INNER_ANGLE CONE_INNER_ANGLE}</td><td>{@link #AL_CONE_OUTER_ANGLE CONE_OUTER_ANGLE}</td><td>{@link #AL_PITCH PITCH}</td><td>{@link #AL_DIRECTION DIRECTION}</td><td>{@link #AL_LOOPING LOOPING}</td><td>{@link #AL_BUFFER BUFFER}</td><td>{@link #AL_SOURCE_STATE SOURCE_STATE}</td></tr><tr><td>{@link #AL_CONE_OUTER_GAIN CONE_OUTER_GAIN}</td><td>{@link #AL_SOURCE_TYPE SOURCE_TYPE}</td><td>{@link #AL_POSITION POSITION}</td><td>{@link #AL_VELOCITY VELOCITY}</td><td>{@link #AL_GAIN GAIN}</td><td>{@link #AL_REFERENCE_DISTANCE REFERENCE_DISTANCE}</td><td>{@link #AL_ROLLOFF_FACTOR ROLLOFF_FACTOR}</td></tr><tr><td>{@link #AL_MAX_DISTANCE MAX_DISTANCE}</td></tr></table>
*/
public int alGetSourcei(int source, int param); public int alGetSourcei(int source, int param);
/**
* Removes a number of buffer entries that have finished processing, in the order of apperance, from the queue of the specified source.
* <p>
* <p>Once a queue entry for a buffer has been appended to a queue and is pending processing, it should not be changed. Removal of a given queue entry is not
* possible unless either the source is stopped (in which case then entire queue is considered processed), or if the queue entry has already been processed
* (AL_PLAYING or AL_PAUSED source). A playing source will enter the AL_STOPPED state if it completes playback of the last buffer in its queue (the same
* behavior as when a single buffer has been attached to a source and has finished playback).</p>
*
* @param source the target source
* @param numBuffers the names count.
* @param buffers the buffer names
*/
public void alSourceUnqueueBuffers(int source, int numBuffers, IntBuffer buffers); public void alSourceUnqueueBuffers(int source, int numBuffers, IntBuffer buffers);
/**
* Queues up one or multiple buffer names to the specified source.
* <p>
* <p>The buffers will be queued in the sequence in which they appear in the array. This command is legal on a source in any playback state (to allow for
* streaming, queuing has to be possible on a AL_PLAYING source). All buffers in a queue must have the same format and attributes, with the exception of
* the {@code NULL} buffer (i.e., 0) which can always be queued.</p>
*
* @param source the target source.
* @param numBuffers the names count.
* @param buffers the buffer names.
*/
public void alSourceQueueBuffers(int source, int numBuffers, IntBuffer buffers); public void alSourceQueueBuffers(int source, int numBuffers, IntBuffer buffers);
/**
* Pointer version of {@link #alListenerf Listenerf}.
*
* @param param the parameter to modify.
* @param data the parameter values.
*/
public void alListener(int param, FloatBuffer data); public void alListener(int param, FloatBuffer data);
/**
* Sets the float value of a listener parameter.
*
* @param param the parameter to modify. One of:<br><table><tr><td>{@link #AL_ORIENTATION ORIENTATION}</td><td>{@link #AL_POSITION POSITION}</td><td>{@link #AL_VELOCITY VELOCITY}</td><td>{@link #AL_GAIN GAIN}</td></tr></table>
* @param value the parameter value.
*/
public void alListenerf(int param, float value); public void alListenerf(int param, float value);
/**
* Sets the 3 dimensional float values of a listener parameter.
*
* @param param the parameter to modify. One of:<br><table><tr><td>{@link #AL_ORIENTATION ORIENTATION}</td><td>{@link #AL_POSITION POSITION}</td><td>{@link #AL_VELOCITY VELOCITY}</td><td>{@link #AL_GAIN GAIN}</td></tr></table>
* @param value1 the first value.
* @param value2 the second value.
* @param value3 the third value.
*/
public void alListener3f(int param, float value1, float value2, float value3); public void alListener3f(int param, float value1, float value2, float value3);
/**
* Sets the 3 dimensional integer values of a source parameter.
*
* @param source the source to modify.
* @param param the parameter to modify.
* @param value1 the first value.
* @param value2 the second value.
* @param value3 the third value.
*/
public void alSource3i(int source, int param, int value1, int value2, int value3); public void alSource3i(int source, int param, int value1, int value2, int value3);
} }

View File

@ -7,67 +7,120 @@ public interface ALC {
/** /**
* No error * No error
*/ */
static final int ALC_NO_ERROR = 0; public static final int ALC_NO_ERROR = 0;
/** /**
* No device * No device
*/ */
static final int ALC_INVALID_DEVICE = 0xA001; public static final int ALC_INVALID_DEVICE = 0xA001;
/** /**
* invalid context ID * invalid context ID
*/ */
static final int ALC_INVALID_CONTEXT = 0xA002; public static final int ALC_INVALID_CONTEXT = 0xA002;
/** /**
* bad enum * bad enum
*/ */
static final int ALC_INVALID_ENUM = 0xA003; public static final int ALC_INVALID_ENUM = 0xA003;
/** /**
* bad value * bad value
*/ */
static final int ALC_INVALID_VALUE = 0xA004; public static final int ALC_INVALID_VALUE = 0xA004;
/** /**
* Out of memory. * Out of memory.
*/ */
static final int ALC_OUT_OF_MEMORY = 0xA005; public static final int ALC_OUT_OF_MEMORY = 0xA005;
/** /**
* The Specifier string for default device * The Specifier string for default device
*/ */
static final int ALC_DEFAULT_DEVICE_SPECIFIER = 0x1004; public static final int ALC_DEFAULT_DEVICE_SPECIFIER = 0x1004;
static final int ALC_DEVICE_SPECIFIER = 0x1005; public static final int ALC_DEVICE_SPECIFIER = 0x1005;
static final int ALC_EXTENSIONS = 0x1006; public static final int ALC_EXTENSIONS = 0x1006;
static final int ALC_MAJOR_VERSION = 0x1000; public static final int ALC_MAJOR_VERSION = 0x1000;
static final int ALC_MINOR_VERSION = 0x1001; public static final int ALC_MINOR_VERSION = 0x1001;
static final int ALC_ATTRIBUTES_SIZE = 0x1002; public static final int ALC_ATTRIBUTES_SIZE = 0x1002;
static final int ALC_ALL_ATTRIBUTES = 0x1003; public static final int ALC_ALL_ATTRIBUTES = 0x1003;
/** /**
* Capture extension * Capture extension
*/ */
static final int ALC_CAPTURE_DEVICE_SPECIFIER = 0x310; public static final int ALC_CAPTURE_DEVICE_SPECIFIER = 0x310;
static final int ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER = 0x311; public static final int ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER = 0x311;
static final int ALC_CAPTURE_SAMPLES = 0x312; public static final int ALC_CAPTURE_SAMPLES = 0x312;
/** /**
* ALC_ENUMERATE_ALL_EXT enums * ALC_ENUMERATE_ALL_EXT enums
*/ */
static final int ALC_DEFAULT_ALL_DEVICES_SPECIFIER = 0x1012; public static final int ALC_DEFAULT_ALL_DEVICES_SPECIFIER = 0x1012;
static final int ALC_ALL_DEVICES_SPECIFIER = 0x1013; public static final int ALC_ALL_DEVICES_SPECIFIER = 0x1013;
//public static ALCCapabilities createCapabilities(long device); //public static ALCCapabilities createCapabilities(long device);
/**
* Creates an AL context.
*/
public void createALC(); public void createALC();
/**
* Destroys an AL context.
*/
public void destroyALC(); public void destroyALC();
/**
* Checks of creating an AL context.
*
* @return true if an AL context is created.
*/
public boolean isCreated(); public boolean isCreated();
/**
* Obtains string value(s) from ALC.
*
* @param parameter the information to query. One of:<br><table><tr><td>{@link #ALC_DEFAULT_DEVICE_SPECIFIER DEFAULT_DEVICE_SPECIFIER}</td><td>{@link #ALC_DEVICE_SPECIFIER DEVICE_SPECIFIER}</td><td>{@link #ALC_EXTENSIONS EXTENSIONS}</td></tr><tr><td>{@link #ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER CAPTURE_DEFAULT_DEVICE_SPECIFIER}</td><td>{@link #ALC_CAPTURE_DEVICE_SPECIFIER CAPTURE_DEVICE_SPECIFIER}</td></tr></table>
*/
public String alcGetString(int parameter); public String alcGetString(int parameter);
/**
* Verifies that a given extension is available for the current context and the device it is associated with.
* <p>
* <p>Invalid and unsupported string tokens return ALC_FALSE. A {@code NULL} deviceHandle is acceptable. {@code extName} is not case sensitive the implementation
* will convert the name to all upper-case internally (and will express extension names in upper-case).</p>
*
* @param extension the extension name.
*/
public boolean alcIsExtensionPresent(String extension); public boolean alcIsExtensionPresent(String extension);
/**
* Obtains integer value(s) from ALC.
*
* @param param the information to query. One of:<br><table><tr><td>{@link #ALC_MAJOR_VERSION MAJOR_VERSION}</td><td>{@link #ALC_MINOR_VERSION MINOR_VERSION}</td><td>{@link #ALC_ATTRIBUTES_SIZE ATTRIBUTES_SIZE}</td><td>{@link #ALC_ALL_ATTRIBUTES ALL_ATTRIBUTES}</td><td>{@link #ALC_CAPTURE_SAMPLES CAPTURE_SAMPLES}</td></tr></table>
* @param buffer the destination buffer.
* @param size the buffer size.
*/
public void alcGetInteger(int param, IntBuffer buffer, int size); public void alcGetInteger(int param, IntBuffer buffer, int size);
/**
* Pauses a playback device.
* <p>
* <p>When paused, no contexts associated with the device will be processed or updated. Playing sources will not produce sound, have their offsets
* incremented, or process any more buffers, until the device is resumed. Pausing a device that is already paused is a legal no-op.</p>
*/
public void alcDevicePauseSOFT(); public void alcDevicePauseSOFT();
/**
* Resumes playback of a paused device.
* <p>
* <p>This will restart processing on the device -- sources will resume playing sound as normal. Resuming playback on a device that is not paused is a legal
* no-op.</p>
* <p>
* <p>These functions are not reference counted. alcDeviceResumeSOFT only needs to be called once to resume playback, regardless of how many times
* {@link #alcDevicePauseSOFT DevicePauseSOFT} was called.</p>
*/
public void alcDeviceResumeSOFT(); public void alcDeviceResumeSOFT();
} }

File diff suppressed because it is too large Load Diff

View File

@ -36,14 +36,18 @@ import com.jme3.app.Application;
import com.jme3.app.state.AppState; import com.jme3.app.state.AppState;
import com.jme3.app.state.AppStateManager; import com.jme3.app.state.AppStateManager;
import com.jme3.cinematic.events.AbstractCinematicEvent; import com.jme3.cinematic.events.AbstractCinematicEvent;
import com.jme3.cinematic.events.CameraEvent;
import com.jme3.cinematic.events.CinematicEvent; import com.jme3.cinematic.events.CinematicEvent;
import com.jme3.export.*; import com.jme3.export.*;
import com.jme3.renderer.Camera; import com.jme3.renderer.Camera;
import com.jme3.renderer.RenderManager; import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.CameraNode; import com.jme3.scene.CameraNode;
import com.jme3.scene.Node; import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.control.CameraControl; import com.jme3.scene.control.CameraControl;
import com.jme3.scene.control.CameraControl.ControlDirection; import com.jme3.scene.control.CameraControl.ControlDirection;
import com.jme3.scene.control.Control;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
@ -88,12 +92,12 @@ import java.util.logging.Logger;
*/ */
public class Cinematic extends AbstractCinematicEvent implements AppState { public class Cinematic extends AbstractCinematicEvent implements AppState {
private static final Logger logger = Logger.getLogger(Application.class.getName()); private static final Logger logger = Logger.getLogger(Cinematic.class.getName());
private Node scene; private Node scene;
protected TimeLine timeLine = new TimeLine(); protected TimeLine timeLine = new TimeLine();
private int lastFetchedKeyFrame = -1; private int lastFetchedKeyFrame = -1;
private List<CinematicEvent> cinematicEvents = new ArrayList<CinematicEvent>(); private List<CinematicEvent> cinematicEvents = new ArrayList<>();
private Map<String, CameraNode> cameras = new HashMap<String, CameraNode>(); private Map<String, CameraNode> cameras = new HashMap<>();
private CameraNode currentCam; private CameraNode currentCam;
private boolean initialized = false; private boolean initialized = false;
private Map<String, Map<Object, Object>> eventsData; private Map<String, Map<Object, Object>> eventsData;
@ -104,6 +108,19 @@ public class Cinematic extends AbstractCinematicEvent implements AppState {
* directly * directly
*/ */
public Cinematic() { public Cinematic() {
super();
}
public Cinematic(float initialDuration) {
super(initialDuration);
}
public Cinematic(LoopMode loopMode) {
super(loopMode);
}
public Cinematic(float initialDuration, LoopMode loopMode) {
super(initialDuration, loopMode);
} }
/** /**
@ -206,8 +223,7 @@ public class Cinematic extends AbstractCinematicEvent implements AppState {
public void write(JmeExporter ex) throws IOException { public void write(JmeExporter ex) throws IOException {
super.write(ex); super.write(ex);
OutputCapsule oc = ex.getCapsule(this); OutputCapsule oc = ex.getCapsule(this);
oc.write(cinematicEvents.toArray(new CinematicEvent[cinematicEvents.size()]), "cinematicEvents", null);
oc.writeSavableArrayList((ArrayList) cinematicEvents, "cinematicEvents", null);
oc.writeStringSavableMap(cameras, "cameras", null); oc.writeStringSavableMap(cameras, "cameras", null);
oc.write(timeLine, "timeLine", null); oc.write(timeLine, "timeLine", null);
@ -224,7 +240,11 @@ public class Cinematic extends AbstractCinematicEvent implements AppState {
super.read(im); super.read(im);
InputCapsule ic = im.getCapsule(this); InputCapsule ic = im.getCapsule(this);
cinematicEvents = ic.readSavableArrayList("cinematicEvents", null); Savable[] events = ic.readSavableArray("cinematicEvents", null);
for (Savable c : events) {
// addCinematicEvent(((CinematicEvent) c).getTime(), (CinematicEvent) c)
cinematicEvents.add((CinematicEvent) c);
}
cameras = (Map<String, CameraNode>) ic.readStringSavableMap("cameras", null); cameras = (Map<String, CameraNode>) ic.readStringSavableMap("cameras", null);
timeLine = (TimeLine) ic.readSavable("timeLine", null); timeLine = (TimeLine) ic.readSavable("timeLine", null);
} }
@ -244,7 +264,6 @@ public class Cinematic extends AbstractCinematicEvent implements AppState {
ce.setSpeed(speed); ce.setSpeed(speed);
} }
} }
/** /**
@ -258,7 +277,11 @@ public class Cinematic extends AbstractCinematicEvent implements AppState {
for (CinematicEvent cinematicEvent : cinematicEvents) { for (CinematicEvent cinematicEvent : cinematicEvents) {
cinematicEvent.initEvent(app, this); cinematicEvent.initEvent(app, this);
} }
if(!cameras.isEmpty()){
for(CameraNode n : cameras.values()){
n.setCamera(app.getCamera());
}
}
initialized = true; initialized = true;
} }
@ -315,8 +338,9 @@ public class Cinematic extends AbstractCinematicEvent implements AppState {
* *
* @param tpf * @param tpf
*/ */
@Override
public void update(float tpf) { public void update(float tpf) {
if (isInitialized()) { if (isInitialized() && playState == PlayState.Playing) {
internalUpdate(tpf); internalUpdate(tpf);
} }
} }
@ -338,13 +362,11 @@ public class Cinematic extends AbstractCinematicEvent implements AppState {
} }
} }
for (int i = 0; i < cinematicEvents.size(); i++) { for (int i = 0; i < cinematicEvents.size(); i++) {
CinematicEvent ce = cinematicEvents.get(i); CinematicEvent ce = cinematicEvents.get(i);
ce.internalUpdate(tpf); ce.internalUpdate(tpf);
} }
lastFetchedKeyFrame = keyFrameIndex; lastFetchedKeyFrame = keyFrameIndex;
} }
@ -386,8 +408,8 @@ public class Cinematic extends AbstractCinematicEvent implements AppState {
* Adds a cinematic event to this cinematic at the given timestamp. This * Adds a cinematic event to this cinematic at the given timestamp. This
* operation returns a keyFrame * operation returns a keyFrame
* *
* @param timeStamp the time when the event will start after the beginning of * @param timeStamp the time when the event will start after the beginning
* the cinematic * of the cinematic
* @param cinematicEvent the cinematic event * @param cinematicEvent the cinematic event
* @return the keyFrame for that event. * @return the keyFrame for that event.
*/ */
@ -580,39 +602,7 @@ public class Cinematic extends AbstractCinematicEvent implements AppState {
* Cinematic#bindCamera()) * Cinematic#bindCamera())
*/ */
public void activateCamera(final float timeStamp, final String cameraName) { public void activateCamera(final float timeStamp, final String cameraName) {
addCinematicEvent(timeStamp, new AbstractCinematicEvent() { addCinematicEvent(timeStamp, new CameraEvent(this, cameraName));
@Override
public void play() {
super.play();
stop();
}
@Override
public void onPlay() {
setActiveCamera(cameraName);
}
@Override
public void onUpdate(float tpf) {
}
@Override
public void onStop() {
}
@Override
public void onPause() {
}
@Override
public void forceStop() {
}
@Override
public void setTime(float time) {
play();
}
});
} }
/** /**
@ -684,6 +674,11 @@ public class Cinematic extends AbstractCinematicEvent implements AppState {
*/ */
public void setScene(Node scene) { public void setScene(Node scene) {
this.scene = scene; this.scene = scene;
if(!cameras.isEmpty()){
for(CameraNode n : cameras.values()){
this.scene.attachChild(n);
}
}
} }
/** /**

View File

@ -43,7 +43,11 @@ import java.util.List;
*/ */
public class KeyFrame implements Savable { public class KeyFrame implements Savable {
List<CinematicEvent> cinematicEvents = new ArrayList<CinematicEvent>(); public KeyFrame(){
}
List<CinematicEvent> cinematicEvents = new ArrayList<>();
private int index; private int index;
public List<CinematicEvent> getCinematicEvents() { public List<CinematicEvent> getCinematicEvents() {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2012 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -202,7 +202,7 @@ public class MotionPath implements Savable {
} }
/** /**
* Addsa waypoint to the path * Add a waypoint to the path
* @param wayPoint a position in world space * @param wayPoint a position in world space
*/ */
public void addWayPoint(Vector3f wayPoint) { public void addWayPoint(Vector3f wayPoint) {
@ -210,7 +210,7 @@ public class MotionPath implements Savable {
} }
/** /**
* retruns the length of the path in world units * Return the length of the path in world units
* @return the length * @return the length
*/ */
public float getLength() { public float getLength() {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2012 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -34,7 +34,7 @@ package com.jme3.cinematic;
import com.jme3.cinematic.events.MotionEvent; import com.jme3.cinematic.events.MotionEvent;
/** /**
* Trigger the events happening on an motion path * Trigger the events happening on a motion path
* @author Nehon * @author Nehon
*/ */
public interface MotionPathListener { public interface MotionPathListener {

View File

@ -41,7 +41,10 @@ import com.jme3.export.InputCapsule;
import com.jme3.export.JmeExporter; import com.jme3.export.JmeExporter;
import com.jme3.export.JmeImporter; import com.jme3.export.JmeImporter;
import com.jme3.export.OutputCapsule; import com.jme3.export.OutputCapsule;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial; import com.jme3.scene.Spatial;
import com.jme3.util.clone.Cloner;
import com.jme3.util.clone.JmeCloneable;
import java.io.IOException; import java.io.IOException;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
@ -80,6 +83,7 @@ public class AnimationEvent extends AbstractCinematicEvent {
* constructors * constructors
*/ */
public AnimationEvent() { public AnimationEvent() {
super();
} }
/** /**
@ -90,6 +94,7 @@ public class AnimationEvent extends AbstractCinematicEvent {
*/ */
public AnimationEvent(Spatial model, String animationName) { public AnimationEvent(Spatial model, String animationName) {
this.model = model; this.model = model;
this.modelName = model.getName();
this.animationName = animationName; this.animationName = animationName;
initialDuration = model.getControl(AnimControl.class).getAnimationLength(animationName); initialDuration = model.getControl(AnimControl.class).getAnimationLength(animationName);
} }
@ -104,6 +109,7 @@ public class AnimationEvent extends AbstractCinematicEvent {
public AnimationEvent(Spatial model, String animationName, float initialDuration) { public AnimationEvent(Spatial model, String animationName, float initialDuration) {
super(initialDuration); super(initialDuration);
this.model = model; this.model = model;
this.modelName = model.getName();
this.animationName = animationName; this.animationName = animationName;
} }
@ -119,6 +125,7 @@ public class AnimationEvent extends AbstractCinematicEvent {
super(loopMode); super(loopMode);
initialDuration = model.getControl(AnimControl.class).getAnimationLength(animationName); initialDuration = model.getControl(AnimControl.class).getAnimationLength(animationName);
this.model = model; this.model = model;
this.modelName = model.getName();
this.animationName = animationName; this.animationName = animationName;
} }
@ -134,6 +141,7 @@ public class AnimationEvent extends AbstractCinematicEvent {
public AnimationEvent(Spatial model, String animationName, float initialDuration, LoopMode loopMode) { public AnimationEvent(Spatial model, String animationName, float initialDuration, LoopMode loopMode) {
super(initialDuration, loopMode); super(initialDuration, loopMode);
this.model = model; this.model = model;
this.modelName = model.getName();
this.animationName = animationName; this.animationName = animationName;
} }
@ -149,6 +157,7 @@ public class AnimationEvent extends AbstractCinematicEvent {
public AnimationEvent(Spatial model, String animationName, float initialDuration, float blendTime) { public AnimationEvent(Spatial model, String animationName, float initialDuration, float blendTime) {
super(initialDuration); super(initialDuration);
this.model = model; this.model = model;
this.modelName = model.getName();
this.animationName = animationName; this.animationName = animationName;
this.blendTime = blendTime; this.blendTime = blendTime;
} }
@ -167,6 +176,7 @@ public class AnimationEvent extends AbstractCinematicEvent {
super(loopMode); super(loopMode);
initialDuration = model.getControl(AnimControl.class).getAnimationLength(animationName); initialDuration = model.getControl(AnimControl.class).getAnimationLength(animationName);
this.model = model; this.model = model;
this.modelName = model.getName();
this.animationName = animationName; this.animationName = animationName;
this.blendTime = blendTime; this.blendTime = blendTime;
} }
@ -185,6 +195,7 @@ public class AnimationEvent extends AbstractCinematicEvent {
public AnimationEvent(Spatial model, String animationName, float initialDuration, LoopMode loopMode, float blendTime) { public AnimationEvent(Spatial model, String animationName, float initialDuration, LoopMode loopMode, float blendTime) {
super(initialDuration, loopMode); super(initialDuration, loopMode);
this.model = model; this.model = model;
this.modelName = model.getName();
this.animationName = animationName; this.animationName = animationName;
this.blendTime = blendTime; this.blendTime = blendTime;
} }
@ -203,6 +214,7 @@ public class AnimationEvent extends AbstractCinematicEvent {
super(loopMode); super(loopMode);
initialDuration = model.getControl(AnimControl.class).getAnimationLength(animationName); initialDuration = model.getControl(AnimControl.class).getAnimationLength(animationName);
this.model = model; this.model = model;
this.modelName = model.getName();
this.animationName = animationName; this.animationName = animationName;
this.channelIndex = channelIndex; this.channelIndex = channelIndex;
} }
@ -217,6 +229,7 @@ public class AnimationEvent extends AbstractCinematicEvent {
*/ */
public AnimationEvent(Spatial model, String animationName, int channelIndex) { public AnimationEvent(Spatial model, String animationName, int channelIndex) {
this.model = model; this.model = model;
this.modelName = model.getName();
this.animationName = animationName; this.animationName = animationName;
initialDuration = model.getControl(AnimControl.class).getAnimationLength(animationName); initialDuration = model.getControl(AnimControl.class).getAnimationLength(animationName);
this.channelIndex = channelIndex; this.channelIndex = channelIndex;
@ -233,6 +246,7 @@ public class AnimationEvent extends AbstractCinematicEvent {
*/ */
public AnimationEvent(Spatial model, String animationName, LoopMode loopMode, int channelIndex, float blendTime) { public AnimationEvent(Spatial model, String animationName, LoopMode loopMode, int channelIndex, float blendTime) {
this.model = model; this.model = model;
this.modelName = model.getName();
this.animationName = animationName; this.animationName = animationName;
this.loopMode = loopMode; this.loopMode = loopMode;
initialDuration = model.getControl(AnimControl.class).getAnimationLength(animationName); initialDuration = model.getControl(AnimControl.class).getAnimationLength(animationName);
@ -252,6 +266,7 @@ public class AnimationEvent extends AbstractCinematicEvent {
public AnimationEvent(Spatial model, String animationName, float initialDuration, int channelIndex) { public AnimationEvent(Spatial model, String animationName, float initialDuration, int channelIndex) {
super(initialDuration); super(initialDuration);
this.model = model; this.model = model;
this.modelName = model.getName();
this.animationName = animationName; this.animationName = animationName;
this.channelIndex = channelIndex; this.channelIndex = channelIndex;
} }
@ -270,6 +285,7 @@ public class AnimationEvent extends AbstractCinematicEvent {
public AnimationEvent(Spatial model, String animationName, float initialDuration, LoopMode loopMode, int channelIndex) { public AnimationEvent(Spatial model, String animationName, float initialDuration, LoopMode loopMode, int channelIndex) {
super(initialDuration, loopMode); super(initialDuration, loopMode);
this.model = model; this.model = model;
this.modelName = model.getName();
this.animationName = animationName; this.animationName = animationName;
this.channelIndex = channelIndex; this.channelIndex = channelIndex;
} }
@ -299,6 +315,18 @@ public class AnimationEvent extends AbstractCinematicEvent {
model = cinematic.getScene().getChild(modelName); model = cinematic.getScene().getChild(modelName);
} }
if (model != null) { if (model != null) {
if(cinematic.getScene() != null){
Spatial sceneModel = cinematic.getScene().getChild(model.getName());
if(sceneModel != null){
Node parent = sceneModel.getParent();
parent.detachChild(sceneModel);
sceneModel = model;
parent.attachChild(sceneModel);
} else {
cinematic.getScene().attachChild(model);
}
}
channel = model.getControl(AnimControl.class).createChannel(); channel = model.getControl(AnimControl.class).createChannel();
map.put(channelIndex, channel); map.put(channelIndex, channel);
} else { } else {
@ -401,6 +429,7 @@ public class AnimationEvent extends AbstractCinematicEvent {
OutputCapsule oc = ex.getCapsule(this); OutputCapsule oc = ex.getCapsule(this);
oc.write(model, "model", null); oc.write(model, "model", null);
oc.write(modelName, "modelName", null);
oc.write(animationName, "animationName", ""); oc.write(animationName, "animationName", "");
oc.write(blendTime, "blendTime", 0f); oc.write(blendTime, "blendTime", 0f);
oc.write(channelIndex, "channelIndex", 0); oc.write(channelIndex, "channelIndex", 0);
@ -411,9 +440,9 @@ public class AnimationEvent extends AbstractCinematicEvent {
public void read(JmeImporter im) throws IOException { public void read(JmeImporter im) throws IOException {
super.read(im); super.read(im);
InputCapsule ic = im.getCapsule(this); InputCapsule ic = im.getCapsule(this);
if (im.getFormatVersion() == 0) { // if (im.getFormatVersion() == 0) {
modelName = ic.readString("modelName", ""); modelName = ic.readString("modelName", "");
} // }
//FIXME always the same issue, because of the clonning of assets, this won't work //FIXME always the same issue, because of the clonning of assets, this won't work
//we have to somehow store userdata in the spatial and then recurse the //we have to somehow store userdata in the spatial and then recurse the
//scene sub scenegraph to find the correct instance of the model //scene sub scenegraph to find the correct instance of the model

View File

@ -0,0 +1,146 @@
/*
* Copyright (c) 2009-2017 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.jme3.cinematic.events;
import com.jme3.app.Application;
import com.jme3.cinematic.Cinematic;
import com.jme3.cinematic.TimeLine;
import com.jme3.export.InputCapsule;
import com.jme3.export.JmeExporter;
import com.jme3.export.JmeImporter;
import com.jme3.export.OutputCapsule;
import com.jme3.export.Savable;
import com.jme3.scene.CameraNode;
import java.io.IOException;
import java.util.Map;
/**
*
* @author Rickard <neph1 @ github>
*/
public class CameraEvent extends AbstractCinematicEvent{
private String cameraName;
private Cinematic cinematic;
public String getCameraName() {
return cameraName;
}
public void setCameraName(String cameraName) {
this.cameraName = cameraName;
}
public CameraEvent(){
}
public CameraEvent(Cinematic parentEvent, String cameraName){
this.cinematic = parentEvent;
this.cameraName = cameraName;
}
@Override
public void initEvent(Application app, Cinematic cinematic) {
super.initEvent(app, cinematic);
this.cinematic = cinematic;
}
@Override
public void play() {
super.play();
stop();
}
@Override
public void onPlay() {
cinematic.setActiveCamera(cameraName);
}
@Override
public void onUpdate(float tpf) {
}
@Override
public void onStop() {
}
@Override
public void onPause() {
}
@Override
public void forceStop() {
}
@Override
public void setTime(float time) {
play();
}
public Cinematic getCinematic() {
return cinematic;
}
public void setCinematic(Cinematic cinematic) {
this.cinematic = cinematic;
}
/**
* used internally for serialization
*
* @param ex
* @throws IOException
*/
@Override
public void write(JmeExporter ex) throws IOException {
super.write(ex);
OutputCapsule oc = ex.getCapsule(this);
oc.write(cameraName, "cameraName", null);
}
/**
* used internally for serialization
*
* @param im
* @throws IOException
*/
@Override
public void read(JmeImporter im) throws IOException {
super.read(im);
InputCapsule ic = im.getCapsule(this);
cameraName = ic.readString("cameraName", null);
}
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2016 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -274,23 +274,10 @@ public class MotionEvent extends AbstractCinematicEvent implements Control, JmeC
* @param spatial * @param spatial
* @return * @return
*/ */
@Deprecated
@Override @Override
public Control cloneForSpatial(Spatial spatial) { public Control cloneForSpatial(Spatial spatial) {
MotionEvent control = new MotionEvent(); throw new UnsupportedOperationException();
control.setPath(path);
control.playState = playState;
control.currentWayPoint = currentWayPoint;
control.currentValue = currentValue;
control.direction = direction.clone();
control.lookAt = lookAt;
control.upVector = upVector.clone();
control.rotation = rotation;
control.initialDuration = initialDuration;
control.speed = speed;
control.loopMode = loopMode;
control.directionType = directionType;
return control;
} }
@Override @Override

View File

@ -147,6 +147,7 @@ public class SoundEvent extends AbstractCinematicEvent {
* used for serialization * used for serialization
*/ */
public SoundEvent() { public SoundEvent() {
super();
} }
@Override @Override

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2012 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -217,7 +217,7 @@ class SweepSphere implements Collidable {
float signedDistanceToPlane = triPlane.pseudoDistance(sCenter); float signedDistanceToPlane = triPlane.pseudoDistance(sCenter);
if (normalDotVelocity == 0.0f){ if (normalDotVelocity == 0.0f){
// we are travelling exactly parrallel to the plane // we are travelling exactly parallel to the plane
if (FastMath.abs(signedDistanceToPlane) >= 1.0f){ if (FastMath.abs(signedDistanceToPlane) >= 1.0f){
// no collision possible // no collision possible
return null; return null;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2012 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -121,10 +121,10 @@ public class ParticleEmitter extends Geometry {
this.parentEmitter = parentEmitter; this.parentEmitter = parentEmitter;
} }
@Deprecated
@Override @Override
public Control cloneForSpatial(Spatial spatial) { public Control cloneForSpatial(Spatial spatial) {
return this; // WARNING: Sets wrong control on spatial. Will be throw new UnsupportedOperationException();
// fixed automatically by ParticleEmitter.clone() method.
} }
@Override @Override
@ -384,7 +384,7 @@ public class ParticleEmitter extends Geometry {
* Set to true if particles should spawn in world space. * Set to true if particles should spawn in world space.
* *
* <p>If set to true and the particle emitter is moved in the scene, * <p>If set to true and the particle emitter is moved in the scene,
* then particles that have already spawned won't be effected by this * then particles that have already spawned won't be affected by this
* motion. If set to false, the particles will emit in local space * motion. If set to false, the particles will emit in local space
* and when the emitter is moved, so are all the particles that * and when the emitter is moved, so are all the particles that
* were emitted previously. * were emitted previously.
@ -846,7 +846,7 @@ public class ParticleEmitter extends Geometry {
* @param initialVelocity Set the initial velocity a particle is spawned with, * @param initialVelocity Set the initial velocity a particle is spawned with,
* the initial velocity given in the parameter will be varied according * the initial velocity given in the parameter will be varied according
* to the velocity variation set in {@link ParticleEmitter#setVelocityVariation(float) }. * to the velocity variation set in {@link ParticleEmitter#setVelocityVariation(float) }.
* A particle will move toward its velocity unless it is effected by the * The particle will move with this velocity unless it is affected by
* gravity. * gravity.
* *
* @deprecated * @deprecated

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2012 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -64,7 +64,7 @@ public interface ParticleInfluencer extends Savable, Cloneable, JmeCloneable {
* Set the initial velocity a particle is spawned with, * Set the initial velocity a particle is spawned with,
* the initial velocity given in the parameter will be varied according * the initial velocity given in the parameter will be varied according
* to the velocity variation set in {@link ParticleEmitter#setVelocityVariation(float) }. * to the velocity variation set in {@link ParticleEmitter#setVelocityVariation(float) }.
* A particle will move toward its velocity unless it is effected by the * The particle will move with this velocity unless it is affected by
* gravity. * gravity.
*/ */
void setInitialVelocity(Vector3f initialVelocity); void setInitialVelocity(Vector3f initialVelocity);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2012 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -37,7 +37,7 @@ import com.jme3.scene.Mesh;
import java.util.List; import java.util.List;
/** /**
* This emiter shape emits the particles from the given shape's interior constrained by its convex hull * This emitter shape emits the particles from the given shape's interior constrained by its convex hull
* (a geometry that tightly wraps the mesh). So in case of multiple meshes some vertices may appear * (a geometry that tightly wraps the mesh). So in case of multiple meshes some vertices may appear
* in a space between them. * in a space between them.
* @author Marcin Roguski (Kaelthas) * @author Marcin Roguski (Kaelthas)

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2012 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -40,7 +40,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
* This emiter shape emits the particles from the given shape's faces. * This emitter shape emits the particles from the given shape's faces.
* @author Marcin Roguski (Kaelthas) * @author Marcin Roguski (Kaelthas)
*/ */
public class EmitterMeshFaceShape extends EmitterMeshVertexShape { public class EmitterMeshFaceShape extends EmitterMeshVertexShape {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2012 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -50,7 +50,7 @@ import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
/** /**
* This emiter shape emits the particles from the given shape's vertices * This emitter shape emits the particles from the given shape's vertices
* @author Marcin Roguski (Kaelthas) * @author Marcin Roguski (Kaelthas)
*/ */
public class EmitterMeshVertexShape implements EmitterShape { public class EmitterMeshVertexShape implements EmitterShape {
@ -74,7 +74,7 @@ public class EmitterMeshVertexShape implements EmitterShape {
} }
/** /**
* This method sets the meshes that will form the emiter's shape. * This method sets the meshes that will form the emitter's shape.
* @param meshes * @param meshes
* a list of meshes that will form the emitter's shape * a list of meshes that will form the emitter's shape
*/ */

View File

@ -96,10 +96,12 @@ public class EmitterSphereShape implements EmitterShape {
@Override @Override
public void getRandomPoint(Vector3f store) { public void getRandomPoint(Vector3f store) {
do { do {
store.x = (FastMath.nextRandomFloat() * 2f - 1f) * radius; store.x = (FastMath.nextRandomFloat() * 2f - 1f);
store.y = (FastMath.nextRandomFloat() * 2f - 1f) * radius; store.y = (FastMath.nextRandomFloat() * 2f - 1f);
store.z = (FastMath.nextRandomFloat() * 2f - 1f) * radius; store.z = (FastMath.nextRandomFloat() * 2f - 1f);
} while (store.distance(center) > radius); } while (store.lengthSquared() > 1);
store.multLocal(radius);
store.addLocal(center);
} }
@Override @Override

View File

@ -48,6 +48,7 @@ import com.jme3.texture.Texture2D;
import com.jme3.texture.TextureCubeMap; import com.jme3.texture.TextureCubeMap;
import com.jme3.texture.image.ColorSpace; import com.jme3.texture.image.ColorSpace;
import com.jme3.util.BufferUtils; import com.jme3.util.BufferUtils;
import com.jme3.util.MipMapGenerator;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.ArrayList; import java.util.ArrayList;
@ -72,6 +73,8 @@ public class EnvironmentCamera extends BaseAppState {
protected Image.Format imageFormat = Image.Format.RGB16F; protected Image.Format imageFormat = Image.Format.RGB16F;
public TextureCubeMap debugEnv;
//Axis for cameras //Axis for cameras
static { static {
//PositiveX axis(left, up, direction) //PositiveX axis(left, up, direction)
@ -188,10 +191,11 @@ public class EnvironmentCamera extends BaseAppState {
buffers[i] = BufferUtils.createByteBuffer(size * size * imageFormat.getBitsPerPixel() / 8); buffers[i] = BufferUtils.createByteBuffer(size * size * imageFormat.getBitsPerPixel() / 8);
renderManager.getRenderer().readFrameBufferWithFormat(framebuffers[i], buffers[i], imageFormat); renderManager.getRenderer().readFrameBufferWithFormat(framebuffers[i], buffers[i], imageFormat);
images[i] = new Image(imageFormat, size, size, buffers[i], ColorSpace.Linear); images[i] = new Image(imageFormat, size, size, buffers[i], ColorSpace.Linear);
MipMapGenerator.generateMipMaps(images[i]);
} }
final TextureCubeMap map = EnvMapUtils.makeCubeMap(images[0], images[1], images[2], images[3], images[4], images[5], imageFormat); final TextureCubeMap map = EnvMapUtils.makeCubeMap(images[0], images[1], images[2], images[3], images[4], images[5], imageFormat);
debugEnv = map;
job.callback.done(map); job.callback.done(map);
map.getImage().dispose(); map.getImage().dispose();
jobs.remove(0); jobs.remove(0);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2015 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -31,13 +31,14 @@
*/ */
package com.jme3.environment; package com.jme3.environment;
import com.jme3.environment.generation.*;
import com.jme3.light.LightProbe;
import com.jme3.environment.util.EnvMapUtils;
import com.jme3.app.Application; import com.jme3.app.Application;
import com.jme3.environment.generation.*;
import com.jme3.environment.util.EnvMapUtils;
import com.jme3.light.LightProbe;
import com.jme3.scene.Node; import com.jme3.scene.Node;
import com.jme3.scene.Spatial; import com.jme3.scene.Spatial;
import com.jme3.texture.TextureCubeMap; import com.jme3.texture.TextureCubeMap;
import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ScheduledThreadPoolExecutor;
/** /**
@ -46,7 +47,7 @@ import java.util.concurrent.ScheduledThreadPoolExecutor;
* Since the process can be long, you can provide a JobProgressListener that * Since the process can be long, you can provide a JobProgressListener that
* will be notified of the ongoing generation process when calling the makeProbe method. * will be notified of the ongoing generation process when calling the makeProbe method.
* *
* The process is the folowing : * The process is as follows:
* 1. Create an EnvironmentCamera * 1. Create an EnvironmentCamera
* 2. give it a position in the scene * 2. give it a position in the scene
* 3. call {@link LightProbeFactory#makeProbe(com.jme3.environment.EnvironmentCamera, com.jme3.scene.Node)} * 3. call {@link LightProbeFactory#makeProbe(com.jme3.environment.EnvironmentCamera, com.jme3.scene.Node)}
@ -60,7 +61,7 @@ import java.util.concurrent.ScheduledThreadPoolExecutor;
* This class is entirely thread safe and can be called from any thread. * This class is entirely thread safe and can be called from any thread.
* *
* Note that in case you are using a {@link JobProgressListener} all the its * Note that in case you are using a {@link JobProgressListener} all the its
* method will be called inside and app.enqueu callable. * method will be called inside and app.enqueue callable.
* This means that it's completely safe to modify the scenegraph within the * This means that it's completely safe to modify the scenegraph within the
* Listener method, but also means that the even will be delayed until next update loop. * Listener method, but also means that the even will be delayed until next update loop.
* *
@ -72,7 +73,7 @@ public class LightProbeFactory {
/** /**
* Creates a LightProbe with the giver EnvironmentCamera in the given scene. * Creates a LightProbe with the giver EnvironmentCamera in the given scene.
* *
* Note that this is an assynchronous process that will run on multiple threads. * Note that this is an asynchronous process that will run on multiple threads.
* The process is thread safe. * The process is thread safe.
* The created lightProbe will only be marked as ready when the rendering process is done. * The created lightProbe will only be marked as ready when the rendering process is done.
* *
@ -93,7 +94,7 @@ public class LightProbeFactory {
/** /**
* Creates a LightProbe with the giver EnvironmentCamera in the given scene. * Creates a LightProbe with the giver EnvironmentCamera in the given scene.
* *
* Note that this is an assynchronous process that will run on multiple threads. * Note that this is an asynchronous process that will run on multiple threads.
* The process is thread safe. * The process is thread safe.
* The created lightProbe will only be marked as ready when the rendering process is done. * The created lightProbe will only be marked as ready when the rendering process is done.
* *
@ -106,10 +107,11 @@ public class LightProbeFactory {
* @param envCam the EnvironmentCamera * @param envCam the EnvironmentCamera
* @param scene the Scene * @param scene the Scene
* @param listener the listener of the genration progress. * @param genType Fast or HighQuality. Fast may be ok for many types of environment, but you may need high quality when an environment map has very high lighting values.
* @param listener the listener of the generation progress.
* @return the created LightProbe * @return the created LightProbe
*/ */
public static LightProbe makeProbe(final EnvironmentCamera envCam, Spatial scene, final JobProgressListener<LightProbe> listener) { public static LightProbe makeProbe(final EnvironmentCamera envCam, Spatial scene, final EnvMapUtils.GenerationType genType, final JobProgressListener<LightProbe> listener) {
final LightProbe probe = new LightProbe(); final LightProbe probe = new LightProbe();
probe.setPosition(envCam.getPosition()); probe.setPosition(envCam.getPosition());
probe.setPrefilteredMap(EnvMapUtils.createPrefilteredEnvMap(envCam.getSize(), envCam.getImageFormat())); probe.setPrefilteredMap(EnvMapUtils.createPrefilteredEnvMap(envCam.getSize(), envCam.getImageFormat()));
@ -117,33 +119,37 @@ public class LightProbeFactory {
@Override @Override
public void done(TextureCubeMap map) { public void done(TextureCubeMap map) {
generatePbrMaps(map, probe, envCam.getApplication(), listener); generatePbrMaps(map, probe, envCam.getApplication(), genType, listener);
} }
}); });
return probe; return probe;
} }
public static LightProbe makeProbe(final EnvironmentCamera envCam, Spatial scene, final JobProgressListener<LightProbe> listener) {
return makeProbe(envCam, scene, EnvMapUtils.GenerationType.Fast, listener);
}
/** /**
* Updates a LightProbe with the giver EnvironmentCamera in the given scene. * Updates a LightProbe with the given EnvironmentCamera in the given scene.
* * <p>
* Note that this is an assynchronous process that will run on multiple threads. * Note that this is an asynchronous process that will run on multiple threads.
* The process is thread safe. * The process is thread safe.
* The created lightProbe will only be marked as ready when the rendering process is done. * The created lightProbe will only be marked as ready when the rendering process is done.
* * <p>
* The JobProgressListener will be notified of the progress of the generation. * The JobProgressListener will be notified of the progress of the generation.
* Note that you can also use a {@link JobProgressAdapter}. * Note that you can also use a {@link JobProgressAdapter}.
* *
* @see LightProbe
* @see EnvironmentCamera
* @see JobProgressListener
*
* @param probe the Light probe to update * @param probe the Light probe to update
* @param envCam the EnvironmentCamera * @param envCam the EnvironmentCamera
* @param scene the Scene * @param scene the Scene
* @param listener the listener of the genration progress. * @param genType Fast or HighQuality. Fast may be ok for many types of environment, but you may need high quality when an environment map has very high lighting values.
* @param listener the listener of the generation progress.
* @return the created LightProbe * @return the created LightProbe
* @see LightProbe
* @see EnvironmentCamera
* @see JobProgressListener
*/ */
public static LightProbe updateProbe(final LightProbe probe, final EnvironmentCamera envCam, Spatial scene, final JobProgressListener<LightProbe> listener) { public static LightProbe updateProbe(final LightProbe probe, final EnvironmentCamera envCam, Spatial scene, final EnvMapUtils.GenerationType genType, final JobProgressListener<LightProbe> listener) {
envCam.setPosition(probe.getPosition()); envCam.setPosition(probe.getPosition());
@ -159,23 +165,27 @@ public class LightProbeFactory {
@Override @Override
public void done(TextureCubeMap map) { public void done(TextureCubeMap map) {
generatePbrMaps(map, probe, envCam.getApplication(), listener); generatePbrMaps(map, probe, envCam.getApplication(), genType, listener);
} }
}); });
return probe; return probe;
} }
public static LightProbe updateProbe(final LightProbe probe, final EnvironmentCamera envCam, Spatial scene, final JobProgressListener<LightProbe> listener) {
return updateProbe(probe, envCam, scene, EnvMapUtils.GenerationType.Fast, listener);
}
/** /**
* Internally called to generate the maps. * Internally called to generate the maps.
* This method will spawn 7 thread (one for the Irradiance spherical harmonics generator, and one for each face of the prefiltered env map). * This method will spawn 7 thread (one for the Irradiance spherical harmonics generator, and one for each face of the prefiltered env map).
* Those threads will be executed in a ScheduledThreadPoolExecutor that will be shutdown when the genration is done. * Those threads will be executed in a ScheduledThreadPoolExecutor that will be shutdown when the generation is done.
* *
* @param envMap the raw env map rendered by the env camera * @param envMap the raw env map rendered by the env camera
* @param probe the LigthProbe to generate maps for * @param probe the LightProbe to generate maps for
* @param app the Application * @param app the Application
* @param listener a progress listener. (can be null if no progress reporting is needed) * @param listener a progress listener. (can be null if no progress reporting is needed)
*/ */
private static void generatePbrMaps(TextureCubeMap envMap, final LightProbe probe, Application app, final JobProgressListener<LightProbe> listener) { private static void generatePbrMaps(TextureCubeMap envMap, final LightProbe probe, Application app, EnvMapUtils.GenerationType genType, final JobProgressListener<LightProbe> listener) {
IrradianceSphericalHarmonicsGenerator irrShGenerator; IrradianceSphericalHarmonicsGenerator irrShGenerator;
PrefilteredEnvMapFaceGenerator[] pemGenerators = new PrefilteredEnvMapFaceGenerator[6]; PrefilteredEnvMapFaceGenerator[] pemGenerators = new PrefilteredEnvMapFaceGenerator[6];
@ -189,7 +199,7 @@ public class LightProbeFactory {
for (int i = 0; i < pemGenerators.length; i++) { for (int i = 0; i < pemGenerators.length; i++) {
pemGenerators[i] = new PrefilteredEnvMapFaceGenerator(app, i, new JobListener(listener, jobState, probe, i)); pemGenerators[i] = new PrefilteredEnvMapFaceGenerator(app, i, new JobListener(listener, jobState, probe, i));
pemGenerators[i].setGenerationParam(EnvMapUtils.duplicateCubeMap(envMap), size, EnvMapUtils.FixSeamsMethod.None, probe.getPrefilteredEnvMap()); pemGenerators[i].setGenerationParam(EnvMapUtils.duplicateCubeMap(envMap), size, EnvMapUtils.FixSeamsMethod.None, genType, probe.getPrefilteredEnvMap());
jobState.executor.execute(pemGenerators[i]); jobState.executor.execute(pemGenerators[i]);
} }
} }
@ -227,7 +237,7 @@ public class LightProbeFactory {
} }
/** /**
* An inner JobProgressListener to controll the genration process and properly clean up when it's done * An inner JobProgressListener to control the generation process and properly clean up when it's done
*/ */
private static class JobListener extends JobProgressAdapter<Integer> { private static class JobListener extends JobProgressAdapter<Integer> {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2015 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -73,7 +73,7 @@ public class IrradianceSphericalHarmonicsGenerator extends RunnableWithProgress
} }
/** /**
* Fills all the genration parameters * Fills all the generation parameters
* *
* @param sourceMap the source cube map * @param sourceMap the source cube map
* {@link EnvMapUtils.FixSeamsMethod} * {@link EnvMapUtils.FixSeamsMethod}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2015 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -31,30 +31,22 @@
*/ */
package com.jme3.environment.generation; package com.jme3.environment.generation;
import com.jme3.app.Application;
import com.jme3.environment.util.CubeMapWrapper; import com.jme3.environment.util.CubeMapWrapper;
import com.jme3.environment.util.EnvMapUtils; import com.jme3.environment.util.EnvMapUtils;
import com.jme3.app.Application;
import com.jme3.math.*; import com.jme3.math.*;
import static com.jme3.math.FastMath.abs;
import static com.jme3.math.FastMath.clamp;
import static com.jme3.math.FastMath.pow;
import static com.jme3.math.FastMath.sqrt;
import com.jme3.texture.TextureCubeMap; import com.jme3.texture.TextureCubeMap;
import static com.jme3.environment.util.EnvMapUtils.getHammersleyPoint;
import static com.jme3.environment.util.EnvMapUtils.getRoughnessFromMip;
import static com.jme3.environment.util.EnvMapUtils.getSampleFromMip;
import static com.jme3.environment.util.EnvMapUtils.getVectorFromCubemapFaceTexCoord;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import static com.jme3.environment.util.EnvMapUtils.*;
import static com.jme3.math.FastMath.abs;
import static com.jme3.math.FastMath.sqrt;
/** /**
* Generates one face of the prefiltered environnement map for PBR. This job can * Generates one face of the prefiltered environment map for PBR. This job can
* be lauched from a separate thread. * be launched from a separate thread.
* <p> * <p>
* TODO there is a lot of duplicate code here with the EnvMapUtils. * TODO there is a lot of duplicate code here with the EnvMapUtils.
* *
@ -69,6 +61,7 @@ public class PrefilteredEnvMapFaceGenerator extends RunnableWithProgress {
private int targetMapSize; private int targetMapSize;
private EnvMapUtils.FixSeamsMethod fixSeamsMethod; private EnvMapUtils.FixSeamsMethod fixSeamsMethod;
private EnvMapUtils.GenerationType genType;
private TextureCubeMap sourceMap; private TextureCubeMap sourceMap;
private TextureCubeMap store; private TextureCubeMap store;
private final Application app; private final Application app;
@ -98,7 +91,7 @@ public class PrefilteredEnvMapFaceGenerator extends RunnableWithProgress {
/** /**
* Fills all the genration parameters * Fills all the generation parameters
* *
* @param sourceMap the source cube map * @param sourceMap the source cube map
* @param targetMapSize the size of the generated map (width or height in * @param targetMapSize the size of the generated map (width or height in
@ -107,11 +100,12 @@ public class PrefilteredEnvMapFaceGenerator extends RunnableWithProgress {
* {@link EnvMapUtils.FixSeamsMethod} * {@link EnvMapUtils.FixSeamsMethod}
* @param store The cube map to store the result in. * @param store The cube map to store the result in.
*/ */
public void setGenerationParam(TextureCubeMap sourceMap, int targetMapSize, EnvMapUtils.FixSeamsMethod fixSeamsMethod, TextureCubeMap store) { public void setGenerationParam(TextureCubeMap sourceMap, int targetMapSize, EnvMapUtils.FixSeamsMethod fixSeamsMethod, EnvMapUtils.GenerationType genType, TextureCubeMap store) {
this.sourceMap = sourceMap; this.sourceMap = sourceMap;
this.targetMapSize = targetMapSize; this.targetMapSize = targetMapSize;
this.fixSeamsMethod = fixSeamsMethod; this.fixSeamsMethod = fixSeamsMethod;
this.store = store; this.store = store;
this.genType = genType;
init(); init();
} }
@ -162,12 +156,16 @@ public class PrefilteredEnvMapFaceGenerator extends RunnableWithProgress {
* @return The irradiance cube map for the given coefficients * @return The irradiance cube map for the given coefficients
*/ */
private TextureCubeMap generatePrefilteredEnvMap(TextureCubeMap sourceEnvMap, int targetMapSize, EnvMapUtils.FixSeamsMethod fixSeamsMethod, TextureCubeMap store) { private TextureCubeMap generatePrefilteredEnvMap(TextureCubeMap sourceEnvMap, int targetMapSize, EnvMapUtils.FixSeamsMethod fixSeamsMethod, TextureCubeMap store) {
try {
TextureCubeMap pem = store; TextureCubeMap pem = store;
int nbMipMap = (int) (Math.log(targetMapSize) / Math.log(2) - 1); int nbMipMap = store.getImage().getMipMapSizes().length;
setEnd(nbMipMap); setEnd(nbMipMap);
if (!sourceEnvMap.getImage().hasMipmaps() || sourceEnvMap.getImage().getMipMapSizes().length < nbMipMap) {
throw new IllegalArgumentException("The input cube map must have at least " + nbMipMap + "mip maps");
}
CubeMapWrapper sourceWrapper = new CubeMapWrapper(sourceEnvMap); CubeMapWrapper sourceWrapper = new CubeMapWrapper(sourceEnvMap);
CubeMapWrapper targetWrapper = new CubeMapWrapper(pem); CubeMapWrapper targetWrapper = new CubeMapWrapper(pem);
@ -175,55 +173,88 @@ public class PrefilteredEnvMapFaceGenerator extends RunnableWithProgress {
Vector3f texelVect = new Vector3f(); Vector3f texelVect = new Vector3f();
Vector3f color = new Vector3f(); Vector3f color = new Vector3f();
ColorRGBA outColor = new ColorRGBA(); ColorRGBA outColor = new ColorRGBA();
int targetMipMapSize = targetMapSize;
for (int mipLevel = 0; mipLevel < nbMipMap; mipLevel++) { for (int mipLevel = 0; mipLevel < nbMipMap; mipLevel++) {
float roughness = getRoughnessFromMip(mipLevel, nbMipMap); float roughness = getRoughnessFromMip(mipLevel, nbMipMap);
int nbSamples = getSampleFromMip(mipLevel, nbMipMap); int nbSamples = getSampleFromMip(mipLevel, nbMipMap);
int targetMipMapSize = (int) pow(2, nbMipMap + 1 - mipLevel);
for (int y = 0; y < targetMipMapSize; y++) { for (int y = 0; y < targetMipMapSize; y++) {
for (int x = 0; x < targetMipMapSize; x++) { for (int x = 0; x < targetMipMapSize; x++) {
color.set(0, 0, 0); color.set(0, 0, 0);
getVectorFromCubemapFaceTexCoord(x, y, targetMipMapSize, face, texelVect, fixSeamsMethod); getVectorFromCubemapFaceTexCoord(x, y, targetMipMapSize, face, texelVect, fixSeamsMethod);
prefilterEnvMapTexel(sourceWrapper, roughness, texelVect, nbSamples, color); prefilterEnvMapTexel(sourceWrapper, roughness, texelVect, nbSamples, mipLevel, color);
outColor.set(Math.max(color.x, 0.0001f), Math.max(color.y, 0.0001f), Math.max(color.z, 0.0001f), 1); outColor.set(Math.max(color.x, 0.0001f), Math.max(color.y, 0.0001f), Math.max(color.z, 0.0001f), 1);
log.log(Level.FINE, "coords {0},{1}", new Object[]{x, y});
targetWrapper.setPixel(x, y, face, mipLevel, outColor); targetWrapper.setPixel(x, y, face, mipLevel, outColor);
} }
} }
targetMipMapSize /= 2;
progress(); progress();
} }
return pem; return pem;
} catch (Exception e) {
e.printStackTrace();
throw e;
}
} }
private Vector3f prefilterEnvMapTexel(CubeMapWrapper envMapReader, float roughness, Vector3f N, int numSamples, Vector3f store) { private Vector3f prefilterEnvMapTexel(CubeMapWrapper envMapReader, float roughness, Vector3f N, int numSamples, int mipLevel, Vector3f store) {
Vector3f prefilteredColor = store; Vector3f prefilteredColor = store;
float totalWeight = 0.0f; float totalWeight = 0.0f;
int nbRotations = 1;
if (genType == GenerationType.HighQuality) {
nbRotations = numSamples == 1 ? 1 : 18;
}
float rad = 2f * FastMath.PI / (float) nbRotations;
// offset rotation to avoid sampling pattern
float gi = (float) (FastMath.abs(N.z + N.x) * 256.0);
float offset = rad * (FastMath.cos((gi * 0.5f) % (2f * FastMath.PI)) * 0.5f + 0.5f);
// a = roughness² and a2 = a² // a = roughness² and a2 = a²
float a2 = roughness * roughness; float a2 = roughness * roughness;
a2 *= a2; a2 *= a2;
//Computing tangent frame
Vector3f upVector = Vector3f.UNIT_X;
if (abs(N.z) < 0.999) {
upVector = Vector3f.UNIT_Y;
}
Vector3f tangentX = tmp1.set(upVector).crossLocal(N).normalizeLocal();
Vector3f tangentY = tmp2.set(N).crossLocal(tangentX);
// https://placeholderart.wordpress.com/2015/07/28/implementation-notes-runtime-environment-map-filtering-for-image-based-lighting/
// in local space view == normal == 0,0,1
Vector3f V = new Vector3f(0, 0, 1);
Vector3f lWorld = new Vector3f();
for (int i = 0; i < numSamples; i++) { for (int i = 0; i < numSamples; i++) {
Xi = getHammersleyPoint(i, numSamples, Xi); Xi = getHammersleyPoint(i, numSamples, Xi);
H = importanceSampleGGX(Xi, a2, N, H); H = importanceSampleGGX(Xi, a2, H);
H.normalizeLocal(); H.normalizeLocal();
tmp.set(H); float VoH = H.z;
float NoH = N.dot(tmp); Vector3f L = H.multLocal(VoH * 2f).subtractLocal(V);
float NoL = L.z;
Vector3f L = tmp.multLocal(NoH * 2).subtractLocal(N); float computedMipLevel = mipLevel;
float NoL = clamp(N.dot(L), 0.0f, 1.0f); if (mipLevel != 0) {
if (NoL > 0) { computedMipLevel = computeMipLevel(roughness, numSamples, this.targetMapSize, VoH);
envMapReader.getPixel(L, c);
prefilteredColor.setX(prefilteredColor.x + c.r * NoL);
prefilteredColor.setY(prefilteredColor.y + c.g * NoL);
prefilteredColor.setZ(prefilteredColor.z + c.b * NoL);
totalWeight += NoL;
} }
toWorld(L, N, tangentX, tangentY, lWorld);
totalWeight += samplePixel(envMapReader, lWorld, NoL, computedMipLevel, prefilteredColor);
for (int j = 1; j < nbRotations; j++) {
rotateDirection(offset + j * rad, L, lWorld);
L.set(lWorld);
toWorld(L, N, tangentX, tangentY, lWorld);
totalWeight += samplePixel(envMapReader, lWorld, NoL, computedMipLevel, prefilteredColor);
}
} }
if (totalWeight > 0) { if (totalWeight > 0) {
prefilteredColor.divideLocal(totalWeight); prefilteredColor.divideLocal(totalWeight);
@ -232,7 +263,78 @@ public class PrefilteredEnvMapFaceGenerator extends RunnableWithProgress {
return prefilteredColor; return prefilteredColor;
} }
public Vector3f importanceSampleGGX(Vector4f xi, float a2, Vector3f normal, Vector3f store) { private float samplePixel(CubeMapWrapper envMapReader, Vector3f lWorld, float NoL, float computedMipLevel, Vector3f store) {
if (NoL <= 0) {
return 0;
}
envMapReader.getPixel(lWorld, computedMipLevel, c);
store.setX(store.x + c.r * NoL);
store.setY(store.y + c.g * NoL);
store.setZ(store.z + c.b * NoL);
return NoL;
}
private void toWorld(Vector3f L, Vector3f N, Vector3f tangentX, Vector3f tangentY, Vector3f store) {
store.set(tangentX).multLocal(L.x);
tmp.set(tangentY).multLocal(L.y);
store.addLocal(tmp);
tmp.set(N).multLocal(L.z);
store.addLocal(tmp);
}
private float computeMipLevel(float roughness, int numSamples, float size, float voH) {
// H[2] is NoH in local space
// adds 1.e-5 to avoid ggx / 0.0
float NoH = voH + 1E-5f;
// Probability Distribution Function
float Pdf = ggx(NoH, roughness) * NoH / (4.0f * voH);
// Solid angle represented by this sample
float omegaS = 1.0f / (numSamples * Pdf);
// Solid angle covered by 1 pixel with 6 faces that are EnvMapSize X EnvMapSize
float omegaP = 4.0f * FastMath.PI / (6.0f * size * size);
// Original paper suggest biasing the mip to improve the results
float mipBias = 1.0f; // I tested that the result is better with bias 1
double maxLod = Math.log(size) / Math.log(2f);
double log2 = Math.log(omegaS / omegaP) / Math.log(2);
return Math.min(Math.max(0.5f * (float) log2 + mipBias, 0.0f), (float) maxLod);
}
private float ggx(float NoH, float alpha) {
// use GGX / Trowbridge-Reitz, same as Disney and Unreal 4
// cf http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf p3
float tmp = alpha / (NoH * NoH * (alpha * alpha - 1.0f) + 1.0f);
return tmp * tmp * (1f / FastMath.PI);
}
private Vector3f rotateDirection(float angle, Vector3f l, Vector3f store) {
float s, c, t;
s = FastMath.sin(angle);
c = FastMath.cos(angle);
t = 1.f - c;
store.x = l.x * c + l.y * s;
store.y = -l.x * s + l.y * c;
store.z = l.z * (t + c);
return store;
}
/**
* Computes GGX half vector in local space
*
* @param xi
* @param a2
* @param store
* @return
*/
public Vector3f importanceSampleGGX(Vector4f xi, float a2, Vector3f store) {
if (store == null) { if (store == null) {
store = new Vector3f(); store = new Vector3f();
} }
@ -243,22 +345,9 @@ public class PrefilteredEnvMapFaceGenerator extends RunnableWithProgress {
float sinThetaCosPhi = sinTheta * xi.z;//xi.z is cos(phi) float sinThetaCosPhi = sinTheta * xi.z;//xi.z is cos(phi)
float sinThetaSinPhi = sinTheta * xi.w;//xi.w is sin(phi) float sinThetaSinPhi = sinTheta * xi.w;//xi.w is sin(phi)
Vector3f upVector = Vector3f.UNIT_X; store.x = sinThetaCosPhi;
store.y = sinThetaSinPhi;
if (abs(normal.z) < 0.999) { store.z = cosTheta;
upVector = Vector3f.UNIT_Y;
}
Vector3f tangentX = tmp1.set(upVector).crossLocal(normal).normalizeLocal();
Vector3f tangentY = tmp2.set(normal).crossLocal(tangentX);
// Tangent to world space
tangentX.multLocal(sinThetaCosPhi);
tangentY.multLocal(sinThetaSinPhi);
tmp3.set(normal).multLocal(cosTheta);
// Tangent to world space
store.set(tangentX).addLocal(tangentY).addLocal(tmp3);
return store; return store;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2015 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -61,7 +61,7 @@ public abstract class RunnableWithProgress implements Runnable {
} }
/** /**
* return the curent progress of the process. * return the current progress of the process.
* *
* @return * @return
*/ */

View File

@ -31,17 +31,15 @@
*/ */
package com.jme3.environment.util; package com.jme3.environment.util;
import com.jme3.environment.util.EnvMapUtils; import com.jme3.math.*;
import com.jme3.math.ColorRGBA;
import static com.jme3.math.FastMath.pow;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.texture.Image; import com.jme3.texture.Image;
import com.jme3.texture.TextureCubeMap; import com.jme3.texture.TextureCubeMap;
import com.jme3.texture.image.DefaultImageRaster; import com.jme3.texture.image.DefaultImageRaster;
import com.jme3.texture.image.MipMapImageRaster; import com.jme3.texture.image.MipMapImageRaster;
import com.jme3.util.BufferUtils; import com.jme3.util.BufferUtils;
import static com.jme3.math.FastMath.pow;
/** /**
* Wraps a Cube map and allows to read from or write pixels into it. * Wraps a Cube map and allows to read from or write pixels into it.
* *
@ -57,6 +55,8 @@ public class CubeMapWrapper {
private final Vector2f uvs = new Vector2f(); private final Vector2f uvs = new Vector2f();
private final Image image; private final Image image;
private final ColorRGBA tmpColor = new ColorRGBA();
/** /**
* Creates a CubeMapWrapper for the given cube map * Creates a CubeMapWrapper for the given cube map
* Note that the cube map must be initialized, and the mipmaps sizes should * Note that the cube map must be initialized, and the mipmaps sizes should
@ -105,7 +105,7 @@ public class CubeMapWrapper {
* @param store the color in which to store the pixel color read. * @param store the color in which to store the pixel color read.
* @return the color of the pixel read. * @return the color of the pixel read.
*/ */
public ColorRGBA getPixel(Vector3f vector, int mipLevel, ColorRGBA store) { public ColorRGBA getPixel(Vector3f vector, float mipLevel, ColorRGBA store) {
if (mipMapRaster == null) { if (mipMapRaster == null) {
throw new IllegalArgumentException("This cube map has no mip maps"); throw new IllegalArgumentException("This cube map has no mip maps");
} }
@ -113,10 +113,26 @@ public class CubeMapWrapper {
store = new ColorRGBA(); store = new ColorRGBA();
} }
int face = EnvMapUtils.getCubemapFaceTexCoordFromVector(vector, sizes[mipLevel], uvs, EnvMapUtils.FixSeamsMethod.Stretch); int lowerMipLevel = (int) mipLevel;
int higherMipLevel = (int) FastMath.ceil(mipLevel);
float ratio = mipLevel - lowerMipLevel;
int face = EnvMapUtils.getCubemapFaceTexCoordFromVector(vector, sizes[lowerMipLevel], uvs, EnvMapUtils.FixSeamsMethod.Stretch);
mipMapRaster.setSlice(face); mipMapRaster.setSlice(face);
mipMapRaster.setMipLevel(mipLevel); mipMapRaster.setMipLevel(lowerMipLevel);
return mipMapRaster.getPixel((int) uvs.x, (int) uvs.y, store); mipMapRaster.getPixel((int) uvs.x, (int) uvs.y, store);
face = EnvMapUtils.getCubemapFaceTexCoordFromVector(vector, sizes[higherMipLevel], uvs, EnvMapUtils.FixSeamsMethod.Stretch);
mipMapRaster.setSlice(face);
mipMapRaster.setMipLevel(higherMipLevel);
mipMapRaster.getPixel((int) uvs.x, (int) uvs.y, tmpColor);
store.r = FastMath.interpolateLinear(ratio, store.r, tmpColor.r);
store.g = FastMath.interpolateLinear(ratio, store.g, tmpColor.g);
store.b = FastMath.interpolateLinear(ratio, store.b, tmpColor.b);
store.a = FastMath.interpolateLinear(ratio, store.a, tmpColor.a);
return store;
} }
/** /**

View File

@ -37,19 +37,16 @@ import com.jme3.math.*;
import com.jme3.scene.Geometry; import com.jme3.scene.Geometry;
import com.jme3.scene.Node; import com.jme3.scene.Node;
import com.jme3.scene.shape.Quad; import com.jme3.scene.shape.Quad;
import com.jme3.texture.Image; import com.jme3.texture.*;
import com.jme3.texture.Texture;
import com.jme3.texture.Texture2D;
import com.jme3.texture.TextureCubeMap;
import com.jme3.texture.image.ColorSpace; import com.jme3.texture.image.ColorSpace;
import com.jme3.ui.Picture; import com.jme3.ui.Picture;
import com.jme3.util.BufferUtils; import com.jme3.util.BufferUtils;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import static com.jme3.math.FastMath.*;
import com.jme3.util.TempVars; import com.jme3.util.TempVars;
import java.nio.ByteBuffer;
import static com.jme3.math.FastMath.*;
/** /**
* *
* This class holds several utility method unseful for Physically Based * This class holds several utility method unseful for Physically Based
@ -88,6 +85,11 @@ public class EnvMapUtils {
None None
} }
public static enum GenerationType {
Fast,
HighQuality
}
/** /**
* Creates a cube map from 6 images * Creates a cube map from 6 images
* *
@ -117,6 +119,8 @@ public class EnvMapUtils {
cubeImage.addData(backImg.getData(0)); cubeImage.addData(backImg.getData(0));
cubeImage.addData(frontImg.getData(0)); cubeImage.addData(frontImg.getData(0));
cubeImage.setMipMapSizes(rightImg.getMipMapSizes());
TextureCubeMap cubeMap = new TextureCubeMap(cubeImage); TextureCubeMap cubeMap = new TextureCubeMap(cubeImage);
cubeMap.setAnisotropicFilter(0); cubeMap.setAnisotropicFilter(0);
cubeMap.setMagFilter(Texture.MagFilter.Bilinear); cubeMap.setMagFilter(Texture.MagFilter.Bilinear);
@ -148,6 +152,8 @@ public class EnvMapUtils {
cubeImage.addData(d.duplicate()); cubeImage.addData(d.duplicate());
} }
cubeImage.setMipMapSizes(srcImg.getMipMapSizes());
TextureCubeMap cubeMap = new TextureCubeMap(cubeImage); TextureCubeMap cubeMap = new TextureCubeMap(cubeImage);
cubeMap.setAnisotropicFilter(sourceMap.getAnisotropicFilter()); cubeMap.setAnisotropicFilter(sourceMap.getAnisotropicFilter());
cubeMap.setMagFilter(sourceMap.getMagFilter()); cubeMap.setMagFilter(sourceMap.getMagFilter());
@ -730,7 +736,7 @@ public class EnvMapUtils {
pem.setMagFilter(Texture.MagFilter.Bilinear); pem.setMagFilter(Texture.MagFilter.Bilinear);
pem.setMinFilter(Texture.MinFilter.Trilinear); pem.setMinFilter(Texture.MinFilter.Trilinear);
pem.getImage().setColorSpace(ColorSpace.Linear); pem.getImage().setColorSpace(ColorSpace.Linear);
int nbMipMap = (int) (Math.log(size) / Math.log(2) - 1); int nbMipMap = Math.min(6, (int) (Math.log(size) / Math.log(2)));
CubeMapWrapper targetWrapper = new CubeMapWrapper(pem); CubeMapWrapper targetWrapper = new CubeMapWrapper(pem);
targetWrapper.initMipMaps(nbMipMap); targetWrapper.initMipMaps(nbMipMap);
return pem; return pem;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2015 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -114,7 +114,7 @@ public class LightsDebugState extends BaseAppState {
} }
/** /**
* Set the scenes for wich to render light gizmos. * Set the scenes for which to render light gizmos.
* @param scene * @param scene
*/ */
public void setScene(Spatial scene) { public void setScene(Spatial scene) {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2012 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -34,7 +34,6 @@ package com.jme3.input;
import com.jme3.export.InputCapsule; import com.jme3.export.InputCapsule;
import com.jme3.export.JmeExporter; import com.jme3.export.JmeExporter;
import com.jme3.export.JmeImporter; import com.jme3.export.JmeImporter;
import com.jme3.export.OutputCapsule;
import com.jme3.input.controls.*; import com.jme3.input.controls.*;
import com.jme3.math.FastMath; import com.jme3.math.FastMath;
import com.jme3.math.Vector3f; import com.jme3.math.Vector3f;
@ -420,7 +419,7 @@ public class ChaseCamera implements ActionListener, AnalogListener, Control, Jme
//the user is rotating the cam by dragging the mouse //the user is rotating the cam by dragging the mouse
if (canRotate) { if (canRotate) {
//reseting the trailing lerp factor //reset the trailing lerp factor
trailingLerpFactor = 0; trailingLerpFactor = 0;
//stop trailing user has the control //stop trailing user has the control
trailing = false; trailing = false;
@ -582,15 +581,14 @@ public class ChaseCamera implements ActionListener, AnalogListener, Control, Jme
/** /**
* clone this camera for a spatial * clone this camera for a spatial
*
* @param spatial * @param spatial
* @return * @return
*/ */
@Deprecated
@Override @Override
public Control cloneForSpatial(Spatial spatial) { public Control cloneForSpatial(Spatial spatial) {
ChaseCamera cc = new ChaseCamera(cam, spatial, inputManager); throw new UnsupportedOperationException();
cc.setMaxDistance(getMaxDistance());
cc.setMinDistance(getMinDistance());
return cc;
} }
@Override @Override

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2012 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -423,16 +423,23 @@ public class InputManager implements RawInputListener {
/** /**
* Callback from RawInputListener. Do not use. * Callback from RawInputListener. Do not use.
*
* @param evt event to add to the input queue (not null)
*/ */
@Override @Override
public void onMouseMotionEvent(MouseMotionEvent evt) { public void onMouseMotionEvent(MouseMotionEvent evt) {
if (!eventsPermitted) { /*
throw new UnsupportedOperationException("MouseInput has raised an event at an illegal time."); * If events aren't allowed, the event may be a "first mouse event"
} * triggered by the constructor setting the mouse listener.
* In that case, use the event to initialize the cursor position,
* but don't queue it for further processing.
* This is part of the fix for issue #792.
*/
cursorPos.set(evt.getX(), evt.getY()); cursorPos.set(evt.getX(), evt.getY());
if (eventsPermitted) {
inputQueue.add(evt); inputQueue.add(evt);
} }
}
private void onMouseButtonEventQueued(MouseButtonEvent evt) { private void onMouseButtonEventQueued(MouseButtonEvent evt) {
int hash = MouseButtonTrigger.mouseButtonHash(evt.getButtonIndex()); int hash = MouseButtonTrigger.mouseButtonHash(evt.getButtonIndex());
@ -867,7 +874,7 @@ public class InputManager implements RawInputListener {
// larynx, 2011.06.10 - flag event as reusable because // larynx, 2011.06.10 - flag event as reusable because
// the android input uses a non-allocating ringbuffer which // the android input uses a non-allocating ringbuffer which
// needs to know when the event is not anymore in inputQueue // needs to know when the event is not anymore in inputQueue
// and therefor can be reused. // and therefore can be reused.
event.setConsumed(); event.setConsumed();
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2012 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -123,7 +123,7 @@ public interface Joystick {
/** /**
* Returns the POV Y axis for this joystick. This is a convenience axis * Returns the POV Y axis for this joystick. This is a convenience axis
* providing an y-axis subview of the HAT axis. * providing a y-axis subview of the HAT axis.
* *
* @see JoystickAxis#assignAxis(java.lang.String, java.lang.String) * @see JoystickAxis#assignAxis(java.lang.String, java.lang.String)
*/ */

View File

@ -445,6 +445,16 @@ public interface KeyInput extends Input {
* (J3100). * (J3100).
*/ */
public static final int KEY_UNLABELED = 0x97; public static final int KEY_UNLABELED = 0x97;
/**
* PrtScr key.
* Note: for use on keyboards with a PrtScr key that is
* separate from the SysRq key. Most keyboards combine
* SysRq and PrtScr so if the intent is to actually
* capture the user's desire to capture the screen
* then SysRq is the most likely scan code.
* Use PrtScr to catch the rest (laptops, mini-keyboards, etc.)
*/
public static final int KEY_PRTSCR = 0x9A;
/** /**
* Enter key (num pad). * Enter key (num pad).
*/ */

View File

@ -128,14 +128,12 @@ public class LightProbe extends Light implements Savable {
super.read(im); super.read(im);
InputCapsule ic = im.getCapsule(this); InputCapsule ic = im.getCapsule(this);
prefilteredEnvMap = (TextureCubeMap) ic.readSavable("prefilteredEnvMap", null); prefilteredEnvMap = (TextureCubeMap) ic.readSavable("prefilteredEnvMap", null);
position = (Vector3f) ic.readSavable("position", this); position = (Vector3f) ic.readSavable("position", null);
bounds = (BoundingVolume) ic.readSavable("bounds", new BoundingSphere(1.0f, Vector3f.ZERO)); bounds = (BoundingVolume) ic.readSavable("bounds", new BoundingSphere(1.0f, Vector3f.ZERO));
nbMipMaps = ic.readInt("nbMipMaps", 0); nbMipMaps = ic.readInt("nbMipMaps", 0);
ready = ic.readBoolean("ready", false); ready = ic.readBoolean("ready", false);
Savable[] coeffs = ic.readSavableArray("shCoeffs", null); Savable[] coeffs = ic.readSavableArray("shCoeffs", null);
if (coeffs == null) { if (coeffs == null) {
ready = false; ready = false;
@ -145,7 +143,6 @@ public class LightProbe extends Light implements Savable {
for (int i = 0; i < coeffs.length; i++) { for (int i = 0; i < coeffs.length; i++) {
shCoeffs[i] = (Vector3f) coeffs[i]; shCoeffs[i] = (Vector3f) coeffs[i];
} }
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2015 jMonkeyEngine * Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -48,7 +48,7 @@ public interface LightProbeBlendingStrategy {
public void registerProbe(LightProbe probe); public void registerProbe(LightProbe probe);
/** /**
* Populates the resulting light probes into the given light list. * Populates the resulting light probes into the given light list.
* @param g the geometry for wich the light list is computed * @param g the geometry for which the light list is computed
* @param lightList the result light list * @param lightList the result light list
*/ */
public void populateProbes(Geometry g, LightList lightList); public void populateProbes(Geometry g, LightList lightList);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2012, 2015-2016 jMonkeyEngine * Copyright (c) 2009-2012, 2015-2016, 2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -54,7 +54,7 @@ import java.io.IOException;
* <p> * <p>
* In addition to a position, point lights also have a radius which * In addition to a position, point lights also have a radius which
* can be used to attenuate the influence of the light depending on the * can be used to attenuate the influence of the light depending on the
* distance between the light and the effected object. * distance between the light and the affected object.
* *
*/ */
public class PointLight extends Light { public class PointLight extends Light {
@ -155,7 +155,7 @@ public class PointLight extends Light {
* Setting a non-zero radius indicates the light should use attenuation. * Setting a non-zero radius indicates the light should use attenuation.
* If a pixel's distance to this light's position * If a pixel's distance to this light's position
* is greater than the light's radius, then the pixel will not be * is greater than the light's radius, then the pixel will not be
* effected by this light, if the distance is less than the radius, then * affected by this light, if the distance is less than the radius, then
* the magnitude of the influence is equal to distance / radius. * the magnitude of the influence is equal to distance / radius.
* *
* @param radius the radius of the light influence. * @param radius the radius of the light influence.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2012, 2015-2016 jMonkeyEngine * Copyright (c) 2009-2012, 2015-2016, 2018 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -337,7 +337,7 @@ public class SpotLight extends Light {
* Setting a non-zero range indicates the light should use attenuation. * Setting a non-zero range indicates the light should use attenuation.
* If a pixel's distance to this light's position * If a pixel's distance to this light's position
* is greater than the light's range, then the pixel will not be * is greater than the light's range, then the pixel will not be
* effected by this light, if the distance is less than the range, then * affected by this light, if the distance is less than the range, then
* the magnitude of the influence is equal to distance / range. * the magnitude of the influence is equal to distance / range.
* *
* @param spotRange the range of the light influence. * @param spotRange the range of the light influence.

View File

@ -0,0 +1,45 @@
/*
* Copyright (c) 2009-2018 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.jme3.material;
/**
* This class is to provide some constants materials.
*
* @author oualid
*/
public class Materials {
public static final String UNSHADED = "Common/MatDefs/Misc/Unshaded.j3md";
public static final String LIGHTING = "Common/MatDefs/Light/Lighting.j3md";
public static final String PBR = "Common/MatDefs/Light/PBRLighting.j3md";
}

View File

@ -206,7 +206,9 @@ public class ShaderGenerationInfo implements Savable, Cloneable {
clone.vertexUniforms.add(uniform.clone()); clone.vertexUniforms.add(uniform.clone());
} }
if (vertexGlobal != null) {
clone.vertexGlobal = vertexGlobal.clone(); clone.vertexGlobal = vertexGlobal.clone();
}
for (ShaderNodeVariable varying : varyings) { for (ShaderNodeVariable varying : varyings) {
clone.varyings.add(varying.clone()); clone.varyings.add(varying.clone());

Some files were not shown because too many files have changed in this diff Show More