Merge branch 'master' of https://github.com/jMonkeyEngine/jmonkeyengine.git
This commit is contained in:
commit
f9f3c0185e
17
.gitignore
vendored
17
.gitignore
vendored
@ -1,11 +1,13 @@
|
|||||||
/.gradle/
|
/.gradle/
|
||||||
/.nb-gradle/private/
|
/.nb-gradle/private/
|
||||||
/.nb-gradle/profiles/private/
|
/.nb-gradle/profiles/private/
|
||||||
|
/.idea/
|
||||||
/dist/
|
/dist/
|
||||||
/build/
|
/build/
|
||||||
/netbeans/
|
/netbeans/
|
||||||
|
/sdk/jdks/local/
|
||||||
/jme3-core/build/
|
/jme3-core/build/
|
||||||
/jme3-core/src/main/java/com/jme3/system/JmeVersion.java
|
/jme3-core/src/main/resources/com/jme3/system/version.properties
|
||||||
/jme3-plugins/build/
|
/jme3-plugins/build/
|
||||||
/jme3-desktop/build/
|
/jme3-desktop/build/
|
||||||
/jme3-android-native/build/
|
/jme3-android-native/build/
|
||||||
@ -80,6 +82,7 @@
|
|||||||
/sdk/jme3-vehicle-creator/build/
|
/sdk/jme3-vehicle-creator/build/
|
||||||
/sdk/jme3-welcome-screen/build/
|
/sdk/jme3-welcome-screen/build/
|
||||||
/sdk/jme3-glsl-support/build/
|
/sdk/jme3-glsl-support/build/
|
||||||
|
/sdk/jme3-dark-laf/build/
|
||||||
/sdk/nbproject/private/
|
/sdk/nbproject/private/
|
||||||
/sdk/jme3-scenecomposer/nbproject/private/
|
/sdk/jme3-scenecomposer/nbproject/private/
|
||||||
/sdk/jme3-core/nbproject/private/
|
/sdk/jme3-core/nbproject/private/
|
||||||
@ -125,6 +128,7 @@
|
|||||||
*.so
|
*.so
|
||||||
*.jnilib
|
*.jnilib
|
||||||
*.dylib
|
*.dylib
|
||||||
|
*.iml
|
||||||
/sdk/dist/
|
/sdk/dist/
|
||||||
!/jme3-bullet-native/libs/native/windows/x86_64/bulletjme.dll
|
!/jme3-bullet-native/libs/native/windows/x86_64/bulletjme.dll
|
||||||
!/jme3-bullet-native/libs/native/windows/x86/bulletjme.dll
|
!/jme3-bullet-native/libs/native/windows/x86/bulletjme.dll
|
||||||
@ -132,3 +136,14 @@
|
|||||||
!/jme3-bullet-native/libs/native/osx/x86_64/libbulletjme.dylib
|
!/jme3-bullet-native/libs/native/osx/x86_64/libbulletjme.dylib
|
||||||
!/jme3-bullet-native/libs/native/linux/x86/libbulletjme.so
|
!/jme3-bullet-native/libs/native/linux/x86/libbulletjme.so
|
||||||
!/jme3-bullet-native/libs/native/linux/x86_64/libbulletjme.so
|
!/jme3-bullet-native/libs/native/linux/x86_64/libbulletjme.so
|
||||||
|
/.nb-gradle/
|
||||||
|
/sdk/ant-jme/nbproject/private/
|
||||||
|
/sdk/nbi/stub/ext/engine/nbproject/private/
|
||||||
|
/sdk/nbi/stub/ext/components/products/jdk/nbproject/private/
|
||||||
|
/sdk/nbi/stub/ext/components/products/blender/nbproject/private/
|
||||||
|
/sdk/nbi/stub/ext/components/products/helloworld/nbproject/private/
|
||||||
|
/sdk/BasicGameTemplate/nbproject/private/
|
||||||
|
/sdk/nbi/stub/ext/components/products/jdk/build/
|
||||||
|
/sdk/nbi/stub/ext/components/products/jdk/dist/
|
||||||
|
/sdk/jme3-dark-laf/nbproject/private/
|
||||||
|
jme3-lwjgl3/build/
|
||||||
|
20
.travis.yml
20
.travis.yml
@ -8,9 +8,9 @@ cache:
|
|||||||
- gradle-cache
|
- gradle-cache
|
||||||
- netbeans
|
- netbeans
|
||||||
|
|
||||||
branches:
|
# branches:
|
||||||
only:
|
# only:
|
||||||
- master
|
# - master
|
||||||
|
|
||||||
notifications:
|
notifications:
|
||||||
slack:
|
slack:
|
||||||
@ -25,16 +25,26 @@ install:
|
|||||||
script:
|
script:
|
||||||
- ./gradlew check
|
- ./gradlew check
|
||||||
- ./gradlew createZipDistribution
|
- ./gradlew createZipDistribution
|
||||||
|
- "[ $TRAVIS_BRANCH == 'master' ] && [ $TRAVIS_PULL_REQUEST == 'false' ] && ./gradlew uploadArchives || :"
|
||||||
|
|
||||||
|
before_deploy:
|
||||||
|
- export RELEASE_DIST=$(ls build/distributions/*.zip)
|
||||||
|
|
||||||
deploy:
|
deploy:
|
||||||
provider: releases
|
provider: releases
|
||||||
api_key:
|
api_key:
|
||||||
secure: "KbFiMt0a8FxUKvCJUYwikLYaqqGMn1p6k4OsXnGqwptQZEUIayabNLHeaD2kTNT3e6AY1ETwQLff/lB2LttmIo4g5NWW63g1K3A/HwgnhJwETengiProZ/Udl+ugPeDL/+ar43HUhFq4knBnzFKnEcHAThTPVqH/RMDvZf1UUYI="
|
secure: PuEsJd6juXBH29ByITW3ntSAyrwWs0IeFvXJ5Y2YlhojhSMtTwkoWeB6YmDJWP4fhzbajk4TQ1HlOX2IxJXSW/8ShOEIUlGXz9fHiST0dkSM+iRAUgC5enCLW5ITPTiem7eY9ZhS9miIam7ngce9jHNMh75PTzZrEJtezoALT9w=
|
||||||
file: build/distributions/jME3.1.0_snapshot-github_2015-06-20.zip
|
file_glob: true
|
||||||
|
file: "${RELEASE_DIST}"
|
||||||
skip_cleanup: true
|
skip_cleanup: true
|
||||||
on:
|
on:
|
||||||
|
repo: jMonkeyEngine/jmonkeyengine
|
||||||
tags: true
|
tags: true
|
||||||
|
|
||||||
|
before_install:
|
||||||
|
- git fetch --unshallow
|
||||||
|
- "[ $TRAVIS_PULL_REQUEST == 'false' ] && openssl aes-256-cbc -K $encrypted_a1949b55824a_key -iv $encrypted_a1949b55824a_iv -in private/www-updater.key.enc -out private/www-updater.key -d || :"
|
||||||
|
|
||||||
# before_install:
|
# before_install:
|
||||||
# required libs for android build tools
|
# required libs for android build tools
|
||||||
# sudo apt-get update
|
# sudo apt-get update
|
||||||
|
@ -16,13 +16,6 @@ When you're ready to submit your code, just make a [pull request](https://help.g
|
|||||||
- When committing, always be sure to run an update before you commit. If there is a conflict between the latest revision and your patch after the update, then it is your responsibility to track down the update that caused the conflict and determine the issue (and fix it). In the case where the breaking commit has no thread linked (and one cannot be found in the forum), then the contributor should contact an administrator and wait for feedback before committing.
|
- When committing, always be sure to run an update before you commit. If there is a conflict between the latest revision and your patch after the update, then it is your responsibility to track down the update that caused the conflict and determine the issue (and fix it). In the case where the breaking commit has no thread linked (and one cannot be found in the forum), then the contributor should contact an administrator and wait for feedback before committing.
|
||||||
- If your code is committed and it introduces new functionality, please edit the wiki accordingly. We can easily roll back to previous revisions, so just do your best; point us to it and we’ll see if it sticks!
|
- If your code is committed and it introduces new functionality, please edit the wiki accordingly. We can easily roll back to previous revisions, so just do your best; point us to it and we’ll see if it sticks!
|
||||||
|
|
||||||
**Note to Eclipse users:** The Eclipse [git client does not support https](http://hub.jmonkeyengine.org/forum/topic/problem-cloning-the-new-git-repository/#post-265594). The current workaround is to use the command line to clone the repository.
|
|
||||||
To import the local repository as a project follow these steps:
|
|
||||||
|
|
||||||
1. Add a line 'apply plugin: eclipse' to your common.gradle file in the main project directory.
|
|
||||||
2. Navigate to the project directory in command line and execute command 'gradle eclipse'. This will load all the dependancies for eclipse.
|
|
||||||
3. In Eclipse, add the repository as an existing Java Project.
|
|
||||||
|
|
||||||
p.s. We will try hold ourselves to a [certain standard](http://www.defmacro.org/2013/04/03/issue-etiquette.html) when it comes to GitHub etiquette. If at any point we fail to uphold this standard, let us know.
|
p.s. We will try hold ourselves to a [certain standard](http://www.defmacro.org/2013/04/03/issue-etiquette.html) when it comes to GitHub etiquette. If at any point we fail to uphold this standard, let us know.
|
||||||
|
|
||||||
#### Core Contributors
|
#### Core Contributors
|
||||||
|
32
build.gradle
32
build.gradle
@ -10,6 +10,8 @@ buildscript {
|
|||||||
}
|
}
|
||||||
|
|
||||||
apply plugin: 'base'
|
apply plugin: 'base'
|
||||||
|
apply from: file('version.gradle')
|
||||||
|
apply from: file('upload.gradle')
|
||||||
|
|
||||||
// This is applied to all sub projects
|
// This is applied to all sub projects
|
||||||
subprojects {
|
subprojects {
|
||||||
@ -59,8 +61,7 @@ task libDist(dependsOn: subprojects.build) << {
|
|||||||
}
|
}
|
||||||
|
|
||||||
task createZipDistribution(type:Zip,dependsOn:["dist","libDist"], description:"Package the nightly zip distribution"){
|
task createZipDistribution(type:Zip,dependsOn:["dist","libDist"], description:"Package the nightly zip distribution"){
|
||||||
archiveName "jME"+jmeVersion+"_"+jmeVersionTag+"_"+new Date().format("yyyy-MM-dd")+".zip"
|
archiveName "jME" + jmeFullVersion + ".zip"
|
||||||
|
|
||||||
into("/") {
|
into("/") {
|
||||||
from {"./dist"}
|
from {"./dist"}
|
||||||
}
|
}
|
||||||
@ -114,7 +115,12 @@ task wrapper(type: Wrapper, description: 'Creates and deploys the Gradle wrapper
|
|||||||
gradleVersion = '2.2.1'
|
gradleVersion = '2.2.1'
|
||||||
}
|
}
|
||||||
|
|
||||||
String findNDK() {
|
ext {
|
||||||
|
ndkCommandPath = ""
|
||||||
|
ndkExists = false
|
||||||
|
}
|
||||||
|
|
||||||
|
task configureAndroidNDK {
|
||||||
def ndkBuildFile = "ndk-build"
|
def ndkBuildFile = "ndk-build"
|
||||||
// if windows, use ndk-build.cmd instead
|
// if windows, use ndk-build.cmd instead
|
||||||
if (System.properties['os.name'].toLowerCase().contains('windows')) {
|
if (System.properties['os.name'].toLowerCase().contains('windows')) {
|
||||||
@ -127,27 +133,13 @@ String findNDK() {
|
|||||||
if (System.env.ANDROID_NDK != null) {
|
if (System.env.ANDROID_NDK != null) {
|
||||||
ndkBuildPath = System.env.ANDROID_NDK + File.separator + ndkBuildFile
|
ndkBuildPath = System.env.ANDROID_NDK + File.separator + ndkBuildFile
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new File(ndkBuildPath).exists()) {
|
if (new File(ndkBuildPath).exists()) {
|
||||||
return ndkBuildPath
|
ndkExists = true
|
||||||
} else {
|
ndkCommandPath = ndkBuildPath
|
||||||
return null
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean checkNdkExists(String ndkCommandPath) {
|
|
||||||
// String ndkCommandPath = findNDK()
|
|
||||||
if (ndkCommandPath != null && new File(ndkCommandPath).exists()) {
|
|
||||||
return true
|
|
||||||
} else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ext {
|
|
||||||
ndkCommandPath = findNDK()
|
|
||||||
ndkExists = checkNdkExists(ndkCommandPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
//class IncrementalReverseTask extends DefaultTask {
|
//class IncrementalReverseTask extends DefaultTask {
|
||||||
// @InputDirectory
|
// @InputDirectory
|
||||||
// def File inputDir
|
// def File inputDir
|
||||||
|
@ -4,10 +4,9 @@
|
|||||||
|
|
||||||
apply plugin: 'java'
|
apply plugin: 'java'
|
||||||
apply plugin: 'maven'
|
apply plugin: 'maven'
|
||||||
apply plugin: 'maven-publish'
|
|
||||||
|
|
||||||
group = 'com.jme3'
|
group = 'com.jme3'
|
||||||
version = jmeVersion + '-' + jmeVersionTag
|
version = jmePomVersion
|
||||||
|
|
||||||
sourceCompatibility = '1.6'
|
sourceCompatibility = '1.6'
|
||||||
[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
|
[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
|
||||||
@ -19,9 +18,23 @@ repositories {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
configurations {
|
||||||
|
deployerJars
|
||||||
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
// Adding dependencies here will add the dependencies to each subproject.
|
// Adding dependencies here will add the dependencies to each subproject.
|
||||||
testCompile group: 'junit', name: 'junit', version: '4.10'
|
testCompile group: 'junit', name: 'junit', version: '4.12'
|
||||||
|
testCompile group: 'org.mockito', name: 'mockito-core', version: '2.0.28-beta'
|
||||||
|
testCompile group: 'org.easytesting', name: 'fest-assert-core', version: '2.0M10'
|
||||||
|
deployerJars "org.apache.maven.wagon:wagon-ssh:2.9"
|
||||||
|
}
|
||||||
|
|
||||||
|
jar {
|
||||||
|
manifest {
|
||||||
|
attributes 'Implementation-Title': 'jMonkeyEngine',
|
||||||
|
'Implementation-Version': jmeFullVersion
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
javadoc {
|
javadoc {
|
||||||
@ -56,16 +69,18 @@ artifacts {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
publishing {
|
uploadArchives {
|
||||||
publications {
|
repositories.mavenDeployer {
|
||||||
maven(MavenPublication) {
|
configuration = configurations.deployerJars
|
||||||
from components.java
|
|
||||||
artifact sourcesJar
|
|
||||||
artifact javadocJar
|
|
||||||
|
|
||||||
pom.withXml {
|
// disable this otherwise it will fill up the server with stale jars
|
||||||
asNode().children().last() + {
|
uniqueVersion = false
|
||||||
resolveStrategy = Closure.DELEGATE_FIRST
|
|
||||||
|
repository(url: "scp://updates.jmonkeyengine.org/var/www/updates/maven") {
|
||||||
|
authentication(userName: "www-updater", privateKey: "private/www-updater.key")
|
||||||
|
}
|
||||||
|
|
||||||
|
pom.project {
|
||||||
name POM_NAME
|
name POM_NAME
|
||||||
description POM_DESCRIPTION
|
description POM_DESCRIPTION
|
||||||
url POM_URL
|
url POM_URL
|
||||||
@ -84,14 +99,6 @@ publishing {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
repositories {
|
|
||||||
maven {
|
|
||||||
url "${rootProject.buildDir}/repo" // change to point to your repo, e.g. http://my.org/repo
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
task createFolders(description: 'Creates the source folders if they do not exist.') doLast {
|
task createFolders(description: 'Creates the source folders if they do not exist.') doLast {
|
||||||
// sourceSets*.allSource*.srcDirs*.each { File srcDir ->
|
// sourceSets*.allSource*.srcDirs*.each { File srcDir ->
|
||||||
|
@ -3,7 +3,9 @@ jmeVersion = 3.1.0
|
|||||||
# Version used for application and settings folder, no spaces!
|
# Version used for application and settings folder, no spaces!
|
||||||
jmeMainVersion = 3.1
|
jmeMainVersion = 3.1
|
||||||
# Version addition pre-alpha-svn, Stable, Beta
|
# Version addition pre-alpha-svn, Stable, Beta
|
||||||
jmeVersionTag = snapshot-github
|
jmeVersionTag = SNAPSHOT
|
||||||
|
# Increment this each time jmeVersionTag changes but jmeVersion stays the same
|
||||||
|
jmeVersionTagID = 0
|
||||||
|
|
||||||
# specify if JavaDoc should be built
|
# specify if JavaDoc should be built
|
||||||
buildJavaDoc = true
|
buildJavaDoc = true
|
||||||
|
@ -122,9 +122,13 @@ public class JmeAndroidSystem extends JmeSystemDelegate {
|
|||||||
return Platform.Android_ARM6;
|
return Platform.Android_ARM6;
|
||||||
} else if (arch.contains("v7")) {
|
} else if (arch.contains("v7")) {
|
||||||
return Platform.Android_ARM7;
|
return Platform.Android_ARM7;
|
||||||
|
} else if (arch.contains("v8")) {
|
||||||
|
return Platform.Android_ARM8;
|
||||||
} else {
|
} else {
|
||||||
return Platform.Android_ARM5; // unknown ARM
|
return Platform.Android_ARM5; // unknown ARM
|
||||||
}
|
}
|
||||||
|
} else if (arch.contains("aarch")) {
|
||||||
|
return Platform.Android_ARM8;
|
||||||
} else {
|
} else {
|
||||||
return Platform.Android_Other;
|
return Platform.Android_Other;
|
||||||
}
|
}
|
||||||
|
@ -230,18 +230,22 @@ public class BlenderKey extends ModelKey {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Not used any more.
|
||||||
* This method sets the asset root path.
|
* This method sets the asset root path.
|
||||||
* @param assetRootPath
|
* @param assetRootPath
|
||||||
* the assets root path
|
* the assets root path
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public void setAssetRootPath(String assetRootPath) {
|
public void setAssetRootPath(String assetRootPath) {
|
||||||
this.assetRootPath = assetRootPath;
|
this.assetRootPath = assetRootPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Not used any more.
|
||||||
* This method returns the asset root path.
|
* This method returns the asset root path.
|
||||||
* @return the asset root path
|
* @return the asset root path
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public String getAssetRootPath() {
|
public String getAssetRootPath() {
|
||||||
return assetRootPath;
|
return assetRootPath;
|
||||||
}
|
}
|
||||||
|
@ -31,8 +31,6 @@
|
|||||||
*/
|
*/
|
||||||
package com.jme3.scene.plugins.blender;
|
package com.jme3.scene.plugins.blender;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -40,25 +38,17 @@ import java.util.Map.Entry;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import com.jme3.animation.Animation;
|
|
||||||
import com.jme3.asset.AssetNotFoundException;
|
import com.jme3.asset.AssetNotFoundException;
|
||||||
import com.jme3.asset.BlenderKey;
|
import com.jme3.asset.BlenderKey;
|
||||||
import com.jme3.export.Savable;
|
import com.jme3.export.Savable;
|
||||||
import com.jme3.light.Light;
|
|
||||||
import com.jme3.math.FastMath;
|
import com.jme3.math.FastMath;
|
||||||
import com.jme3.math.Quaternion;
|
import com.jme3.math.Quaternion;
|
||||||
import com.jme3.post.Filter;
|
|
||||||
import com.jme3.renderer.Camera;
|
|
||||||
import com.jme3.scene.Node;
|
|
||||||
import com.jme3.scene.Spatial;
|
import com.jme3.scene.Spatial;
|
||||||
import com.jme3.scene.plugins.blender.BlenderContext.LoadedDataType;
|
import com.jme3.scene.plugins.blender.BlenderContext.LoadedDataType;
|
||||||
import com.jme3.scene.plugins.blender.file.BlenderFileException;
|
import com.jme3.scene.plugins.blender.file.BlenderFileException;
|
||||||
import com.jme3.scene.plugins.blender.file.Pointer;
|
import com.jme3.scene.plugins.blender.file.Pointer;
|
||||||
import com.jme3.scene.plugins.blender.file.Structure;
|
import com.jme3.scene.plugins.blender.file.Structure;
|
||||||
import com.jme3.scene.plugins.blender.materials.MaterialContext;
|
|
||||||
import com.jme3.scene.plugins.blender.meshes.TemporalMesh;
|
|
||||||
import com.jme3.scene.plugins.blender.objects.Properties;
|
import com.jme3.scene.plugins.blender.objects.Properties;
|
||||||
import com.jme3.texture.Texture;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A purpose of the helper class is to split calculation code into several classes. Each helper after use should be cleared because it can
|
* A purpose of the helper class is to split calculation code into several classes. Each helper after use should be cleared because it can
|
||||||
@ -157,7 +147,6 @@ public abstract class AbstractBlenderHelper {
|
|||||||
* @throws BlenderFileException
|
* @throws BlenderFileException
|
||||||
* and exception is throw when problems with reading a blend file occur
|
* and exception is throw when problems with reading a blend file occur
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
protected Object loadLibrary(Structure id) throws BlenderFileException {
|
protected Object loadLibrary(Structure id) throws BlenderFileException {
|
||||||
Pointer pLib = (Pointer) id.getFieldValue("lib");
|
Pointer pLib = (Pointer) id.getFieldValue("lib");
|
||||||
if (pLib.isNotNull()) {
|
if (pLib.isNotNull()) {
|
||||||
@ -167,79 +156,21 @@ public abstract class AbstractBlenderHelper {
|
|||||||
String path = library.getFieldValue("filepath").toString();
|
String path = library.getFieldValue("filepath").toString();
|
||||||
|
|
||||||
if (!blenderContext.getLinkedFeatures().keySet().contains(path)) {
|
if (!blenderContext.getLinkedFeatures().keySet().contains(path)) {
|
||||||
File file = new File(path);
|
|
||||||
List<String> pathsToCheck = new ArrayList<String>();
|
|
||||||
String currentPath = file.getName();
|
|
||||||
do {
|
|
||||||
pathsToCheck.add(currentPath);
|
|
||||||
file = file.getParentFile();
|
|
||||||
if (file != null) {
|
|
||||||
currentPath = file.getName() + '/' + currentPath;
|
|
||||||
}
|
|
||||||
} while (file != null);
|
|
||||||
|
|
||||||
Spatial loadedAsset = null;
|
Spatial loadedAsset = null;
|
||||||
BlenderKey blenderKey = null;
|
BlenderKey blenderKey = new BlenderKey(path);
|
||||||
for (String p : pathsToCheck) {
|
|
||||||
blenderKey = new BlenderKey(p);
|
|
||||||
blenderKey.setLoadUnlinkedAssets(true);
|
blenderKey.setLoadUnlinkedAssets(true);
|
||||||
try {
|
try {
|
||||||
loadedAsset = blenderContext.getAssetManager().loadAsset(blenderKey);
|
loadedAsset = blenderContext.getAssetManager().loadAsset(blenderKey);
|
||||||
break;// break if no exception was thrown
|
|
||||||
} catch (AssetNotFoundException e) {
|
} catch (AssetNotFoundException e) {
|
||||||
LOGGER.log(Level.FINEST, "Cannot locate linked resource at path: {0}.", p);
|
LOGGER.log(Level.FINEST, "Cannot locate linked resource at path: {0}.", path);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (loadedAsset != null) {
|
if (loadedAsset != null) {
|
||||||
Map<String, Map<String, Object>> linkedData = loadedAsset.getUserData("linkedData");
|
Map<String, Map<String, Object>> linkedData = loadedAsset.getUserData("linkedData");
|
||||||
|
|
||||||
for (Entry<String, Map<String, Object>> entry : linkedData.entrySet()) {
|
for (Entry<String, Map<String, Object>> entry : linkedData.entrySet()) {
|
||||||
String linkedDataFilePath = "this".equals(entry.getKey()) ? path : entry.getKey();
|
String linkedDataFilePath = "this".equals(entry.getKey()) ? path : entry.getKey();
|
||||||
|
blenderContext.getLinkedFeatures().put(linkedDataFilePath, entry.getValue());
|
||||||
List<Node> scenes = (List<Node>) entry.getValue().get("scenes");
|
|
||||||
for (Node scene : scenes) {
|
|
||||||
blenderContext.addLinkedFeature(linkedDataFilePath, "SC" + scene.getName(), scene);
|
|
||||||
}
|
|
||||||
List<Node> objects = (List<Node>) entry.getValue().get("objects");
|
|
||||||
for (Node object : objects) {
|
|
||||||
blenderContext.addLinkedFeature(linkedDataFilePath, "OB" + object.getName(), object);
|
|
||||||
}
|
|
||||||
List<TemporalMesh> meshes = (List<TemporalMesh>) entry.getValue().get("meshes");
|
|
||||||
for (TemporalMesh mesh : meshes) {
|
|
||||||
blenderContext.addLinkedFeature(linkedDataFilePath, "ME" + mesh.getName(), mesh);
|
|
||||||
}
|
|
||||||
List<MaterialContext> materials = (List<MaterialContext>) entry.getValue().get("materials");
|
|
||||||
for (MaterialContext materialContext : materials) {
|
|
||||||
blenderContext.addLinkedFeature(linkedDataFilePath, "MA" + materialContext.getName(), materialContext);
|
|
||||||
}
|
|
||||||
List<Texture> textures = (List<Texture>) entry.getValue().get("textures");
|
|
||||||
for (Texture texture : textures) {
|
|
||||||
blenderContext.addLinkedFeature(linkedDataFilePath, "TE" + texture.getName(), texture);
|
|
||||||
}
|
|
||||||
List<Texture> images = (List<Texture>) entry.getValue().get("images");
|
|
||||||
for (Texture image : images) {
|
|
||||||
blenderContext.addLinkedFeature(linkedDataFilePath, "IM" + image.getName(), image);
|
|
||||||
}
|
|
||||||
List<Animation> animations = (List<Animation>) entry.getValue().get("animations");
|
|
||||||
for (Animation animation : animations) {
|
|
||||||
blenderContext.addLinkedFeature(linkedDataFilePath, "AC" + animation.getName(), animation);
|
|
||||||
}
|
|
||||||
List<Camera> cameras = (List<Camera>) entry.getValue().get("cameras");
|
|
||||||
for (Camera camera : cameras) {
|
|
||||||
blenderContext.addLinkedFeature(linkedDataFilePath, "CA" + camera.getName(), camera);
|
|
||||||
}
|
|
||||||
List<Light> lights = (List<Light>) entry.getValue().get("lights");
|
|
||||||
for (Light light : lights) {
|
|
||||||
blenderContext.addLinkedFeature(linkedDataFilePath, "LA" + light.getName(), light);
|
|
||||||
}
|
|
||||||
Spatial sky = (Spatial) entry.getValue().get("sky");
|
|
||||||
if (sky != null) {
|
|
||||||
blenderContext.addLinkedFeature(linkedDataFilePath, sky.getName(), sky);
|
|
||||||
}
|
|
||||||
List<Filter> filters = (List<Filter>) entry.getValue().get("filters");
|
|
||||||
for (Filter filter : filters) {
|
|
||||||
blenderContext.addLinkedFeature(linkedDataFilePath, filter.getName(), filter);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LOGGER.log(Level.WARNING, "No features loaded from path: {0}.", path);
|
LOGGER.log(Level.WARNING, "No features loaded from path: {0}.", path);
|
||||||
|
@ -44,8 +44,11 @@ import com.jme3.animation.Bone;
|
|||||||
import com.jme3.animation.Skeleton;
|
import com.jme3.animation.Skeleton;
|
||||||
import com.jme3.asset.AssetManager;
|
import com.jme3.asset.AssetManager;
|
||||||
import com.jme3.asset.BlenderKey;
|
import com.jme3.asset.BlenderKey;
|
||||||
|
import com.jme3.light.Light;
|
||||||
import com.jme3.material.Material;
|
import com.jme3.material.Material;
|
||||||
import com.jme3.math.ColorRGBA;
|
import com.jme3.math.ColorRGBA;
|
||||||
|
import com.jme3.post.Filter;
|
||||||
|
import com.jme3.renderer.Camera;
|
||||||
import com.jme3.scene.Node;
|
import com.jme3.scene.Node;
|
||||||
import com.jme3.scene.plugins.blender.animations.BlenderAction;
|
import com.jme3.scene.plugins.blender.animations.BlenderAction;
|
||||||
import com.jme3.scene.plugins.blender.animations.BoneContext;
|
import com.jme3.scene.plugins.blender.animations.BoneContext;
|
||||||
@ -55,6 +58,8 @@ import com.jme3.scene.plugins.blender.file.DnaBlockData;
|
|||||||
import com.jme3.scene.plugins.blender.file.FileBlockHeader;
|
import com.jme3.scene.plugins.blender.file.FileBlockHeader;
|
||||||
import com.jme3.scene.plugins.blender.file.FileBlockHeader.BlockCode;
|
import com.jme3.scene.plugins.blender.file.FileBlockHeader.BlockCode;
|
||||||
import com.jme3.scene.plugins.blender.file.Structure;
|
import com.jme3.scene.plugins.blender.file.Structure;
|
||||||
|
import com.jme3.scene.plugins.blender.materials.MaterialContext;
|
||||||
|
import com.jme3.texture.Texture;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The class that stores temporary data and manages it during loading the belnd
|
* The class that stores temporary data and manages it during loading the belnd
|
||||||
@ -77,7 +82,7 @@ public class BlenderContext {
|
|||||||
/** The asset manager. */
|
/** The asset manager. */
|
||||||
private AssetManager assetManager;
|
private AssetManager assetManager;
|
||||||
/** The blocks read from the file. */
|
/** The blocks read from the file. */
|
||||||
protected List<FileBlockHeader> blocks;
|
protected List<FileBlockHeader> blocks = new ArrayList<FileBlockHeader>();
|
||||||
/**
|
/**
|
||||||
* A map containing the file block headers. The key is the old memory address.
|
* A map containing the file block headers. The key is the old memory address.
|
||||||
*/
|
*/
|
||||||
@ -233,6 +238,7 @@ public class BlenderContext {
|
|||||||
* the block header to store
|
* the block header to store
|
||||||
*/
|
*/
|
||||||
public void addFileBlockHeader(Long oldMemoryAddress, FileBlockHeader fileBlockHeader) {
|
public void addFileBlockHeader(Long oldMemoryAddress, FileBlockHeader fileBlockHeader) {
|
||||||
|
blocks.add(fileBlockHeader);
|
||||||
fileBlockHeadersByOma.put(oldMemoryAddress, fileBlockHeader);
|
fileBlockHeadersByOma.put(oldMemoryAddress, fileBlockHeader);
|
||||||
List<FileBlockHeader> headers = fileBlockHeadersByCode.get(fileBlockHeader.getCode());
|
List<FileBlockHeader> headers = fileBlockHeadersByCode.get(fileBlockHeader.getCode());
|
||||||
if (headers == null) {
|
if (headers == null) {
|
||||||
@ -242,6 +248,13 @@ public class BlenderContext {
|
|||||||
headers.add(fileBlockHeader);
|
headers.add(fileBlockHeader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the block headers
|
||||||
|
*/
|
||||||
|
public List<FileBlockHeader> getBlocks() {
|
||||||
|
return blocks;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the block header of a given memory address. If the
|
* This method returns the block header of a given memory address. If the
|
||||||
* header is not present then null is returned.
|
* header is not present then null is returned.
|
||||||
@ -332,22 +345,14 @@ public class BlenderContext {
|
|||||||
* The method adds linked content to the blender context.
|
* The method adds linked content to the blender context.
|
||||||
* @param blenderFilePath
|
* @param blenderFilePath
|
||||||
* the path of linked blender file
|
* the path of linked blender file
|
||||||
* @param featureName
|
* @param featureGroup
|
||||||
* the linked feature name
|
* the linked feature group (ie. scenes, materials, meshes, etc.)
|
||||||
* @param feature
|
* @param feature
|
||||||
* the linked feature
|
* the linked feature
|
||||||
*/
|
*/
|
||||||
public void addLinkedFeature(String blenderFilePath, String featureName, Object feature) {
|
@Deprecated
|
||||||
if (feature != null) {
|
public void addLinkedFeature(String blenderFilePath, String featureGroup, Object feature) {
|
||||||
Map<String, Object> linkedFeatures = this.linkedFeatures.get(blenderFilePath);
|
// the method is deprecated and empty at the moment
|
||||||
if (linkedFeatures == null) {
|
|
||||||
linkedFeatures = new HashMap<String, Object>();
|
|
||||||
this.linkedFeatures.put(blenderFilePath, linkedFeatures);
|
|
||||||
}
|
|
||||||
if (!linkedFeatures.containsKey(featureName)) {
|
|
||||||
linkedFeatures.put(featureName, feature);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -358,9 +363,106 @@ public class BlenderContext {
|
|||||||
* the feature name we want to get
|
* the feature name we want to get
|
||||||
* @return linked feature or null if none was found
|
* @return linked feature or null if none was found
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public Object getLinkedFeature(String blenderFilePath, String featureName) {
|
public Object getLinkedFeature(String blenderFilePath, String featureName) {
|
||||||
Map<String, Object> linkedFeatures = this.linkedFeatures.get(blenderFilePath);
|
Map<String, Object> linkedFeatures = this.linkedFeatures.get(blenderFilePath);
|
||||||
return linkedFeatures != null ? linkedFeatures.get(featureName) : null;
|
if(linkedFeatures != null) {
|
||||||
|
String namePrefix = (featureName.charAt(0) + "" + featureName.charAt(1)).toUpperCase();
|
||||||
|
featureName = featureName.substring(2);
|
||||||
|
|
||||||
|
if("SC".equals(namePrefix)) {
|
||||||
|
List<Node> scenes = (List<Node>) linkedFeatures.get("scenes");
|
||||||
|
if(scenes != null) {
|
||||||
|
for(Node scene : scenes) {
|
||||||
|
if(featureName.equals(scene.getName())) {
|
||||||
|
return scene;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if("OB".equals(namePrefix)) {
|
||||||
|
List<Node> features = (List<Node>) linkedFeatures.get("objects");
|
||||||
|
if(features != null) {
|
||||||
|
for(Node feature : features) {
|
||||||
|
if(featureName.equals(feature.getName())) {
|
||||||
|
return feature;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if("ME".equals(namePrefix)) {
|
||||||
|
List<Node> features = (List<Node>) linkedFeatures.get("meshes");
|
||||||
|
if(features != null) {
|
||||||
|
for(Node feature : features) {
|
||||||
|
if(featureName.equals(feature.getName())) {
|
||||||
|
return feature;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if("MA".equals(namePrefix)) {
|
||||||
|
List<MaterialContext> features = (List<MaterialContext>) linkedFeatures.get("materials");
|
||||||
|
if(features != null) {
|
||||||
|
for(MaterialContext feature : features) {
|
||||||
|
if(featureName.equals(feature.getName())) {
|
||||||
|
return feature;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if("TX".equals(namePrefix)) {
|
||||||
|
List<Texture> features = (List<Texture>) linkedFeatures.get("textures");
|
||||||
|
if(features != null) {
|
||||||
|
for(Texture feature : features) {
|
||||||
|
if(featureName.equals(feature.getName())) {
|
||||||
|
return feature;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if("IM".equals(namePrefix)) {
|
||||||
|
List<Texture> features = (List<Texture>) linkedFeatures.get("images");
|
||||||
|
if(features != null) {
|
||||||
|
for(Texture feature : features) {
|
||||||
|
if(featureName.equals(feature.getName())) {
|
||||||
|
return feature;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if("AC".equals(namePrefix)) {
|
||||||
|
List<Animation> features = (List<Animation>) linkedFeatures.get("animations");
|
||||||
|
if(features != null) {
|
||||||
|
for(Animation feature : features) {
|
||||||
|
if(featureName.equals(feature.getName())) {
|
||||||
|
return feature;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if("CA".equals(namePrefix)) {
|
||||||
|
List<Camera> features = (List<Camera>) linkedFeatures.get("cameras");
|
||||||
|
if(features != null) {
|
||||||
|
for(Camera feature : features) {
|
||||||
|
if(featureName.equals(feature.getName())) {
|
||||||
|
return feature;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if("LA".equals(namePrefix)) {
|
||||||
|
List<Light> features = (List<Light>) linkedFeatures.get("lights");
|
||||||
|
if(features != null) {
|
||||||
|
for(Light feature : features) {
|
||||||
|
if(featureName.equals(feature.getName())) {
|
||||||
|
return feature;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if("FI".equals(featureName)) {
|
||||||
|
List<Filter> features = (List<Filter>) linkedFeatures.get("lights");
|
||||||
|
if(features != null) {
|
||||||
|
for(Filter feature : features) {
|
||||||
|
if(featureName.equals(feature.getName())) {
|
||||||
|
return feature;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -659,4 +761,9 @@ public class BlenderContext {
|
|||||||
public static enum LoadedDataType {
|
public static enum LoadedDataType {
|
||||||
STRUCTURE, FEATURE, TEMPORAL_MESH;
|
STRUCTURE, FEATURE, TEMPORAL_MESH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return blenderKey == null ? "BlenderContext [key = null]" : "BlenderContext [ key = " + blenderKey.toString() + " ]";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,9 @@
|
|||||||
*/
|
*/
|
||||||
package com.jme3.scene.plugins.blender;
|
package com.jme3.scene.plugins.blender;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -41,9 +44,13 @@ import java.util.logging.Logger;
|
|||||||
|
|
||||||
import com.jme3.animation.Animation;
|
import com.jme3.animation.Animation;
|
||||||
import com.jme3.asset.AssetInfo;
|
import com.jme3.asset.AssetInfo;
|
||||||
|
import com.jme3.asset.AssetKey;
|
||||||
import com.jme3.asset.AssetLoader;
|
import com.jme3.asset.AssetLoader;
|
||||||
|
import com.jme3.asset.AssetLocator;
|
||||||
|
import com.jme3.asset.AssetManager;
|
||||||
import com.jme3.asset.BlenderKey;
|
import com.jme3.asset.BlenderKey;
|
||||||
import com.jme3.asset.ModelKey;
|
import com.jme3.asset.ModelKey;
|
||||||
|
import com.jme3.asset.StreamAssetInfo;
|
||||||
import com.jme3.light.Light;
|
import com.jme3.light.Light;
|
||||||
import com.jme3.math.ColorRGBA;
|
import com.jme3.math.ColorRGBA;
|
||||||
import com.jme3.post.Filter;
|
import com.jme3.post.Filter;
|
||||||
@ -81,22 +88,17 @@ import com.jme3.texture.Texture;
|
|||||||
public class BlenderLoader implements AssetLoader {
|
public class BlenderLoader implements AssetLoader {
|
||||||
private static final Logger LOGGER = Logger.getLogger(BlenderLoader.class.getName());
|
private static final Logger LOGGER = Logger.getLogger(BlenderLoader.class.getName());
|
||||||
|
|
||||||
/** The blocks read from the file. */
|
|
||||||
protected List<FileBlockHeader> blocks;
|
|
||||||
/** The blender context. */
|
|
||||||
protected BlenderContext blenderContext;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Spatial load(AssetInfo assetInfo) throws IOException {
|
public Spatial load(AssetInfo assetInfo) throws IOException {
|
||||||
try {
|
try {
|
||||||
this.setup(assetInfo);
|
BlenderContext blenderContext = this.setup(assetInfo);
|
||||||
|
|
||||||
AnimationHelper animationHelper = blenderContext.getHelper(AnimationHelper.class);
|
AnimationHelper animationHelper = blenderContext.getHelper(AnimationHelper.class);
|
||||||
animationHelper.loadAnimations();
|
animationHelper.loadAnimations();
|
||||||
|
|
||||||
BlenderKey blenderKey = blenderContext.getBlenderKey();
|
BlenderKey blenderKey = blenderContext.getBlenderKey();
|
||||||
LoadedFeatures loadedFeatures = new LoadedFeatures();
|
LoadedFeatures loadedFeatures = new LoadedFeatures();
|
||||||
for (FileBlockHeader block : blocks) {
|
for (FileBlockHeader block : blenderContext.getBlocks()) {
|
||||||
switch (block.getCode()) {
|
switch (block.getCode()) {
|
||||||
case BLOCK_OB00:
|
case BLOCK_OB00:
|
||||||
ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class);
|
ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class);
|
||||||
@ -181,7 +183,7 @@ public class BlenderLoader implements AssetLoader {
|
|||||||
|
|
||||||
LOGGER.fine("Loading scenes and attaching them to the root object.");
|
LOGGER.fine("Loading scenes and attaching them to the root object.");
|
||||||
for (FileBlockHeader sceneBlock : loadedFeatures.sceneBlocks) {
|
for (FileBlockHeader sceneBlock : loadedFeatures.sceneBlocks) {
|
||||||
loadedFeatures.scenes.add(this.toScene(sceneBlock.getStructure(blenderContext)));
|
loadedFeatures.scenes.add(this.toScene(sceneBlock.getStructure(blenderContext), blenderContext));
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGGER.fine("Creating the root node of the model and applying loaded nodes of the scene and loaded features to it.");
|
LOGGER.fine("Creating the root node of the model and applying loaded nodes of the scene and loaded features to it.");
|
||||||
@ -220,7 +222,7 @@ public class BlenderLoader implements AssetLoader {
|
|||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new IOException("Unexpected importer exception occured: " + e.getLocalizedMessage(), e);
|
throw new IOException("Unexpected importer exception occured: " + e.getLocalizedMessage(), e);
|
||||||
} finally {
|
} finally {
|
||||||
this.clear();
|
this.clear(assetInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -228,11 +230,12 @@ public class BlenderLoader implements AssetLoader {
|
|||||||
* This method converts the given structure to a scene node.
|
* This method converts the given structure to a scene node.
|
||||||
* @param structure
|
* @param structure
|
||||||
* structure of a scene
|
* structure of a scene
|
||||||
|
* @param blenderContext the blender context
|
||||||
* @return scene's node
|
* @return scene's node
|
||||||
* @throws BlenderFileException
|
* @throws BlenderFileException
|
||||||
* an exception throw when problems with blender file occur
|
* an exception throw when problems with blender file occur
|
||||||
*/
|
*/
|
||||||
private Node toScene(Structure structure) throws BlenderFileException {
|
private Node toScene(Structure structure, BlenderContext blenderContext) throws BlenderFileException {
|
||||||
ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class);
|
ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class);
|
||||||
Node result = new Node(structure.getName());
|
Node result = new Node(structure.getName());
|
||||||
List<Structure> base = ((Structure) structure.getFieldValue("base")).evaluateListBase();
|
List<Structure> base = ((Structure) structure.getFieldValue("base")).evaluateListBase();
|
||||||
@ -265,7 +268,7 @@ public class BlenderLoader implements AssetLoader {
|
|||||||
* @throws BlenderFileException
|
* @throws BlenderFileException
|
||||||
* an exception is throw when something wrong happens with blender file
|
* an exception is throw when something wrong happens with blender file
|
||||||
*/
|
*/
|
||||||
protected void setup(AssetInfo assetInfo) throws BlenderFileException {
|
protected BlenderContext setup(AssetInfo assetInfo) throws BlenderFileException {
|
||||||
// registering loaders
|
// registering loaders
|
||||||
ModelKey modelKey = (ModelKey) assetInfo.getKey();
|
ModelKey modelKey = (ModelKey) assetInfo.getKey();
|
||||||
BlenderKey blenderKey;
|
BlenderKey blenderKey;
|
||||||
@ -273,16 +276,15 @@ public class BlenderLoader implements AssetLoader {
|
|||||||
blenderKey = (BlenderKey) modelKey;
|
blenderKey = (BlenderKey) modelKey;
|
||||||
} else {
|
} else {
|
||||||
blenderKey = new BlenderKey(modelKey.getName());
|
blenderKey = new BlenderKey(modelKey.getName());
|
||||||
blenderKey.setAssetRootPath(modelKey.getFolder());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// opening stream
|
// opening stream
|
||||||
BlenderInputStream inputStream = new BlenderInputStream(assetInfo.openStream());
|
BlenderInputStream inputStream = new BlenderInputStream(assetInfo.openStream());
|
||||||
|
|
||||||
// reading blocks
|
// reading blocks
|
||||||
blocks = new ArrayList<FileBlockHeader>();
|
List<FileBlockHeader> blocks = new ArrayList<FileBlockHeader>();
|
||||||
FileBlockHeader fileBlock;
|
FileBlockHeader fileBlock;
|
||||||
blenderContext = new BlenderContext();
|
BlenderContext blenderContext = new BlenderContext();
|
||||||
blenderContext.setBlenderVersion(inputStream.getVersionNumber());
|
blenderContext.setBlenderVersion(inputStream.getVersionNumber());
|
||||||
blenderContext.setAssetManager(assetInfo.getManager());
|
blenderContext.setAssetManager(assetInfo.getManager());
|
||||||
blenderContext.setInputStream(inputStream);
|
blenderContext.setInputStream(inputStream);
|
||||||
@ -317,15 +319,19 @@ public class BlenderLoader implements AssetLoader {
|
|||||||
if (sceneFileBlock != null) {
|
if (sceneFileBlock != null) {
|
||||||
blenderContext.setSceneStructure(sceneFileBlock.getStructure(blenderContext));
|
blenderContext.setSceneStructure(sceneFileBlock.getStructure(blenderContext));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// adding locator for linked content
|
||||||
|
assetInfo.getManager().registerLocator(assetInfo.getKey().getName(), LinkedContentLocator.class);
|
||||||
|
|
||||||
|
return blenderContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The internal data is only needed during loading so make it unreachable so that the GC can release
|
* The internal data is only needed during loading so make it unreachable so that the GC can release
|
||||||
* that memory (which can be quite large amount).
|
* that memory (which can be quite large amount).
|
||||||
*/
|
*/
|
||||||
protected void clear() {
|
protected void clear(AssetInfo assetInfo) {
|
||||||
blenderContext = null;
|
assetInfo.getManager().unregisterLocator(assetInfo.getKey().getName(), LinkedContentLocator.class);
|
||||||
blocks = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -362,4 +368,50 @@ public class BlenderLoader implements AssetLoader {
|
|||||||
*/
|
*/
|
||||||
private ColorRGBA backgroundColor = ColorRGBA.Gray;
|
private ColorRGBA backgroundColor = ColorRGBA.Gray;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class LinkedContentLocator implements AssetLocator {
|
||||||
|
private File rootFolder;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRootPath(String rootPath) {
|
||||||
|
rootFolder = new File(rootPath);
|
||||||
|
if(rootFolder.isFile()) {
|
||||||
|
rootFolder = rootFolder.getParentFile();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("rawtypes")
|
||||||
|
@Override
|
||||||
|
public AssetInfo locate(AssetManager manager, AssetKey key) {
|
||||||
|
if(key instanceof BlenderKey) {
|
||||||
|
File linkedAbsoluteFile = new File(key.getName());
|
||||||
|
if(linkedAbsoluteFile.exists() && linkedAbsoluteFile.isFile()) {
|
||||||
|
try {
|
||||||
|
return new StreamAssetInfo(manager, key, new FileInputStream(linkedAbsoluteFile));
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
File linkedFileInCurrentAssetFolder = new File(rootFolder, linkedAbsoluteFile.getName());
|
||||||
|
if(linkedFileInCurrentAssetFolder.exists() && linkedFileInCurrentAssetFolder.isFile()) {
|
||||||
|
try {
|
||||||
|
return new StreamAssetInfo(manager, key, new FileInputStream(linkedFileInCurrentAssetFolder));
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
File linkedFileInCurrentFolder = new File(".", linkedAbsoluteFile.getName());
|
||||||
|
if(linkedFileInCurrentFolder.exists() && linkedFileInCurrentFolder.isFile()) {
|
||||||
|
try {
|
||||||
|
return new StreamAssetInfo(manager, key, new FileInputStream(linkedFileInCurrentFolder));
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -145,7 +145,7 @@ public class Ipo {
|
|||||||
|
|
||||||
float[] times = new float[framesAmount + 1];
|
float[] times = new float[framesAmount + 1];
|
||||||
Vector3f[] translations = new Vector3f[framesAmount + 1];
|
Vector3f[] translations = new Vector3f[framesAmount + 1];
|
||||||
float[] translation = new float[] { localTranslation.x, localTranslation.y, localTranslation.z };
|
float[] translation = new float[3];
|
||||||
Quaternion[] rotations = new Quaternion[framesAmount + 1];
|
Quaternion[] rotations = new Quaternion[framesAmount + 1];
|
||||||
float[] quaternionRotation = new float[] { localRotation.getX(), localRotation.getY(), localRotation.getZ(), localRotation.getW(), };
|
float[] quaternionRotation = new float[] { localRotation.getX(), localRotation.getY(), localRotation.getZ(), localRotation.getW(), };
|
||||||
float[] eulerRotation = localRotation.toAngles(null);
|
float[] eulerRotation = localRotation.toAngles(null);
|
||||||
@ -165,6 +165,8 @@ public class Ipo {
|
|||||||
|
|
||||||
// calculating track data
|
// calculating track data
|
||||||
for (int frame = startFrame; frame <= stopFrame; ++frame) {
|
for (int frame = startFrame; frame <= stopFrame; ++frame) {
|
||||||
|
boolean translationSet = false;
|
||||||
|
translation[0] = translation[1] = translation[2] = 0;
|
||||||
int index = frame - startFrame;
|
int index = frame - startFrame;
|
||||||
times[index] = index * timeBetweenFrames;// start + (frame - 1) * timeBetweenFrames;
|
times[index] = index * timeBetweenFrames;// start + (frame - 1) * timeBetweenFrames;
|
||||||
for (int j = 0; j < bezierCurves.length; ++j) {
|
for (int j = 0; j < bezierCurves.length; ++j) {
|
||||||
@ -173,15 +175,18 @@ public class Ipo {
|
|||||||
// LOCATION
|
// LOCATION
|
||||||
case AC_LOC_X:
|
case AC_LOC_X:
|
||||||
translation[0] = (float) value;
|
translation[0] = (float) value;
|
||||||
|
translationSet = true;
|
||||||
break;
|
break;
|
||||||
case AC_LOC_Y:
|
case AC_LOC_Y:
|
||||||
if (swapAxes && value != 0) {
|
if (swapAxes && value != 0) {
|
||||||
value = -value;
|
value = -value;
|
||||||
}
|
}
|
||||||
translation[yIndex] = (float) value;
|
translation[yIndex] = (float) value;
|
||||||
|
translationSet = true;
|
||||||
break;
|
break;
|
||||||
case AC_LOC_Z:
|
case AC_LOC_Z:
|
||||||
translation[zIndex] = (float) value;
|
translation[zIndex] = (float) value;
|
||||||
|
translationSet = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// EULER ROTATION
|
// EULER ROTATION
|
||||||
@ -235,7 +240,11 @@ public class Ipo {
|
|||||||
LOGGER.log(Level.WARNING, "Unknown ipo curve type: {0}.", bezierCurves[j].getType());
|
LOGGER.log(Level.WARNING, "Unknown ipo curve type: {0}.", bezierCurves[j].getType());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(translationSet) {
|
||||||
translations[index] = localRotation.multLocal(new Vector3f(translation[0], translation[1], translation[2]));
|
translations[index] = localRotation.multLocal(new Vector3f(translation[0], translation[1], translation[2]));
|
||||||
|
} else {
|
||||||
|
translations[index] = new Vector3f();
|
||||||
|
}
|
||||||
|
|
||||||
if(boneContext != null) {
|
if(boneContext != null) {
|
||||||
if(boneContext.getBone().getParent() == null && boneContext.is(BoneContext.NO_LOCAL_LOCATION)) {
|
if(boneContext.getBone().getParent() == null && boneContext.is(BoneContext.NO_LOCAL_LOCATION)) {
|
||||||
|
@ -174,7 +174,7 @@ public class ConstraintDefinitionIK extends ConstraintDefinition {
|
|||||||
private static class BonesChain extends ArrayList<BoneContext> {
|
private static class BonesChain extends ArrayList<BoneContext> {
|
||||||
private static final long serialVersionUID = -1850524345643600718L;
|
private static final long serialVersionUID = -1850524345643600718L;
|
||||||
|
|
||||||
private List<Matrix> bonesMatrices = new ArrayList<Matrix>();
|
private List<Matrix> localBonesMatrices = new ArrayList<Matrix>();
|
||||||
|
|
||||||
public BonesChain(Bone bone, boolean useTail, int bonesAffected, Collection<Long> alteredOmas, BlenderContext blenderContext) {
|
public BonesChain(Bone bone, boolean useTail, int bonesAffected, Collection<Long> alteredOmas, BlenderContext blenderContext) {
|
||||||
if (bone != null) {
|
if (bone != null) {
|
||||||
@ -187,12 +187,21 @@ public class ConstraintDefinitionIK extends ConstraintDefinition {
|
|||||||
this.add(boneContext);
|
this.add(boneContext);
|
||||||
alteredOmas.add(boneContext.getBoneOma());
|
alteredOmas.add(boneContext.getBoneOma());
|
||||||
|
|
||||||
Space space = this.size() < bonesAffected ? Space.CONSTRAINT_SPACE_LOCAL : Space.CONSTRAINT_SPACE_WORLD;
|
Transform transform = constraintHelper.getTransform(boneContext.getArmatureObjectOMA(), boneContext.getBone().getName(), Space.CONSTRAINT_SPACE_WORLD);
|
||||||
Transform transform = constraintHelper.getTransform(boneContext.getArmatureObjectOMA(), boneContext.getBone().getName(), space);
|
localBonesMatrices.add(new DTransform(transform).toMatrix());
|
||||||
bonesMatrices.add(new DTransform(transform).toMatrix());
|
|
||||||
|
|
||||||
bone = bone.getParent();
|
bone = bone.getParent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(localBonesMatrices.size() > 0) {
|
||||||
|
// making the matrices describe the local transformation
|
||||||
|
Matrix parentWorldMatrix = localBonesMatrices.get(localBonesMatrices.size() - 1);
|
||||||
|
for(int i=localBonesMatrices.size() - 2;i>=0;--i) {
|
||||||
|
SimpleMatrix m = parentWorldMatrix.invert().mult(localBonesMatrices.get(i));
|
||||||
|
parentWorldMatrix = localBonesMatrices.get(i);
|
||||||
|
localBonesMatrices.set(i, new Matrix(m));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,16 +220,16 @@ public class ConstraintDefinitionIK extends ConstraintDefinition {
|
|||||||
SimpleMatrix m = parentWorldMatrix.invert().mult(boneMatrix);
|
SimpleMatrix m = parentWorldMatrix.invert().mult(boneMatrix);
|
||||||
boneMatrix = new Matrix(m);
|
boneMatrix = new Matrix(m);
|
||||||
}
|
}
|
||||||
bonesMatrices.set(index, boneMatrix);
|
localBonesMatrices.set(index, boneMatrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Matrix getWorldMatrix(int index) {
|
public Matrix getWorldMatrix(int index) {
|
||||||
if (index == this.size() - 1) {
|
if (index == this.size() - 1) {
|
||||||
return new Matrix(bonesMatrices.get(this.size() - 1));
|
return new Matrix(localBonesMatrices.get(this.size() - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
SimpleMatrix result = this.getWorldMatrix(index + 1);
|
SimpleMatrix result = this.getWorldMatrix(index + 1);
|
||||||
result = result.mult(bonesMatrices.get(index));
|
result = result.mult(localBonesMatrices.get(index));
|
||||||
return new Matrix(result);
|
return new Matrix(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -180,8 +180,8 @@ public class CurvesTemporalMesh extends TemporalMesh {
|
|||||||
if (bevelObject != null && beziers.size() > 0) {
|
if (bevelObject != null && beziers.size() > 0) {
|
||||||
this.append(this.applyBevelAndTaper(this, bevelObject, taperObject, blenderContext));
|
this.append(this.applyBevelAndTaper(this, bevelObject, taperObject, blenderContext));
|
||||||
} else {
|
} else {
|
||||||
int originalVerticesAmount = vertices.size();
|
|
||||||
for (BezierLine bezierLine : beziers) {
|
for (BezierLine bezierLine : beziers) {
|
||||||
|
int originalVerticesAmount = vertices.size();
|
||||||
vertices.add(bezierLine.vertices[0]);
|
vertices.add(bezierLine.vertices[0]);
|
||||||
Vector3f v = bezierLine.vertices[1].subtract(bezierLine.vertices[0]).normalizeLocal();
|
Vector3f v = bezierLine.vertices[1].subtract(bezierLine.vertices[0]).normalizeLocal();
|
||||||
float temp = v.x;
|
float temp = v.x;
|
||||||
|
@ -81,6 +81,7 @@ public class LandscapeHelper extends AbstractBlenderHelper {
|
|||||||
if ((mode & MODE_MIST) != 0) {
|
if ((mode & MODE_MIST) != 0) {
|
||||||
LOGGER.fine("Loading fog.");
|
LOGGER.fine("Loading fog.");
|
||||||
result = new FogFilter();
|
result = new FogFilter();
|
||||||
|
result.setName("FIfog");
|
||||||
result.setFogColor(this.toBackgroundColor(worldStructure));
|
result.setFogColor(this.toBackgroundColor(worldStructure));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -168,9 +168,11 @@ public final class MaterialContext implements Savable {
|
|||||||
|
|
||||||
this.setTexture(material, combinedTexture.getMappingType(), combinedTexture.getResultTexture());
|
this.setTexture(material, combinedTexture.getMappingType(), combinedTexture.getResultTexture());
|
||||||
List<Vector2f> uvs = combinedTexture.getResultUVS();
|
List<Vector2f> uvs = combinedTexture.getResultUVS();
|
||||||
|
if(uvs != null && uvs.size() > 0) {
|
||||||
VertexBuffer uvCoordsBuffer = new VertexBuffer(TextureHelper.TEXCOORD_TYPES[textureIndex++]);
|
VertexBuffer uvCoordsBuffer = new VertexBuffer(TextureHelper.TEXCOORD_TYPES[textureIndex++]);
|
||||||
uvCoordsBuffer.setupData(Usage.Static, 2, Format.Float, BufferUtils.createFloatBuffer(uvs.toArray(new Vector2f[uvs.size()])));
|
uvCoordsBuffer.setupData(Usage.Static, 2, Format.Float, BufferUtils.createFloatBuffer(uvs.toArray(new Vector2f[uvs.size()])));
|
||||||
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)
|
||||||
} 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);
|
||||||
}
|
}
|
||||||
|
@ -46,6 +46,8 @@ import com.jme3.scene.plugins.blender.objects.Properties;
|
|||||||
*/
|
*/
|
||||||
public class TemporalMesh extends Geometry {
|
public class TemporalMesh extends Geometry {
|
||||||
private static final Logger LOGGER = Logger.getLogger(TemporalMesh.class.getName());
|
private static final Logger LOGGER = Logger.getLogger(TemporalMesh.class.getName());
|
||||||
|
/** A minimum weight value. */
|
||||||
|
private static final double MINIMUM_BONE_WEIGHT = FastMath.DBL_EPSILON;
|
||||||
|
|
||||||
/** The blender context. */
|
/** The blender context. */
|
||||||
protected final BlenderContext blenderContext;
|
protected final BlenderContext blenderContext;
|
||||||
@ -530,7 +532,11 @@ public class TemporalMesh extends Geometry {
|
|||||||
for (Entry<String, Integer> entry : boneIndexes.entrySet()) {
|
for (Entry<String, Integer> entry : boneIndexes.entrySet()) {
|
||||||
if (vertexGroupsForVertex.containsKey(entry.getKey())) {
|
if (vertexGroupsForVertex.containsKey(entry.getKey())) {
|
||||||
float weight = vertexGroupsForVertex.get(entry.getKey());
|
float weight = vertexGroupsForVertex.get(entry.getKey());
|
||||||
if (weight > 0) {// no need to use such weights
|
if (weight > MINIMUM_BONE_WEIGHT) {
|
||||||
|
// only values of weight greater than MINIMUM_BONE_WEIGHT are used
|
||||||
|
// if all non zero weights were used, and they were samm enough, problems with normalisation would occur
|
||||||
|
// because adding a very small value to 1.0 will give 1.0
|
||||||
|
// so in order to avoid such errors, which can cause severe animation artifacts we need to use some minimum weight value
|
||||||
boneBuffersForVertex.put(weight, entry.getValue());
|
boneBuffersForVertex.put(weight, entry.getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package com.jme3.scene.plugins.blender.modifiers;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
@ -129,6 +130,8 @@ public class SubdivisionSurfaceModifier extends Modifier {
|
|||||||
for (int i = 0; i < temporalMesh.getVertexCount(); ++i) {
|
for (int i = 0; i < temporalMesh.getVertexCount(); ++i) {
|
||||||
// finding adjacent edges that were created by dividing original edges
|
// finding adjacent edges that were created by dividing original edges
|
||||||
List<Edge> adjacentOriginalEdges = new ArrayList<Edge>();
|
List<Edge> adjacentOriginalEdges = new ArrayList<Edge>();
|
||||||
|
Collection<Edge> adjacentEdges = temporalMesh.getAdjacentEdges(i);
|
||||||
|
if(adjacentEdges != null) {// this can be null if a vertex with index 'i' is not connected to any face nor edge
|
||||||
for (Edge edge : temporalMesh.getAdjacentEdges(i)) {
|
for (Edge edge : temporalMesh.getAdjacentEdges(i)) {
|
||||||
if (verticesOnOriginalEdges.contains(edge.getFirstIndex()) || verticesOnOriginalEdges.contains(edge.getSecondIndex())) {
|
if (verticesOnOriginalEdges.contains(edge.getFirstIndex()) || verticesOnOriginalEdges.contains(edge.getSecondIndex())) {
|
||||||
adjacentOriginalEdges.add(edge);
|
adjacentOriginalEdges.add(edge);
|
||||||
@ -136,6 +139,9 @@ public class SubdivisionSurfaceModifier extends Modifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
creasePoints.add(new CreasePoint(i, boundaryVertices.contains(i), adjacentOriginalEdges, temporalMesh));
|
creasePoints.add(new CreasePoint(i, boundaryVertices.contains(i), adjacentOriginalEdges, temporalMesh));
|
||||||
|
} else {
|
||||||
|
creasePoints.add(null);//the count of crease points must be equal to vertex count; otherwise we'll get IndexOutofBoundsException later
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3f[] averageVert = new Vector3f[temporalMesh.getVertexCount()];
|
Vector3f[] averageVert = new Vector3f[temporalMesh.getVertexCount()];
|
||||||
@ -174,6 +180,7 @@ public class SubdivisionSurfaceModifier extends Modifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < averageVert.length; ++i) {
|
for (int i = 0; i < averageVert.length; ++i) {
|
||||||
|
if(averageVert[i] != null && averageCount[i] > 0) {
|
||||||
Vector3f v = temporalMesh.getVertices().get(i);
|
Vector3f v = temporalMesh.getVertices().get(i);
|
||||||
averageVert[i].divideLocal(averageCount[i]);
|
averageVert[i].divideLocal(averageCount[i]);
|
||||||
|
|
||||||
@ -194,6 +201,7 @@ public class SubdivisionSurfaceModifier extends Modifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The method performs a simple subdivision of the mesh.
|
* The method performs a simple subdivision of the mesh.
|
||||||
|
@ -158,6 +158,9 @@ public class CombinedTexture {
|
|||||||
} else {
|
} else {
|
||||||
resultUVS = userDefinedUVCoordinates.get(textureData.uvCoordinatesName);
|
resultUVS = userDefinedUVCoordinates.get(textureData.uvCoordinatesName);
|
||||||
}
|
}
|
||||||
|
if(resultUVS == null && LOGGER.isLoggable(Level.WARNING)) {
|
||||||
|
LOGGER.warning("The texture " + textureData.texture.getName() + " has assigned non existing UV coordinates group: " + textureData.uvCoordinatesName + ".");
|
||||||
|
}
|
||||||
masterUserUVSetName = textureData.uvCoordinatesName;
|
masterUserUVSetName = textureData.uvCoordinatesName;
|
||||||
} else {
|
} else {
|
||||||
TemporalMesh temporalMesh = (TemporalMesh) blenderContext.getLoadedFeature(geometriesOMA, LoadedDataType.TEMPORAL_MESH);
|
TemporalMesh temporalMesh = (TemporalMesh) blenderContext.getLoadedFeature(geometriesOMA, LoadedDataType.TEMPORAL_MESH);
|
||||||
|
@ -51,6 +51,7 @@ extern "C" {
|
|||||||
jmeClasses::initJavaClasses(env);
|
jmeClasses::initJavaClasses(env);
|
||||||
btTriangleIndexVertexArray* array = reinterpret_cast<btTriangleIndexVertexArray*>(meshId);
|
btTriangleIndexVertexArray* array = reinterpret_cast<btTriangleIndexVertexArray*>(meshId);
|
||||||
btGImpactMeshShape* shape = new btGImpactMeshShape(array);
|
btGImpactMeshShape* shape = new btGImpactMeshShape(array);
|
||||||
|
shape->updateBound();
|
||||||
return reinterpret_cast<jlong>(shape);
|
return reinterpret_cast<jlong>(shape);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -811,37 +811,70 @@ extern "C" {
|
|||||||
/*
|
/*
|
||||||
* Class: com_jme3_bullet_objects_PhysicsRigidBody
|
* Class: com_jme3_bullet_objects_PhysicsRigidBody
|
||||||
* Method: getAngularFactor
|
* Method: getAngularFactor
|
||||||
* Signature: (J)F
|
* Signature: (JLcom/jme3/math/Vector3f;)V
|
||||||
*/
|
*/
|
||||||
JNIEXPORT jfloat JNICALL Java_com_jme3_bullet_objects_PhysicsRigidBody_getAngularFactor
|
JNIEXPORT void JNICALL Java_com_jme3_bullet_objects_PhysicsRigidBody_getAngularFactor
|
||||||
(JNIEnv *env, jobject object, jlong bodyId) {
|
(JNIEnv *env, jobject object, jlong bodyId, jobject factor) {
|
||||||
btRigidBody* body = reinterpret_cast<btRigidBody*>(bodyId);
|
|
||||||
if (body == NULL) {
|
|
||||||
jclass newExc = env->FindClass("java/lang/NullPointerException");
|
|
||||||
env->ThrowNew(newExc, "The native object does not exist.");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return body->getAngularFactor().getX();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Class: com_jme3_bullet_objects_PhysicsRigidBody
|
|
||||||
* Method: setAngularFactor
|
|
||||||
* Signature: (JF)V
|
|
||||||
*/
|
|
||||||
JNIEXPORT void JNICALL Java_com_jme3_bullet_objects_PhysicsRigidBody_setAngularFactor
|
|
||||||
(JNIEnv *env, jobject object, jlong bodyId, jfloat value) {
|
|
||||||
btRigidBody* body = reinterpret_cast<btRigidBody*>(bodyId);
|
btRigidBody* body = reinterpret_cast<btRigidBody*>(bodyId);
|
||||||
if (body == NULL) {
|
if (body == NULL) {
|
||||||
jclass newExc = env->FindClass("java/lang/NullPointerException");
|
jclass newExc = env->FindClass("java/lang/NullPointerException");
|
||||||
env->ThrowNew(newExc, "The native object does not exist.");
|
env->ThrowNew(newExc, "The native object does not exist.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
btVector3 vec1 = btVector3();
|
jmeBulletUtil::convert(env, &body->getAngularFactor(), factor);
|
||||||
vec1.setX(value);
|
}
|
||||||
vec1.setY(value);
|
|
||||||
vec1.setZ(value);
|
|
||||||
body->setAngularFactor(vec1);
|
/*
|
||||||
|
* Class: com_jme3_bullet_objects_PhysicsRigidBody
|
||||||
|
* Method: setAngularFactor
|
||||||
|
* Signature: (JLcom/jme3/math/Vector3f;)V
|
||||||
|
*/
|
||||||
|
JNIEXPORT void JNICALL Java_com_jme3_bullet_objects_PhysicsRigidBody_setAngularFactor
|
||||||
|
(JNIEnv *env, jobject object, jlong bodyId, jobject factor) {
|
||||||
|
btRigidBody* body = reinterpret_cast<btRigidBody*>(bodyId);
|
||||||
|
if (body == NULL) {
|
||||||
|
jclass newExc = env->FindClass("java/lang/NullPointerException");
|
||||||
|
env->ThrowNew(newExc, "The native object does not exist.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
btVector3 vec = btVector3();
|
||||||
|
jmeBulletUtil::convert(env, factor, &vec);
|
||||||
|
body->setAngularFactor(vec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: com_jme3_bullet_objects_PhysicsRigidBody
|
||||||
|
* Method: getLinearFactor
|
||||||
|
* Signature: (JLcom/jme3/math/Vector3f;)V
|
||||||
|
*/
|
||||||
|
JNIEXPORT void JNICALL Java_com_jme3_bullet_objects_PhysicsRigidBody_getLinearFactor
|
||||||
|
(JNIEnv *env, jobject object, jlong bodyId, jobject factor) {
|
||||||
|
btRigidBody* body = reinterpret_cast<btRigidBody*>(bodyId);
|
||||||
|
if (body == NULL) {
|
||||||
|
jclass newExc = env->FindClass("java/lang/NullPointerException");
|
||||||
|
env->ThrowNew(newExc, "The native object does not exist.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
jmeBulletUtil::convert(env, &body->getLinearFactor(), factor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: com_jme3_bullet_objects_PhysicsRigidBody
|
||||||
|
* Method: setLinearFactor
|
||||||
|
* Signature: (JLcom/jme3/math/Vector3f;)V
|
||||||
|
*/
|
||||||
|
JNIEXPORT void JNICALL Java_com_jme3_bullet_objects_PhysicsRigidBody_setLinearFactor
|
||||||
|
(JNIEnv *env, jobject object, jlong bodyId, jobject factor) {
|
||||||
|
btRigidBody* body = reinterpret_cast<btRigidBody*>(bodyId);
|
||||||
|
if (body == NULL) {
|
||||||
|
jclass newExc = env->FindClass("java/lang/NullPointerException");
|
||||||
|
env->ThrowNew(newExc, "The native object does not exist.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
btVector3 vec = btVector3();
|
||||||
|
jmeBulletUtil::convert(env, factor, &vec);
|
||||||
|
body->setLinearFactor(vec);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -396,18 +396,35 @@ JNIEXPORT jfloat JNICALL Java_com_jme3_bullet_objects_PhysicsRigidBody_getAngula
|
|||||||
/*
|
/*
|
||||||
* Class: com_jme3_bullet_objects_PhysicsRigidBody
|
* Class: com_jme3_bullet_objects_PhysicsRigidBody
|
||||||
* Method: getAngularFactor
|
* Method: getAngularFactor
|
||||||
* Signature: (J)F
|
* Signature: (JLcom/jme3/math/Vector3f;)V
|
||||||
*/
|
*/
|
||||||
JNIEXPORT jfloat JNICALL Java_com_jme3_bullet_objects_PhysicsRigidBody_getAngularFactor
|
JNIEXPORT void JNICALL Java_com_jme3_bullet_objects_PhysicsRigidBody_getAngularFactor
|
||||||
(JNIEnv *, jobject, jlong);
|
(JNIEnv *, jobject, jlong, jobject);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Class: com_jme3_bullet_objects_PhysicsRigidBody
|
* Class: com_jme3_bullet_objects_PhysicsRigidBody
|
||||||
* Method: setAngularFactor
|
* Method: setAngularFactor
|
||||||
* Signature: (JF)V
|
* Signature: (JLcom/jme3/math/Vector3f;)V
|
||||||
*/
|
*/
|
||||||
JNIEXPORT void JNICALL Java_com_jme3_bullet_objects_PhysicsRigidBody_setAngularFactor
|
JNIEXPORT void JNICALL Java_com_jme3_bullet_objects_PhysicsRigidBody_setAngularFactor
|
||||||
(JNIEnv *, jobject, jlong, jfloat);
|
(JNIEnv *, jobject, jlong, jobject);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: com_jme3_bullet_objects_PhysicsRigidBody
|
||||||
|
* Method: getLinearFactor
|
||||||
|
* Signature: (JLcom/jme3/math/Vector3f;)V
|
||||||
|
*/
|
||||||
|
JNIEXPORT void JNICALL Java_com_jme3_bullet_objects_PhysicsRigidBody_getLinearFactor
|
||||||
|
(JNIEnv *, jobject, jlong, jobject);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: com_jme3_bullet_objects_PhysicsRigidBody
|
||||||
|
* Method: setLinearFactor
|
||||||
|
* Signature: (JLcom/jme3/math/Vector3f;)V
|
||||||
|
*/
|
||||||
|
JNIEXPORT void JNICALL Java_com_jme3_bullet_objects_PhysicsRigidBody_setLinearFactor
|
||||||
|
(JNIEnv *, jobject, jlong, jobject);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -351,7 +351,7 @@ void jmeBulletUtil::addResult(JNIEnv* env, jobject resultlist, btVector3* hitnor
|
|||||||
env->SetFloatField(singleresult, jmeClasses::PhysicsRay_hitfraction, m_hitFraction);
|
env->SetFloatField(singleresult, jmeClasses::PhysicsRay_hitfraction, m_hitFraction);
|
||||||
|
|
||||||
env->SetObjectField(singleresult, jmeClasses::PhysicsRay_collisionObject, up1->javaCollisionObject);
|
env->SetObjectField(singleresult, jmeClasses::PhysicsRay_collisionObject, up1->javaCollisionObject);
|
||||||
env->CallVoidMethod(resultlist, jmeClasses::PhysicsRay_addmethod, singleresult);
|
env->CallBooleanMethod(resultlist, jmeClasses::PhysicsRay_addmethod, singleresult);
|
||||||
if (env->ExceptionCheck()) {
|
if (env->ExceptionCheck()) {
|
||||||
env->Throw(env->ExceptionOccurred());
|
env->Throw(env->ExceptionOccurred());
|
||||||
return;
|
return;
|
||||||
@ -371,7 +371,7 @@ void jmeBulletUtil::addSweepResult(JNIEnv* env, jobject resultlist, btVector3* h
|
|||||||
env->SetFloatField(singleresult, jmeClasses::PhysicsSweep_hitfraction, m_hitFraction);
|
env->SetFloatField(singleresult, jmeClasses::PhysicsSweep_hitfraction, m_hitFraction);
|
||||||
|
|
||||||
env->SetObjectField(singleresult, jmeClasses::PhysicsSweep_collisionObject, up1->javaCollisionObject);
|
env->SetObjectField(singleresult, jmeClasses::PhysicsSweep_collisionObject, up1->javaCollisionObject);
|
||||||
env->CallVoidMethod(resultlist, jmeClasses::PhysicsSweep_addmethod, singleresult);
|
env->CallBooleanMethod(resultlist, jmeClasses::PhysicsSweep_addmethod, singleresult);
|
||||||
if (env->ExceptionCheck()) {
|
if (env->ExceptionCheck()) {
|
||||||
env->Throw(env->ExceptionOccurred());
|
env->Throw(env->ExceptionOccurred());
|
||||||
return;
|
return;
|
||||||
|
@ -93,8 +93,10 @@ public class CapsuleCollisionShape extends CollisionShape{
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void setScale(Vector3f scale) {
|
public void setScale(Vector3f scale) {
|
||||||
|
if (!scale.equals(Vector3f.UNIT_XYZ)) {
|
||||||
Logger.getLogger(this.getClass().getName()).log(Level.WARNING, "CapsuleCollisionShape cannot be scaled");
|
Logger.getLogger(this.getClass().getName()).log(Level.WARNING, "CapsuleCollisionShape cannot be scaled");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void write(JmeExporter ex) throws IOException {
|
public void write(JmeExporter ex) throws IOException {
|
||||||
super.write(ex);
|
super.write(ex);
|
||||||
|
@ -627,16 +627,44 @@ public class PhysicsRigidBody extends PhysicsCollisionObject {
|
|||||||
private native float getAngularSleepingThreshold(long objectId);
|
private native float getAngularSleepingThreshold(long objectId);
|
||||||
|
|
||||||
public float getAngularFactor() {
|
public float getAngularFactor() {
|
||||||
return getAngularFactor(objectId);
|
return getAngularFactor(null).getX();
|
||||||
}
|
}
|
||||||
|
|
||||||
private native float getAngularFactor(long objectId);
|
public Vector3f getAngularFactor(Vector3f store) {
|
||||||
|
// doing like this prevent from breaking the API
|
||||||
|
if (store == null) {
|
||||||
|
store = new Vector3f();
|
||||||
|
}
|
||||||
|
getAngularFactor(objectId, store);
|
||||||
|
return store;
|
||||||
|
}
|
||||||
|
|
||||||
|
private native void getAngularFactor(long objectId, Vector3f vec);
|
||||||
|
|
||||||
public void setAngularFactor(float factor) {
|
public void setAngularFactor(float factor) {
|
||||||
|
setAngularFactor(objectId, new Vector3f(factor, factor, factor));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAngularFactor(Vector3f factor) {
|
||||||
setAngularFactor(objectId, factor);
|
setAngularFactor(objectId, factor);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void setAngularFactor(long objectId, float factor);
|
private native void setAngularFactor(long objectId, Vector3f factor);
|
||||||
|
|
||||||
|
public Vector3f getLinearFactor() {
|
||||||
|
Vector3f vec = new Vector3f();
|
||||||
|
getLinearFactor(objectId, vec);
|
||||||
|
return vec;
|
||||||
|
}
|
||||||
|
|
||||||
|
private native void getLinearFactor(long objectId, Vector3f vec);
|
||||||
|
|
||||||
|
public void setLinearFactor(Vector3f factor) {
|
||||||
|
setLinearFactor(objectId, factor);
|
||||||
|
}
|
||||||
|
|
||||||
|
private native void setLinearFactor(long objectId, Vector3f factor);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* do not use manually, joints are added automatically
|
* do not use manually, joints are added automatically
|
||||||
@ -673,7 +701,13 @@ public class PhysicsRigidBody extends PhysicsCollisionObject {
|
|||||||
capsule.write(getGravity(), "gravity", Vector3f.ZERO);
|
capsule.write(getGravity(), "gravity", Vector3f.ZERO);
|
||||||
capsule.write(getFriction(), "friction", 0.5f);
|
capsule.write(getFriction(), "friction", 0.5f);
|
||||||
capsule.write(getRestitution(), "restitution", 0);
|
capsule.write(getRestitution(), "restitution", 0);
|
||||||
|
Vector3f angularFactor = getAngularFactor(null);
|
||||||
|
if (angularFactor.x == angularFactor.y && angularFactor.y == angularFactor.z) {
|
||||||
capsule.write(getAngularFactor(), "angularFactor", 1);
|
capsule.write(getAngularFactor(), "angularFactor", 1);
|
||||||
|
} else {
|
||||||
|
capsule.write(getAngularFactor(null), "angularFactor", Vector3f.UNIT_XYZ);
|
||||||
|
capsule.write(getLinearFactor(), "linearFactor", Vector3f.UNIT_XYZ);
|
||||||
|
}
|
||||||
capsule.write(kinematic, "kinematic", false);
|
capsule.write(kinematic, "kinematic", false);
|
||||||
|
|
||||||
capsule.write(getLinearDamping(), "linearDamping", 0);
|
capsule.write(getLinearDamping(), "linearDamping", 0);
|
||||||
@ -703,7 +737,13 @@ public class PhysicsRigidBody extends PhysicsCollisionObject {
|
|||||||
setKinematic(capsule.readBoolean("kinematic", false));
|
setKinematic(capsule.readBoolean("kinematic", false));
|
||||||
|
|
||||||
setRestitution(capsule.readFloat("restitution", 0));
|
setRestitution(capsule.readFloat("restitution", 0));
|
||||||
|
Vector3f angularFactor = (Vector3f) capsule.readSavable("angularFactor", null);
|
||||||
|
if(angularFactor == null) {
|
||||||
setAngularFactor(capsule.readFloat("angularFactor", 1));
|
setAngularFactor(capsule.readFloat("angularFactor", 1));
|
||||||
|
} else {
|
||||||
|
setAngularFactor(angularFactor);
|
||||||
|
setLinearFactor((Vector3f) capsule.readSavable("linearFactor", Vector3f.UNIT_XYZ.clone()));
|
||||||
|
}
|
||||||
setDamping(capsule.readFloat("linearDamping", 0), capsule.readFloat("angularDamping", 0));
|
setDamping(capsule.readFloat("linearDamping", 0), capsule.readFloat("angularDamping", 0));
|
||||||
setSleepingThresholds(capsule.readFloat("linearSleepingThreshold", 0.8f), capsule.readFloat("angularSleepingThreshold", 1.0f));
|
setSleepingThresholds(capsule.readFloat("linearSleepingThreshold", 0.8f), capsule.readFloat("angularSleepingThreshold", 1.0f));
|
||||||
setCcdMotionThreshold(capsule.readFloat("ccdMotionThreshold", 0));
|
setCcdMotionThreshold(capsule.readFloat("ccdMotionThreshold", 0));
|
||||||
|
@ -10,57 +10,30 @@ sourceSets {
|
|||||||
srcDir 'src/tools/java'
|
srcDir 'src/tools/java'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
test {
|
||||||
|
java {
|
||||||
|
srcDir 'src/test/java'
|
||||||
}
|
}
|
||||||
|
|
||||||
buildscript {
|
|
||||||
repositories {
|
|
||||||
mavenCentral()
|
|
||||||
}
|
|
||||||
dependencies {
|
|
||||||
classpath 'org.ajoberstar:gradle-git:1.0.0-rc.1'
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
import java.text.SimpleDateFormat
|
task updateVersionPropertiesFile << {
|
||||||
import org.ajoberstar.grgit.*
|
def verfile = file('src/main/resources/com/jme3/system/version.properties')
|
||||||
|
verfile.text = "# THIS IS AN AUTO-GENERATED FILE..\n" +
|
||||||
task updateVersion << {
|
"# DO NOT MODIFY!\n" +
|
||||||
|
"build.date=${jmeBuildDate}\n" +
|
||||||
def verfile = file('src/main/java/com/jme3/system/JmeVersion.java')
|
"git.revision=${jmeRevision}\n" +
|
||||||
def jmeGitHash
|
"git.branch=${jmeBranchName}\n" +
|
||||||
def jmeShortGitHash
|
"git.hash=${jmeGitHash}\n" +
|
||||||
def jmeBuildDate
|
"git.hash.short=${jmeShortGitHash}\n" +
|
||||||
def jmeBranchName
|
"git.tag=${jmeGitTag}\n" +
|
||||||
|
"name.full=jMonkeyEngine ${jmeFullVersion}\n" +
|
||||||
try {
|
"version.full=${jmeFullVersion}\n" +
|
||||||
def grgit = Grgit.open(project.file('.').parent)
|
"version.number=${jmeVersion}\n" +
|
||||||
jmeGitHash = grgit.head().id
|
"version.tag=${jmeVersionTag}"
|
||||||
jmeShortGitHash = grgit.head().abbreviatedId
|
|
||||||
jmeBuildDate = new SimpleDateFormat("yyyy-MM-dd").format(new Date())
|
|
||||||
jmeBranchName = grgit.branch.current.name
|
|
||||||
} catch (ex) {
|
|
||||||
// Failed to get repo info
|
|
||||||
logger.warn("Failed to get repository info: " + ex.message + ". " + \
|
|
||||||
"Only partial build info will be generated.")
|
|
||||||
|
|
||||||
jmeGitHash = ""
|
|
||||||
jmeShortGitHash = ""
|
|
||||||
jmeBuildDate = new SimpleDateFormat("yyyy-MM-dd").format(new Date())
|
|
||||||
jmeBranchName = "unknown"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
verfile.text = "\npackage com.jme3.system;\n\n" +
|
compileJava.dependsOn(updateVersionPropertiesFile)
|
||||||
"/**\n * THIS IS AN AUTO-GENERATED FILE..\n * DO NOT MODIFY!\n */\n" +
|
|
||||||
"public class JmeVersion {\n" +
|
|
||||||
" public static final String BUILD_DATE = \"${jmeBuildDate}\";\n" +
|
|
||||||
" public static final String BRANCH_NAME = \"${jmeBranchName}\";\n" +
|
|
||||||
" public static final String GIT_HASH = \"${jmeGitHash}\";\n" +
|
|
||||||
" public static final String GIT_SHORT_HASH = \"${jmeShortGitHash}\";\n" +
|
|
||||||
" public static final String FULL_NAME = \"jMonkeyEngine ${jmeVersion} (${jmeVersionTag})\";\n" +
|
|
||||||
"}\n"
|
|
||||||
}
|
|
||||||
|
|
||||||
compileJava.dependsOn(updateVersion)
|
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
}
|
}
|
||||||
|
@ -553,7 +553,6 @@ public final class Bone implements Savable {
|
|||||||
Vector3f translate = modelPos.add(rotate.mult(scale.mult(modelBindInversePos, tmp2), tmp2), tmp2);
|
Vector3f translate = modelPos.add(rotate.mult(scale.mult(modelBindInversePos, tmp2), tmp2), tmp2);
|
||||||
|
|
||||||
// Populating the matrix
|
// Populating the matrix
|
||||||
outTransform.loadIdentity();
|
|
||||||
outTransform.setTransform(translate, scale, rotate.toRotationMatrix(tmp4));
|
outTransform.setTransform(translate, scale, rotate.toRotationMatrix(tmp4));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,7 +75,7 @@ final class ImplHandler {
|
|||||||
this.assetManager = assetManager;
|
this.assetManager = assetManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static class ImplThreadLocal<T> extends ThreadLocal {
|
protected static class ImplThreadLocal<T> extends ThreadLocal<T> {
|
||||||
|
|
||||||
private final Class<T> type;
|
private final Class<T> type;
|
||||||
private final String path;
|
private final String path;
|
||||||
@ -112,9 +112,13 @@ final class ImplHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Object initialValue(){
|
protected T initialValue(){
|
||||||
try {
|
try {
|
||||||
return type.newInstance();
|
T obj = type.newInstance();
|
||||||
|
if (path != null) {
|
||||||
|
((AssetLocator)obj).setRootPath(path);
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
} catch (InstantiationException ex) {
|
} catch (InstantiationException ex) {
|
||||||
logger.log(Level.SEVERE,"Cannot create locator of type {0}, does"
|
logger.log(Level.SEVERE,"Cannot create locator of type {0}, does"
|
||||||
+ " the class have an empty and publically accessible"+
|
+ " the class have an empty and publically accessible"+
|
||||||
@ -169,15 +173,12 @@ final class ImplHandler {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ImplThreadLocal local : locatorsList){
|
for (ImplThreadLocal<AssetLocator> local : locatorsList){
|
||||||
AssetLocator locator = (AssetLocator) local.get();
|
AssetInfo info = local.get().locate(assetManager, key);
|
||||||
if (local.getPath() != null){
|
if (info != null) {
|
||||||
locator.setRootPath((String) local.getPath());
|
|
||||||
}
|
|
||||||
AssetInfo info = locator.locate(assetManager, key);
|
|
||||||
if (info != null)
|
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -31,22 +31,20 @@
|
|||||||
*/
|
*/
|
||||||
package com.jme3.audio.openal;
|
package com.jme3.audio.openal;
|
||||||
|
|
||||||
import com.jme3.audio.AudioSource.Status;
|
|
||||||
import com.jme3.audio.*;
|
import com.jme3.audio.*;
|
||||||
|
import com.jme3.audio.AudioSource.Status;
|
||||||
import com.jme3.math.Vector3f;
|
import com.jme3.math.Vector3f;
|
||||||
import com.jme3.util.BufferUtils;
|
import com.jme3.util.BufferUtils;
|
||||||
import com.jme3.util.NativeObjectManager;
|
import com.jme3.util.NativeObjectManager;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.FloatBuffer;
|
import java.nio.FloatBuffer;
|
||||||
import java.nio.IntBuffer;
|
import java.nio.IntBuffer;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import static com.jme3.audio.openal.AL.*;
|
import static com.jme3.audio.openal.AL.*;
|
||||||
import static com.jme3.audio.openal.ALC.*;
|
|
||||||
import static com.jme3.audio.openal.EFX.*;
|
|
||||||
|
|
||||||
public class ALAudioRenderer implements AudioRenderer, Runnable {
|
public class ALAudioRenderer implements AudioRenderer, Runnable {
|
||||||
|
|
||||||
@ -102,16 +100,6 @@ public class ALAudioRenderer implements AudioRenderer, Runnable {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String deviceName = alc.alcGetString(ALC.ALC_DEVICE_SPECIFIER);
|
|
||||||
|
|
||||||
logger.log(Level.INFO, "Audio Device: {0}", deviceName);
|
|
||||||
logger.log(Level.INFO, "Audio Vendor: {0}", al.alGetString(AL_VENDOR));
|
|
||||||
logger.log(Level.INFO, "Audio Renderer: {0}", al.alGetString(AL_RENDERER));
|
|
||||||
logger.log(Level.INFO, "Audio Version: {0}", al.alGetString(AL_VERSION));
|
|
||||||
|
|
||||||
logger.log(Level.INFO, "ALC extensions: {0}", alc.alcGetString(ALC.ALC_EXTENSIONS));
|
|
||||||
logger.log(Level.INFO, "AL extensions: {0}", al.alGetString(AL_EXTENSIONS));
|
|
||||||
|
|
||||||
// Find maximum # of sources supported by this implementation
|
// Find maximum # of sources supported by this implementation
|
||||||
ArrayList<Integer> channelList = new ArrayList<Integer>();
|
ArrayList<Integer> channelList = new ArrayList<Integer>();
|
||||||
for (int i = 0; i < MAX_NUM_CHANNELS; i++) {
|
for (int i = 0; i < MAX_NUM_CHANNELS; i++) {
|
||||||
@ -131,7 +119,25 @@ public class ALAudioRenderer implements AudioRenderer, Runnable {
|
|||||||
ib = BufferUtils.createIntBuffer(channels.length);
|
ib = BufferUtils.createIntBuffer(channels.length);
|
||||||
chanSrcs = new AudioSource[channels.length];
|
chanSrcs = new AudioSource[channels.length];
|
||||||
|
|
||||||
logger.log(Level.INFO, "AudioRenderer supports {0} channels", channels.length);
|
final String deviceName = alc.alcGetString(ALC.ALC_DEVICE_SPECIFIER);
|
||||||
|
|
||||||
|
logger.log(Level.INFO, "Audio Renderer Information\n" +
|
||||||
|
" * Device: {0}\n" +
|
||||||
|
" * Vendor: {1}\n" +
|
||||||
|
" * Renderer: {2}\n" +
|
||||||
|
" * Version: {3}\n" +
|
||||||
|
" * Supported channels: {4}\n" +
|
||||||
|
" * ALC extensions: {5}\n" +
|
||||||
|
" * AL extensions: {6}",
|
||||||
|
new Object[]{
|
||||||
|
deviceName,
|
||||||
|
al.alGetString(AL_VENDOR),
|
||||||
|
al.alGetString(AL_RENDERER),
|
||||||
|
al.alGetString(AL_VERSION),
|
||||||
|
channels.length,
|
||||||
|
alc.alcGetString(ALC.ALC_EXTENSIONS),
|
||||||
|
al.alGetString(AL_EXTENSIONS)
|
||||||
|
});
|
||||||
|
|
||||||
// Pause device is a feature used specifically on Android
|
// Pause device is a feature used specifically on Android
|
||||||
// where the application could be closed but still running,
|
// where the application could be closed but still running,
|
||||||
@ -153,7 +159,7 @@ public class ALAudioRenderer implements AudioRenderer, Runnable {
|
|||||||
|
|
||||||
alc.alcGetInteger(EFX.ALC_MAX_AUXILIARY_SENDS, ib, 1);
|
alc.alcGetInteger(EFX.ALC_MAX_AUXILIARY_SENDS, ib, 1);
|
||||||
auxSends = ib.get(0);
|
auxSends = ib.get(0);
|
||||||
logger.log(Level.INFO, "Audio max auxilary sends: {0}", auxSends);
|
logger.log(Level.INFO, "Audio max auxiliary sends: {0}", auxSends);
|
||||||
|
|
||||||
// create slot
|
// create slot
|
||||||
ib.position(0).limit(1);
|
ib.position(0).limit(1);
|
||||||
|
@ -41,6 +41,7 @@ import com.jme3.export.JmeImporter;
|
|||||||
import com.jme3.export.OutputCapsule;
|
import com.jme3.export.OutputCapsule;
|
||||||
import com.jme3.math.*;
|
import com.jme3.math.*;
|
||||||
import com.jme3.scene.Mesh;
|
import com.jme3.scene.Mesh;
|
||||||
|
import com.jme3.scene.Spatial;
|
||||||
import com.jme3.util.TempVars;
|
import com.jme3.util.TempVars;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.FloatBuffer;
|
import java.nio.FloatBuffer;
|
||||||
@ -313,7 +314,7 @@ public class BoundingBox extends BoundingVolume {
|
|||||||
transMatrix.absoluteLocal();
|
transMatrix.absoluteLocal();
|
||||||
|
|
||||||
Vector3f scale = trans.getScale();
|
Vector3f scale = trans.getScale();
|
||||||
vars.vect1.set(xExtent * scale.x, yExtent * scale.y, zExtent * scale.z);
|
vars.vect1.set(xExtent * FastMath.abs(scale.x), yExtent * FastMath.abs(scale.y), zExtent * FastMath.abs(scale.z));
|
||||||
transMatrix.mult(vars.vect1, vars.vect2);
|
transMatrix.mult(vars.vect1, vars.vect2);
|
||||||
// Assign the biggest rotations after scales.
|
// Assign the biggest rotations after scales.
|
||||||
box.xExtent = FastMath.abs(vars.vect2.getX());
|
box.xExtent = FastMath.abs(vars.vect2.getX());
|
||||||
@ -593,18 +594,7 @@ public class BoundingBox extends BoundingVolume {
|
|||||||
* @see BoundingVolume#intersectsSphere(com.jme3.bounding.BoundingSphere)
|
* @see BoundingVolume#intersectsSphere(com.jme3.bounding.BoundingSphere)
|
||||||
*/
|
*/
|
||||||
public boolean intersectsSphere(BoundingSphere bs) {
|
public boolean intersectsSphere(BoundingSphere bs) {
|
||||||
assert Vector3f.isValidVector(center) && Vector3f.isValidVector(bs.center);
|
return bs.intersectsBoundingBox(this);
|
||||||
|
|
||||||
if (FastMath.abs(center.x - bs.center.x) < bs.getRadius()
|
|
||||||
+ xExtent
|
|
||||||
&& FastMath.abs(center.y - bs.center.y) < bs.getRadius()
|
|
||||||
+ yExtent
|
|
||||||
&& FastMath.abs(center.z - bs.center.z) < bs.getRadius()
|
|
||||||
+ zExtent) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -790,6 +780,7 @@ public class BoundingBox extends BoundingVolume {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int collideWith(Collidable other, CollisionResults results) {
|
public int collideWith(Collidable other, CollisionResults results) {
|
||||||
if (other instanceof Ray) {
|
if (other instanceof Ray) {
|
||||||
Ray ray = (Ray) other;
|
Ray ray = (Ray) other;
|
||||||
@ -802,6 +793,15 @@ public class BoundingBox extends BoundingVolume {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
} else if (other instanceof BoundingVolume) {
|
||||||
|
if (intersects((BoundingVolume) other)) {
|
||||||
|
CollisionResult r = new CollisionResult();
|
||||||
|
results.addCollision(r);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
} else if (other instanceof Spatial) {
|
||||||
|
return ((Spatial)other).collideWith(this, results);
|
||||||
} else {
|
} else {
|
||||||
throw new UnsupportedCollisionException("With: " + other.getClass().getSimpleName());
|
throw new UnsupportedCollisionException("With: " + other.getClass().getSimpleName());
|
||||||
}
|
}
|
||||||
@ -818,6 +818,8 @@ public class BoundingBox extends BoundingVolume {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
} else if (other instanceof BoundingVolume) {
|
||||||
|
return intersects((BoundingVolume) other) ? 1 : 0;
|
||||||
} else {
|
} else {
|
||||||
throw new UnsupportedCollisionException("With: " + other.getClass().getSimpleName());
|
throw new UnsupportedCollisionException("With: " + other.getClass().getSimpleName());
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,7 @@ import com.jme3.collision.UnsupportedCollisionException;
|
|||||||
import com.jme3.export.JmeExporter;
|
import com.jme3.export.JmeExporter;
|
||||||
import com.jme3.export.JmeImporter;
|
import com.jme3.export.JmeImporter;
|
||||||
import com.jme3.math.*;
|
import com.jme3.math.*;
|
||||||
|
import com.jme3.scene.Spatial;
|
||||||
import com.jme3.util.BufferUtils;
|
import com.jme3.util.BufferUtils;
|
||||||
import com.jme3.util.TempVars;
|
import com.jme3.util.TempVars;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -670,15 +671,7 @@ public class BoundingSphere extends BoundingVolume {
|
|||||||
* @see com.jme.bounding.BoundingVolume#intersectsSphere(com.jme.bounding.BoundingSphere)
|
* @see com.jme.bounding.BoundingVolume#intersectsSphere(com.jme.bounding.BoundingSphere)
|
||||||
*/
|
*/
|
||||||
public boolean intersectsSphere(BoundingSphere bs) {
|
public boolean intersectsSphere(BoundingSphere bs) {
|
||||||
assert Vector3f.isValidVector(center) && Vector3f.isValidVector(bs.center);
|
return Intersection.intersect(bs, center, radius);
|
||||||
|
|
||||||
TempVars vars = TempVars.get();
|
|
||||||
|
|
||||||
Vector3f diff = center.subtract(bs.center, vars.vect1);
|
|
||||||
float rsum = getRadius() + bs.getRadius();
|
|
||||||
boolean eq = (diff.dot(diff) <= rsum * rsum);
|
|
||||||
vars.release();
|
|
||||||
return eq;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -687,18 +680,7 @@ public class BoundingSphere extends BoundingVolume {
|
|||||||
* @see com.jme.bounding.BoundingVolume#intersectsBoundingBox(com.jme.bounding.BoundingBox)
|
* @see com.jme.bounding.BoundingVolume#intersectsBoundingBox(com.jme.bounding.BoundingBox)
|
||||||
*/
|
*/
|
||||||
public boolean intersectsBoundingBox(BoundingBox bb) {
|
public boolean intersectsBoundingBox(BoundingBox bb) {
|
||||||
assert Vector3f.isValidVector(center) && Vector3f.isValidVector(bb.center);
|
return Intersection.intersect(bb, center, radius);
|
||||||
|
|
||||||
if (FastMath.abs(bb.center.x - center.x) < getRadius()
|
|
||||||
+ bb.xExtent
|
|
||||||
&& FastMath.abs(bb.center.y - center.y) < getRadius()
|
|
||||||
+ bb.yExtent
|
|
||||||
&& FastMath.abs(bb.center.z - center.z) < getRadius()
|
|
||||||
+ bb.zExtent) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1013,17 +995,29 @@ public class BoundingSphere extends BoundingVolume {
|
|||||||
} else if (other instanceof Triangle){
|
} else if (other instanceof Triangle){
|
||||||
Triangle t = (Triangle) other;
|
Triangle t = (Triangle) other;
|
||||||
return collideWithTri(t, results);
|
return collideWithTri(t, results);
|
||||||
|
} else if (other instanceof BoundingVolume) {
|
||||||
|
if (intersects((BoundingVolume)other)) {
|
||||||
|
CollisionResult result = new CollisionResult();
|
||||||
|
results.addCollision(result);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
} else if (other instanceof Spatial) {
|
||||||
|
return ((Spatial)other).collideWith(this, results);
|
||||||
} else {
|
} else {
|
||||||
throw new UnsupportedCollisionException();
|
throw new UnsupportedCollisionException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public int collideWith(Collidable other) {
|
@Override
|
||||||
|
public int collideWith(Collidable other) {
|
||||||
if (other instanceof Ray) {
|
if (other instanceof Ray) {
|
||||||
Ray ray = (Ray) other;
|
Ray ray = (Ray) other;
|
||||||
return collideWithRay(ray);
|
return collideWithRay(ray);
|
||||||
} else if (other instanceof Triangle){
|
} else if (other instanceof Triangle){
|
||||||
return super.collideWith(other);
|
return super.collideWith(other);
|
||||||
|
} else if (other instanceof BoundingVolume) {
|
||||||
|
return intersects((BoundingVolume)other) ? 1 : 0;
|
||||||
} else {
|
} else {
|
||||||
throw new UnsupportedCollisionException();
|
throw new UnsupportedCollisionException();
|
||||||
}
|
}
|
||||||
|
@ -327,12 +327,13 @@ public abstract class BoundingVolume implements Savable, Cloneable, Collidable {
|
|||||||
|
|
||||||
public int collideWith(Collidable other) {
|
public int collideWith(Collidable other) {
|
||||||
TempVars tempVars = TempVars.get();
|
TempVars tempVars = TempVars.get();
|
||||||
|
try {
|
||||||
CollisionResults tempResults = tempVars.collisionResults;
|
CollisionResults tempResults = tempVars.collisionResults;
|
||||||
tempResults.clear();
|
tempResults.clear();
|
||||||
int retval = collideWith(other, tempResults);
|
return collideWith(other, tempResults);
|
||||||
|
} finally {
|
||||||
tempVars.release();
|
tempVars.release();
|
||||||
return retval;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,9 +41,55 @@ import static java.lang.Math.min;
|
|||||||
/**
|
/**
|
||||||
* This class includes some utility methods for computing intersection
|
* This class includes some utility methods for computing intersection
|
||||||
* between bounding volumes and triangles.
|
* between bounding volumes and triangles.
|
||||||
|
*
|
||||||
* @author Kirill
|
* @author Kirill
|
||||||
*/
|
*/
|
||||||
public class Intersection {
|
public final class Intersection {
|
||||||
|
|
||||||
|
private Intersection() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean intersect(BoundingSphere sphere, Vector3f center, float radius) {
|
||||||
|
assert Vector3f.isValidVector(center) && Vector3f.isValidVector(sphere.center);
|
||||||
|
|
||||||
|
TempVars vars = TempVars.get();
|
||||||
|
try {
|
||||||
|
Vector3f diff = center.subtract(sphere.center, vars.vect1);
|
||||||
|
float rsum = sphere.getRadius() + radius;
|
||||||
|
return (diff.dot(diff) <= rsum * rsum);
|
||||||
|
} finally {
|
||||||
|
vars.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean intersect(BoundingBox bbox, Vector3f center, float radius) {
|
||||||
|
assert Vector3f.isValidVector(center) && Vector3f.isValidVector(bbox.center);
|
||||||
|
|
||||||
|
// Arvo's algorithm
|
||||||
|
float distSqr = radius * radius;
|
||||||
|
|
||||||
|
float minX = bbox.center.x - bbox.xExtent;
|
||||||
|
float maxX = bbox.center.x + bbox.xExtent;
|
||||||
|
|
||||||
|
float minY = bbox.center.y - bbox.yExtent;
|
||||||
|
float maxY = bbox.center.y + bbox.yExtent;
|
||||||
|
|
||||||
|
float minZ = bbox.center.z - bbox.zExtent;
|
||||||
|
float maxZ = bbox.center.z + bbox.zExtent;
|
||||||
|
|
||||||
|
if (center.x < minX) distSqr -= FastMath.sqr(center.x - minX);
|
||||||
|
else if (center.x > maxX) distSqr -= FastMath.sqr(center.x - maxX);
|
||||||
|
|
||||||
|
|
||||||
|
if (center.y < minY) distSqr -= FastMath.sqr(center.y - minY);
|
||||||
|
else if (center.y > maxY) distSqr -= FastMath.sqr(center.y - maxY);
|
||||||
|
|
||||||
|
|
||||||
|
if (center.z < minZ) distSqr -= FastMath.sqr(center.z - minZ);
|
||||||
|
else if (center.z > maxZ) distSqr -= FastMath.sqr(center.z - maxZ);
|
||||||
|
|
||||||
|
return distSqr > 0;
|
||||||
|
}
|
||||||
|
|
||||||
private static final void findMinMax(float x0, float x1, float x2, Vector3f minMax) {
|
private static final void findMinMax(float x0, float x1, float x2, Vector3f minMax) {
|
||||||
minMax.set(x0, x0, 0);
|
minMax.set(x0, x0, 0);
|
||||||
|
@ -702,8 +702,10 @@ public class Cinematic extends AbstractCinematicEvent implements AppState {
|
|||||||
dispose();
|
dispose();
|
||||||
cinematicEvents.clear();
|
cinematicEvents.clear();
|
||||||
timeLine.clear();
|
timeLine.clear();
|
||||||
|
if (eventsData != null) {
|
||||||
eventsData.clear();
|
eventsData.clear();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* used internally to cleanup the cinematic. Called when the clear() method
|
* used internally to cleanup the cinematic. Called when the clear() method
|
||||||
|
@ -43,7 +43,7 @@ import com.jme3.export.JmeImporter;
|
|||||||
import com.jme3.export.OutputCapsule;
|
import com.jme3.export.OutputCapsule;
|
||||||
import com.jme3.scene.Spatial;
|
import com.jme3.scene.Spatial;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
@ -431,11 +431,12 @@ public class AnimationEvent extends AbstractCinematicEvent {
|
|||||||
@Override
|
@Override
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
super.dispose();
|
super.dispose();
|
||||||
|
if (cinematic != null) {
|
||||||
Object o = cinematic.getEventData(MODEL_CHANNELS, model);
|
Object o = cinematic.getEventData(MODEL_CHANNELS, model);
|
||||||
if (o != null) {
|
if (o != null) {
|
||||||
ArrayList<AnimChannel> list = (ArrayList<AnimChannel>) o;
|
Collection<AnimChannel> values = ((HashMap<Integer, AnimChannel>) o).values();
|
||||||
list.remove(channel);
|
while (values.remove(channel));
|
||||||
if (list.isEmpty()) {
|
if (values.isEmpty()) {
|
||||||
cinematic.removeEventData(MODEL_CHANNELS, model);
|
cinematic.removeEventData(MODEL_CHANNELS, model);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -443,3 +444,4 @@ public class AnimationEvent extends AbstractCinematicEvent {
|
|||||||
channel = null;
|
channel = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
@ -48,6 +48,7 @@ import com.jme3.math.Vector3f;
|
|||||||
import com.jme3.scene.CollisionData;
|
import com.jme3.scene.CollisionData;
|
||||||
import com.jme3.scene.Mesh;
|
import com.jme3.scene.Mesh;
|
||||||
import com.jme3.scene.Mesh.Mode;
|
import com.jme3.scene.Mesh.Mode;
|
||||||
|
import com.jme3.scene.VertexBuffer;
|
||||||
import com.jme3.scene.VertexBuffer.Type;
|
import com.jme3.scene.VertexBuffer.Type;
|
||||||
import com.jme3.scene.mesh.IndexBuffer;
|
import com.jme3.scene.mesh.IndexBuffer;
|
||||||
import com.jme3.scene.mesh.VirtualIndexBuffer;
|
import com.jme3.scene.mesh.VirtualIndexBuffer;
|
||||||
@ -114,8 +115,13 @@ public class BIHTree implements CollisionData {
|
|||||||
|
|
||||||
bihSwapTmp = new float[9];
|
bihSwapTmp = new float[9];
|
||||||
|
|
||||||
FloatBuffer vb = (FloatBuffer) mesh.getBuffer(Type.Position).getData();
|
VertexBuffer vBuffer = mesh.getBuffer(Type.Position);
|
||||||
|
if(vBuffer == null){
|
||||||
|
throw new IllegalArgumentException("A mesh should at least contain a Position buffer");
|
||||||
|
}
|
||||||
IndexBuffer ib = mesh.getIndexBuffer();
|
IndexBuffer ib = mesh.getIndexBuffer();
|
||||||
|
FloatBuffer vb = (FloatBuffer) vBuffer.getData();
|
||||||
|
|
||||||
if (ib == null) {
|
if (ib == null) {
|
||||||
ib = new VirtualIndexBuffer(mesh.getVertexCount(), mesh.getMode());
|
ib = new VirtualIndexBuffer(mesh.getVertexCount(), mesh.getMode());
|
||||||
} else if (mesh.getMode() != Mode.Triangles) {
|
} else if (mesh.getMode() != Mode.Triangles) {
|
||||||
|
@ -59,6 +59,7 @@ class BitmapTextPage extends Geometry {
|
|||||||
|
|
||||||
BitmapTextPage(BitmapFont font, boolean arrayBased, int page) {
|
BitmapTextPage(BitmapFont font, boolean arrayBased, int page) {
|
||||||
super("BitmapFont", new Mesh());
|
super("BitmapFont", new Mesh());
|
||||||
|
setRequiresUpdates(false);
|
||||||
setBatchHint(BatchHint.Never);
|
setBatchHint(BatchHint.Never);
|
||||||
if (font == null) {
|
if (font == null) {
|
||||||
throw new IllegalArgumentException("font cannot be null.");
|
throw new IllegalArgumentException("font cannot be null.");
|
||||||
|
@ -72,9 +72,11 @@ public class DefaultJoystickAxis implements JoystickAxis {
|
|||||||
* @param negativeMapping The mapping to receive events when the axis is positive
|
* @param negativeMapping The mapping to receive events when the axis is positive
|
||||||
*/
|
*/
|
||||||
public void assignAxis(String positiveMapping, String negativeMapping){
|
public void assignAxis(String positiveMapping, String negativeMapping){
|
||||||
|
if (axisIndex != -1) {
|
||||||
inputManager.addMapping(positiveMapping, new JoyAxisTrigger(parent.getJoyId(), axisIndex, false));
|
inputManager.addMapping(positiveMapping, new JoyAxisTrigger(parent.getJoyId(), axisIndex, false));
|
||||||
inputManager.addMapping(negativeMapping, new JoyAxisTrigger(parent.getJoyId(), axisIndex, true));
|
inputManager.addMapping(negativeMapping, new JoyAxisTrigger(parent.getJoyId(), axisIndex, true));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the joystick to which this axis object belongs.
|
* Returns the joystick to which this axis object belongs.
|
||||||
@ -133,6 +135,14 @@ public class DefaultJoystickAxis implements JoystickAxis {
|
|||||||
return deadZone;
|
return deadZone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets/overrides the dead zone for this axis. This indicates that values
|
||||||
|
* within +/- deadZone should be ignored.
|
||||||
|
*/
|
||||||
|
public void setDeadZone( float f ) {
|
||||||
|
this.deadZone = f;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString(){
|
public String toString(){
|
||||||
return "JoystickAxis[name=" + name + ", parent=" + parent.getName() + ", id=" + axisIndex
|
return "JoystickAxis[name=" + name + ", parent=" + parent.getName() + ", id=" + axisIndex
|
||||||
|
@ -277,8 +277,7 @@ public class FlyByCamera implements AnalogListener, ActionListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers the FlyByCamera to receive input events from the provided
|
* Unregisters the FlyByCamera from the event Dispatcher.
|
||||||
* Dispatcher.
|
|
||||||
*/
|
*/
|
||||||
public void unregisterInput(){
|
public void unregisterInput(){
|
||||||
|
|
||||||
|
@ -39,6 +39,7 @@ import com.jme3.math.FastMath;
|
|||||||
import com.jme3.math.Vector2f;
|
import com.jme3.math.Vector2f;
|
||||||
import com.jme3.util.IntMap;
|
import com.jme3.util.IntMap;
|
||||||
import com.jme3.util.IntMap.Entry;
|
import com.jme3.util.IntMap.Entry;
|
||||||
|
import com.jme3.util.SafeArrayList;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
@ -96,16 +97,15 @@ public class InputManager implements RawInputListener {
|
|||||||
private boolean eventsPermitted = false;
|
private boolean eventsPermitted = false;
|
||||||
private boolean mouseVisible = true;
|
private boolean mouseVisible = true;
|
||||||
private boolean safeMode = false;
|
private boolean safeMode = false;
|
||||||
private float axisDeadZone = 0.05f;
|
private float globalAxisDeadZone = 0.05f;
|
||||||
private Vector2f cursorPos = new Vector2f();
|
private final Vector2f cursorPos = new Vector2f();
|
||||||
private Joystick[] joysticks;
|
private Joystick[] joysticks;
|
||||||
private final IntMap<ArrayList<Mapping>> bindings = new IntMap<ArrayList<Mapping>>();
|
private final IntMap<ArrayList<Mapping>> bindings = new IntMap<ArrayList<Mapping>>();
|
||||||
private final HashMap<String, Mapping> mappings = new HashMap<String, Mapping>();
|
private final HashMap<String, Mapping> mappings = new HashMap<String, Mapping>();
|
||||||
private final IntMap<Long> pressedButtons = new IntMap<Long>();
|
private final IntMap<Long> pressedButtons = new IntMap<Long>();
|
||||||
private final IntMap<Float> axisValues = new IntMap<Float>();
|
private final IntMap<Float> axisValues = new IntMap<Float>();
|
||||||
private ArrayList<RawInputListener> rawListeners = new ArrayList<RawInputListener>();
|
private final SafeArrayList<RawInputListener> rawListeners = new SafeArrayList<RawInputListener>(RawInputListener.class);
|
||||||
private RawInputListener[] rawListenerArray = null;
|
private final ArrayList<InputEvent> inputQueue = new ArrayList<InputEvent>();
|
||||||
private ArrayList<InputEvent> inputQueue = new ArrayList<InputEvent>();
|
|
||||||
|
|
||||||
private static class Mapping {
|
private static class Mapping {
|
||||||
|
|
||||||
@ -248,8 +248,8 @@ public class InputManager implements RawInputListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void invokeAnalogsAndActions(int hash, float value, boolean applyTpf) {
|
private void invokeAnalogsAndActions(int hash, float value, float effectiveDeadZone, boolean applyTpf) {
|
||||||
if (value < axisDeadZone) {
|
if (value < effectiveDeadZone) {
|
||||||
invokeAnalogs(hash, value, !applyTpf);
|
invokeAnalogs(hash, value, !applyTpf);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -287,12 +287,14 @@ public class InputManager implements RawInputListener {
|
|||||||
/**
|
/**
|
||||||
* Callback from RawInputListener. Do not use.
|
* Callback from RawInputListener. Do not use.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void beginInput() {
|
public void beginInput() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback from RawInputListener. Do not use.
|
* Callback from RawInputListener. Do not use.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void endInput() {
|
public void endInput() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -304,17 +306,18 @@ public class InputManager implements RawInputListener {
|
|||||||
int joyId = evt.getJoyIndex();
|
int joyId = evt.getJoyIndex();
|
||||||
int axis = evt.getAxisIndex();
|
int axis = evt.getAxisIndex();
|
||||||
float value = evt.getValue();
|
float value = evt.getValue();
|
||||||
if (value < axisDeadZone && value > -axisDeadZone) {
|
float effectiveDeadZone = Math.max(globalAxisDeadZone, evt.getAxis().getDeadZone());
|
||||||
|
if (value < effectiveDeadZone && value > -effectiveDeadZone) {
|
||||||
int hash1 = JoyAxisTrigger.joyAxisHash(joyId, axis, true);
|
int hash1 = JoyAxisTrigger.joyAxisHash(joyId, axis, true);
|
||||||
int hash2 = JoyAxisTrigger.joyAxisHash(joyId, axis, false);
|
int hash2 = JoyAxisTrigger.joyAxisHash(joyId, axis, false);
|
||||||
|
|
||||||
Float val1 = axisValues.get(hash1);
|
Float val1 = axisValues.get(hash1);
|
||||||
Float val2 = axisValues.get(hash2);
|
Float val2 = axisValues.get(hash2);
|
||||||
|
|
||||||
if (val1 != null && val1.floatValue() > axisDeadZone) {
|
if (val1 != null && val1 > effectiveDeadZone) {
|
||||||
invokeActions(hash1, false);
|
invokeActions(hash1, false);
|
||||||
}
|
}
|
||||||
if (val2 != null && val2.floatValue() > axisDeadZone) {
|
if (val2 != null && val2 > effectiveDeadZone) {
|
||||||
invokeActions(hash2, false);
|
invokeActions(hash2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -328,11 +331,11 @@ public class InputManager implements RawInputListener {
|
|||||||
// Clear the reverse direction's actions in case we
|
// Clear the reverse direction's actions in case we
|
||||||
// crossed center too quickly
|
// crossed center too quickly
|
||||||
Float otherVal = axisValues.get(otherHash);
|
Float otherVal = axisValues.get(otherHash);
|
||||||
if (otherVal != null && otherVal.floatValue() > axisDeadZone) {
|
if (otherVal != null && otherVal > effectiveDeadZone) {
|
||||||
invokeActions(otherHash, false);
|
invokeActions(otherHash, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
invokeAnalogsAndActions(hash, -value, true);
|
invokeAnalogsAndActions(hash, -value, effectiveDeadZone, true);
|
||||||
axisValues.put(hash, -value);
|
axisValues.put(hash, -value);
|
||||||
axisValues.remove(otherHash);
|
axisValues.remove(otherHash);
|
||||||
} else {
|
} else {
|
||||||
@ -342,11 +345,11 @@ public class InputManager implements RawInputListener {
|
|||||||
// Clear the reverse direction's actions in case we
|
// Clear the reverse direction's actions in case we
|
||||||
// crossed center too quickly
|
// crossed center too quickly
|
||||||
Float otherVal = axisValues.get(otherHash);
|
Float otherVal = axisValues.get(otherHash);
|
||||||
if (otherVal != null && otherVal.floatValue() > axisDeadZone) {
|
if (otherVal != null && otherVal > effectiveDeadZone) {
|
||||||
invokeActions(otherHash, false);
|
invokeActions(otherHash, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
invokeAnalogsAndActions(hash, value, true);
|
invokeAnalogsAndActions(hash, value, effectiveDeadZone, true);
|
||||||
axisValues.put(hash, value);
|
axisValues.put(hash, value);
|
||||||
axisValues.remove(otherHash);
|
axisValues.remove(otherHash);
|
||||||
}
|
}
|
||||||
@ -355,6 +358,7 @@ public class InputManager implements RawInputListener {
|
|||||||
/**
|
/**
|
||||||
* Callback from RawInputListener. Do not use.
|
* Callback from RawInputListener. Do not use.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void onJoyAxisEvent(JoyAxisEvent evt) {
|
public void onJoyAxisEvent(JoyAxisEvent evt) {
|
||||||
if (!eventsPermitted) {
|
if (!eventsPermitted) {
|
||||||
throw new UnsupportedOperationException("JoyInput has raised an event at an illegal time.");
|
throw new UnsupportedOperationException("JoyInput has raised an event at an illegal time.");
|
||||||
@ -376,6 +380,7 @@ public class InputManager implements RawInputListener {
|
|||||||
/**
|
/**
|
||||||
* Callback from RawInputListener. Do not use.
|
* Callback from RawInputListener. Do not use.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void onJoyButtonEvent(JoyButtonEvent evt) {
|
public void onJoyButtonEvent(JoyButtonEvent evt) {
|
||||||
if (!eventsPermitted) {
|
if (!eventsPermitted) {
|
||||||
throw new UnsupportedOperationException("JoyInput has raised an event at an illegal time.");
|
throw new UnsupportedOperationException("JoyInput has raised an event at an illegal time.");
|
||||||
@ -391,15 +396,15 @@ public class InputManager implements RawInputListener {
|
|||||||
|
|
||||||
if (evt.getDX() != 0) {
|
if (evt.getDX() != 0) {
|
||||||
float val = Math.abs(evt.getDX()) / 1024f;
|
float val = Math.abs(evt.getDX()) / 1024f;
|
||||||
invokeAnalogsAndActions(MouseAxisTrigger.mouseAxisHash(MouseInput.AXIS_X, evt.getDX() < 0), val, false);
|
invokeAnalogsAndActions(MouseAxisTrigger.mouseAxisHash(MouseInput.AXIS_X, evt.getDX() < 0), val, globalAxisDeadZone, false);
|
||||||
}
|
}
|
||||||
if (evt.getDY() != 0) {
|
if (evt.getDY() != 0) {
|
||||||
float val = Math.abs(evt.getDY()) / 1024f;
|
float val = Math.abs(evt.getDY()) / 1024f;
|
||||||
invokeAnalogsAndActions(MouseAxisTrigger.mouseAxisHash(MouseInput.AXIS_Y, evt.getDY() < 0), val, false);
|
invokeAnalogsAndActions(MouseAxisTrigger.mouseAxisHash(MouseInput.AXIS_Y, evt.getDY() < 0), val, globalAxisDeadZone, false);
|
||||||
}
|
}
|
||||||
if (evt.getDeltaWheel() != 0) {
|
if (evt.getDeltaWheel() != 0) {
|
||||||
float val = Math.abs(evt.getDeltaWheel()) / 100f;
|
float val = Math.abs(evt.getDeltaWheel()) / 100f;
|
||||||
invokeAnalogsAndActions(MouseAxisTrigger.mouseAxisHash(MouseInput.AXIS_WHEEL, evt.getDeltaWheel() < 0), val, false);
|
invokeAnalogsAndActions(MouseAxisTrigger.mouseAxisHash(MouseInput.AXIS_WHEEL, evt.getDeltaWheel() < 0), val, globalAxisDeadZone, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -419,6 +424,7 @@ public class InputManager implements RawInputListener {
|
|||||||
/**
|
/**
|
||||||
* Callback from RawInputListener. Do not use.
|
* Callback from RawInputListener. Do not use.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void onMouseMotionEvent(MouseMotionEvent evt) {
|
public void onMouseMotionEvent(MouseMotionEvent evt) {
|
||||||
if (!eventsPermitted) {
|
if (!eventsPermitted) {
|
||||||
throw new UnsupportedOperationException("MouseInput has raised an event at an illegal time.");
|
throw new UnsupportedOperationException("MouseInput has raised an event at an illegal time.");
|
||||||
@ -437,6 +443,7 @@ public class InputManager implements RawInputListener {
|
|||||||
/**
|
/**
|
||||||
* Callback from RawInputListener. Do not use.
|
* Callback from RawInputListener. Do not use.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void onMouseButtonEvent(MouseButtonEvent evt) {
|
public void onMouseButtonEvent(MouseButtonEvent evt) {
|
||||||
if (!eventsPermitted) {
|
if (!eventsPermitted) {
|
||||||
throw new UnsupportedOperationException("MouseInput has raised an event at an illegal time.");
|
throw new UnsupportedOperationException("MouseInput has raised an event at an illegal time.");
|
||||||
@ -459,6 +466,7 @@ public class InputManager implements RawInputListener {
|
|||||||
/**
|
/**
|
||||||
* Callback from RawInputListener. Do not use.
|
* Callback from RawInputListener. Do not use.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void onKeyEvent(KeyInputEvent evt) {
|
public void onKeyEvent(KeyInputEvent evt) {
|
||||||
if (!eventsPermitted) {
|
if (!eventsPermitted) {
|
||||||
throw new UnsupportedOperationException("KeyInput has raised an event at an illegal time.");
|
throw new UnsupportedOperationException("KeyInput has raised an event at an illegal time.");
|
||||||
@ -477,7 +485,7 @@ public class InputManager implements RawInputListener {
|
|||||||
* @param deadZone the deadzone for joystick axes.
|
* @param deadZone the deadzone for joystick axes.
|
||||||
*/
|
*/
|
||||||
public void setAxisDeadZone(float deadZone) {
|
public void setAxisDeadZone(float deadZone) {
|
||||||
this.axisDeadZone = deadZone;
|
this.globalAxisDeadZone = deadZone;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -486,7 +494,7 @@ public class InputManager implements RawInputListener {
|
|||||||
* @return the deadzone for joystick axes.
|
* @return the deadzone for joystick axes.
|
||||||
*/
|
*/
|
||||||
public float getAxisDeadZone() {
|
public float getAxisDeadZone() {
|
||||||
return axisDeadZone;
|
return globalAxisDeadZone;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -721,7 +729,6 @@ public class InputManager implements RawInputListener {
|
|||||||
*/
|
*/
|
||||||
public void addRawInputListener(RawInputListener listener) {
|
public void addRawInputListener(RawInputListener listener) {
|
||||||
rawListeners.add(listener);
|
rawListeners.add(listener);
|
||||||
rawListenerArray = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -734,7 +741,6 @@ public class InputManager implements RawInputListener {
|
|||||||
*/
|
*/
|
||||||
public void removeRawInputListener(RawInputListener listener) {
|
public void removeRawInputListener(RawInputListener listener) {
|
||||||
rawListeners.remove(listener);
|
rawListeners.remove(listener);
|
||||||
rawListenerArray = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -744,13 +750,6 @@ public class InputManager implements RawInputListener {
|
|||||||
*/
|
*/
|
||||||
public void clearRawInputListeners() {
|
public void clearRawInputListeners() {
|
||||||
rawListeners.clear();
|
rawListeners.clear();
|
||||||
rawListenerArray = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private RawInputListener[] getRawListenerArray() {
|
|
||||||
if (rawListenerArray == null)
|
|
||||||
rawListenerArray = rawListeners.toArray(new RawInputListener[rawListeners.size()]);
|
|
||||||
return rawListenerArray;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -813,7 +812,7 @@ public class InputManager implements RawInputListener {
|
|||||||
|
|
||||||
private void processQueue() {
|
private void processQueue() {
|
||||||
int queueSize = inputQueue.size();
|
int queueSize = inputQueue.size();
|
||||||
RawInputListener[] array = getRawListenerArray();
|
RawInputListener[] array = rawListeners.getArray();
|
||||||
|
|
||||||
for (RawInputListener listener : array) {
|
for (RawInputListener listener : array) {
|
||||||
listener.beginInput();
|
listener.beginInput();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
* Copyright (c) 2009-2012, 2015 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,6 +32,8 @@
|
|||||||
package com.jme3.light;
|
package com.jme3.light;
|
||||||
|
|
||||||
import com.jme3.bounding.BoundingBox;
|
import com.jme3.bounding.BoundingBox;
|
||||||
|
import com.jme3.bounding.BoundingSphere;
|
||||||
|
import com.jme3.math.ColorRGBA;
|
||||||
import com.jme3.math.Vector3f;
|
import com.jme3.math.Vector3f;
|
||||||
import com.jme3.renderer.Camera;
|
import com.jme3.renderer.Camera;
|
||||||
import com.jme3.scene.Spatial;
|
import com.jme3.scene.Spatial;
|
||||||
@ -49,11 +51,23 @@ import com.jme3.util.TempVars;
|
|||||||
*/
|
*/
|
||||||
public class AmbientLight extends Light {
|
public class AmbientLight extends Light {
|
||||||
|
|
||||||
|
public AmbientLight() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public AmbientLight(ColorRGBA color) {
|
||||||
|
super(color);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean intersectsBox(BoundingBox box, TempVars vars) {
|
public boolean intersectsBox(BoundingBox box, TempVars vars) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean intersectsSphere(BoundingSphere sphere, TempVars vars) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean intersectsFrustum(Camera camera, TempVars vars) {
|
public boolean intersectsFrustum(Camera camera, TempVars vars) {
|
||||||
return true;
|
return true;
|
||||||
@ -61,6 +75,8 @@ public class AmbientLight extends Light {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void computeLastDistance(Spatial owner) {
|
public void computeLastDistance(Spatial owner) {
|
||||||
|
// ambient lights must always be before directional lights.
|
||||||
|
lastDistance = -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2014 jMonkeyEngine
|
* Copyright (c) 2009-2015 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,6 +44,7 @@ public final class DefaultLightFilter implements LightFilter {
|
|||||||
private Camera camera;
|
private Camera camera;
|
||||||
private final HashSet<Light> processedLights = new HashSet<Light>();
|
private final HashSet<Light> processedLights = new HashSet<Light>();
|
||||||
|
|
||||||
|
@Override
|
||||||
public void setCamera(Camera camera) {
|
public void setCamera(Camera camera) {
|
||||||
this.camera = camera;
|
this.camera = camera;
|
||||||
for (Light light : processedLights) {
|
for (Light light : processedLights) {
|
||||||
@ -51,6 +52,7 @@ public final class DefaultLightFilter implements LightFilter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void filterLights(Geometry geometry, LightList filteredLightList) {
|
public void filterLights(Geometry geometry, LightList filteredLightList) {
|
||||||
TempVars vars = TempVars.get();
|
TempVars vars = TempVars.get();
|
||||||
try {
|
try {
|
||||||
@ -76,8 +78,9 @@ public final class DefaultLightFilter implements LightFilter {
|
|||||||
}
|
}
|
||||||
} else if (bv instanceof BoundingSphere) {
|
} else if (bv instanceof BoundingSphere) {
|
||||||
if (!Float.isInfinite( ((BoundingSphere)bv).getRadius() )) {
|
if (!Float.isInfinite( ((BoundingSphere)bv).getRadius() )) {
|
||||||
// Non-infinite bounding sphere... Not supported yet.
|
if (!light.intersectsSphere((BoundingSphere)bv, vars)) {
|
||||||
throw new UnsupportedOperationException("Only AABB supported for now");
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
* Copyright (c) 2009-2012, 2015 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,10 +32,12 @@
|
|||||||
package com.jme3.light;
|
package com.jme3.light;
|
||||||
|
|
||||||
import com.jme3.bounding.BoundingBox;
|
import com.jme3.bounding.BoundingBox;
|
||||||
|
import com.jme3.bounding.BoundingSphere;
|
||||||
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.export.OutputCapsule;
|
||||||
|
import com.jme3.math.ColorRGBA;
|
||||||
import com.jme3.math.Vector3f;
|
import com.jme3.math.Vector3f;
|
||||||
import com.jme3.renderer.Camera;
|
import com.jme3.renderer.Camera;
|
||||||
import com.jme3.scene.Spatial;
|
import com.jme3.scene.Spatial;
|
||||||
@ -53,9 +55,35 @@ public class DirectionalLight extends Light {
|
|||||||
|
|
||||||
protected Vector3f direction = new Vector3f(0f, -1f, 0f);
|
protected Vector3f direction = new Vector3f(0f, -1f, 0f);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a DirectionalLight
|
||||||
|
*/
|
||||||
|
public DirectionalLight() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a DirectionalLight with the given direction
|
||||||
|
* @param direction the light's direction
|
||||||
|
*/
|
||||||
|
public DirectionalLight(Vector3f direction) {
|
||||||
|
setDirection(direction);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a DirectionalLight with the given direction and the given color
|
||||||
|
* @param direction the light's direction
|
||||||
|
* @param color the light's color
|
||||||
|
*/
|
||||||
|
public DirectionalLight(Vector3f direction, ColorRGBA color) {
|
||||||
|
super(color);
|
||||||
|
setDirection(direction);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void computeLastDistance(Spatial owner) {
|
public void computeLastDistance(Spatial owner) {
|
||||||
lastDistance = 0; // directional lights are always closest to their owner
|
// directional lights are after ambient lights
|
||||||
|
// but before all other lights.
|
||||||
|
lastDistance = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -77,7 +105,7 @@ public class DirectionalLight extends Light {
|
|||||||
*
|
*
|
||||||
* @param dir the direction of the light.
|
* @param dir the direction of the light.
|
||||||
*/
|
*/
|
||||||
public void setDirection(Vector3f dir){
|
public final void setDirection(Vector3f dir){
|
||||||
direction.set(dir);
|
direction.set(dir);
|
||||||
if (!direction.isUnitVector()) {
|
if (!direction.isUnitVector()) {
|
||||||
direction.normalizeLocal();
|
direction.normalizeLocal();
|
||||||
@ -89,6 +117,11 @@ public class DirectionalLight extends Light {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean intersectsSphere(BoundingSphere sphere, TempVars vars) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean intersectsFrustum(Camera camera, TempVars vars) {
|
public boolean intersectsFrustum(Camera camera, TempVars vars) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
* Copyright (c) 2009-2012, 2015 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,6 +32,7 @@
|
|||||||
package com.jme3.light;
|
package com.jme3.light;
|
||||||
|
|
||||||
import com.jme3.bounding.BoundingBox;
|
import com.jme3.bounding.BoundingBox;
|
||||||
|
import com.jme3.bounding.BoundingSphere;
|
||||||
import com.jme3.export.*;
|
import com.jme3.export.*;
|
||||||
import com.jme3.math.ColorRGBA;
|
import com.jme3.math.ColorRGBA;
|
||||||
import com.jme3.renderer.Camera;
|
import com.jme3.renderer.Camera;
|
||||||
@ -94,7 +95,7 @@ public abstract class Light implements Savable, Cloneable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ColorRGBA color = new ColorRGBA(1f,1f,1f,1f);
|
protected ColorRGBA color = new ColorRGBA(ColorRGBA.White);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used in LightList for caching the distance
|
* Used in LightList for caching the distance
|
||||||
@ -115,6 +116,13 @@ public abstract class Light implements Savable, Cloneable {
|
|||||||
boolean frustumCheckNeeded = true;
|
boolean frustumCheckNeeded = true;
|
||||||
boolean intersectsFrustum = false;
|
boolean intersectsFrustum = false;
|
||||||
|
|
||||||
|
protected Light() {
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Light(ColorRGBA color) {
|
||||||
|
setColor(color);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the color of the light.
|
* Returns the color of the light.
|
||||||
*
|
*
|
||||||
@ -190,7 +198,21 @@ public abstract class Light implements Savable, Cloneable {
|
|||||||
public abstract boolean intersectsBox(BoundingBox box, TempVars vars);
|
public abstract boolean intersectsBox(BoundingBox box, TempVars vars);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines if the lgiht intersects with the given camera frustum.
|
* Determines if the light intersects with the given bounding sphere.
|
||||||
|
* <p>
|
||||||
|
* For non-local lights, such as {@link DirectionalLight directional lights},
|
||||||
|
* {@link AmbientLight ambient lights}, or {@link PointLight point lights}
|
||||||
|
* without influence radius, this method should always return true.
|
||||||
|
*
|
||||||
|
* @param sphere The sphere to check intersection against.
|
||||||
|
* @param vars TempVars in case it is needed.
|
||||||
|
*
|
||||||
|
* @return True if the light intersects the sphere, false otherwise.
|
||||||
|
*/
|
||||||
|
public abstract boolean intersectsSphere(BoundingSphere sphere, TempVars vars);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if the light intersects with the given camera frustum.
|
||||||
*
|
*
|
||||||
* For non-local lights, such as {@link DirectionalLight directional lights},
|
* For non-local lights, such as {@link DirectionalLight directional lights},
|
||||||
* {@link AmbientLight ambient lights}, or {@link PointLight point lights}
|
* {@link AmbientLight ambient lights}, or {@link PointLight point lights}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
* Copyright (c) 2009-2012, 2015 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,12 +34,13 @@ package com.jme3.light;
|
|||||||
import com.jme3.bounding.BoundingBox;
|
import com.jme3.bounding.BoundingBox;
|
||||||
import com.jme3.bounding.BoundingSphere;
|
import com.jme3.bounding.BoundingSphere;
|
||||||
import com.jme3.bounding.BoundingVolume;
|
import com.jme3.bounding.BoundingVolume;
|
||||||
|
import com.jme3.bounding.Intersection;
|
||||||
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.export.OutputCapsule;
|
||||||
import com.jme3.math.FastMath;
|
import com.jme3.math.FastMath;
|
||||||
import com.jme3.math.Plane;
|
import com.jme3.math.ColorRGBA;
|
||||||
import com.jme3.math.Vector3f;
|
import com.jme3.math.Vector3f;
|
||||||
import com.jme3.renderer.Camera;
|
import com.jme3.renderer.Camera;
|
||||||
import com.jme3.scene.Spatial;
|
import com.jme3.scene.Spatial;
|
||||||
@ -62,6 +63,52 @@ public class PointLight extends Light {
|
|||||||
protected float radius = 0;
|
protected float radius = 0;
|
||||||
protected float invRadius = 0;
|
protected float invRadius = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a PointLight
|
||||||
|
*/
|
||||||
|
public PointLight() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a PointLight at the given position
|
||||||
|
* @param position the position in world space
|
||||||
|
*/
|
||||||
|
public PointLight(Vector3f position) {
|
||||||
|
setPosition(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a PointLight at the given position and with the given color
|
||||||
|
* @param position the position in world space
|
||||||
|
* @param color the light color
|
||||||
|
*/
|
||||||
|
public PointLight(Vector3f position, ColorRGBA color) {
|
||||||
|
super(color);
|
||||||
|
setPosition(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a PointLight at the given position, with the given color and the
|
||||||
|
* given radius
|
||||||
|
* @param position the position in world space
|
||||||
|
* @param color the light color
|
||||||
|
* @param radius the light radius
|
||||||
|
*/
|
||||||
|
public PointLight(Vector3f position, ColorRGBA color, float radius) {
|
||||||
|
this(position, color);
|
||||||
|
setRadius(radius);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a PointLight at the given position, with the given radius
|
||||||
|
* @param position the position in world space
|
||||||
|
* @param radius the light radius
|
||||||
|
*/
|
||||||
|
public PointLight(Vector3f position, float radius) {
|
||||||
|
this(position);
|
||||||
|
setRadius(radius);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void computeLastDistance(Spatial owner) {
|
public void computeLastDistance(Spatial owner) {
|
||||||
if (owner.getWorldBound() != null) {
|
if (owner.getWorldBound() != null) {
|
||||||
@ -88,7 +135,7 @@ public class PointLight extends Light {
|
|||||||
*
|
*
|
||||||
* @param position the world space position of the light.
|
* @param position the world space position of the light.
|
||||||
*/
|
*/
|
||||||
public void setPosition(Vector3f position) {
|
public final void setPosition(Vector3f position) {
|
||||||
this.position.set(position);
|
this.position.set(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,13 +162,13 @@ public class PointLight extends Light {
|
|||||||
*
|
*
|
||||||
* @throws IllegalArgumentException If radius is negative
|
* @throws IllegalArgumentException If radius is negative
|
||||||
*/
|
*/
|
||||||
public void setRadius(float radius) {
|
public final void setRadius(float radius) {
|
||||||
if (radius < 0) {
|
if (radius < 0) {
|
||||||
throw new IllegalArgumentException("Light radius cannot be negative");
|
throw new IllegalArgumentException("Light radius cannot be negative");
|
||||||
}
|
}
|
||||||
this.radius = radius;
|
this.radius = radius;
|
||||||
if (radius != 0) {
|
if (radius != 0f) {
|
||||||
this.invRadius = 1 / radius;
|
this.invRadius = 1f / radius;
|
||||||
} else {
|
} else {
|
||||||
this.invRadius = 0;
|
this.invRadius = 0;
|
||||||
}
|
}
|
||||||
@ -146,9 +193,17 @@ public class PointLight extends Light {
|
|||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
// Sphere v. box collision
|
// Sphere v. box collision
|
||||||
return FastMath.abs(box.getCenter().x - position.x) < radius + box.getXExtent()
|
return Intersection.intersect(box, position, radius);
|
||||||
&& FastMath.abs(box.getCenter().y - position.y) < radius + box.getYExtent()
|
}
|
||||||
&& FastMath.abs(box.getCenter().z - position.z) < radius + box.getZExtent();
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean intersectsSphere(BoundingSphere sphere, TempVars vars) {
|
||||||
|
if (this.radius == 0) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
// Sphere v. sphere collision
|
||||||
|
return Intersection.intersect(sphere, position, radius);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
* Copyright (c) 2009-2012, 2015 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,8 +32,11 @@
|
|||||||
package com.jme3.light;
|
package com.jme3.light;
|
||||||
|
|
||||||
import com.jme3.bounding.BoundingBox;
|
import com.jme3.bounding.BoundingBox;
|
||||||
|
import com.jme3.bounding.BoundingSphere;
|
||||||
import com.jme3.bounding.BoundingVolume;
|
import com.jme3.bounding.BoundingVolume;
|
||||||
|
import com.jme3.bounding.Intersection;
|
||||||
import com.jme3.export.*;
|
import com.jme3.export.*;
|
||||||
|
import com.jme3.math.ColorRGBA;
|
||||||
import com.jme3.math.FastMath;
|
import com.jme3.math.FastMath;
|
||||||
import com.jme3.math.Plane;
|
import com.jme3.math.Plane;
|
||||||
import com.jme3.math.Vector3f;
|
import com.jme3.math.Vector3f;
|
||||||
@ -44,16 +47,16 @@ import java.io.IOException;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a spot light.
|
* Represents a spot light.
|
||||||
* A spot light emmit a cone of light from a position and in a direction.
|
* A spot light emits a cone of light from a position and in a direction.
|
||||||
* It can be used to fake torch lights or car's lights.
|
* It can be used to fake torch lights or cars' lights.
|
||||||
* <p>
|
* <p>
|
||||||
* In addition to a position and a direction, spot lights also have a range which
|
* In addition to a position and a direction, spot lights also have a range 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.
|
||||||
* Also the angle of the cone can be tweaked by changing the spot inner angle and the spot outer angle.
|
* Also the angle of the cone can be tweaked by changing the spot inner angle and the spot outer angle.
|
||||||
* the spot inner angle determin the cone of light where light has full influence.
|
* the spot inner angle determines the cone of light where light has full influence.
|
||||||
* the spot outer angle determin the cone global cone of light of the spot light.
|
* the spot outer angle determines the cone global cone of light of the spot light.
|
||||||
* the light intensity slowly decrease between the inner cone and the outer cone.
|
* the light intensity slowly decreases between the inner cone and the outer cone.
|
||||||
* @author Nehon
|
* @author Nehon
|
||||||
*/
|
*/
|
||||||
public class SpotLight extends Light {
|
public class SpotLight extends Light {
|
||||||
@ -69,11 +72,96 @@ public class SpotLight extends Light {
|
|||||||
protected float outerAngleCosSqr, outerAngleSinSqr;
|
protected float outerAngleCosSqr, outerAngleSinSqr;
|
||||||
protected float outerAngleSinRcp, outerAngleSin, outerAngleCos;
|
protected float outerAngleSinRcp, outerAngleSin, outerAngleCos;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a SpotLight.
|
||||||
|
*/
|
||||||
public SpotLight() {
|
public SpotLight() {
|
||||||
super();
|
super();
|
||||||
computeAngleParameters();
|
computeAngleParameters();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a SpotLight at the given position and with the given direction.
|
||||||
|
* @param position the position in world space.
|
||||||
|
* @param direction the direction of the light.
|
||||||
|
*/
|
||||||
|
public SpotLight(Vector3f position, Vector3f direction) {
|
||||||
|
this();
|
||||||
|
setPosition(position);
|
||||||
|
setDirection(direction);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a SpotLight at the given position, with the given direction, and the
|
||||||
|
* given range.
|
||||||
|
* @param position the position in world space.
|
||||||
|
* @param direction the direction of the light.
|
||||||
|
* @param range the spot light range
|
||||||
|
*/
|
||||||
|
public SpotLight(Vector3f position, Vector3f direction, float range) {
|
||||||
|
this();
|
||||||
|
setPosition(position);
|
||||||
|
setDirection(direction);
|
||||||
|
this.spotRange = range;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a SpotLight at the given position, with the given direction and
|
||||||
|
* the given color.
|
||||||
|
* @param position the position in world space.
|
||||||
|
* @param direction the direction of the light.
|
||||||
|
* @param color the light's color.
|
||||||
|
*/
|
||||||
|
public SpotLight(Vector3f position, Vector3f direction, ColorRGBA color) {
|
||||||
|
super(color);
|
||||||
|
computeAngleParameters();
|
||||||
|
setPosition(position);
|
||||||
|
setDirection(direction);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a SpotLight at the given position, with the given direction,
|
||||||
|
* the given range and the given color.
|
||||||
|
* @param position the position in world space.
|
||||||
|
* @param direction the direction of the light.
|
||||||
|
* @param range the spot light range
|
||||||
|
* @param color the light's color.
|
||||||
|
*/
|
||||||
|
public SpotLight(Vector3f position, Vector3f direction, float range, ColorRGBA color) {
|
||||||
|
super(color);
|
||||||
|
computeAngleParameters();
|
||||||
|
setPosition(position);
|
||||||
|
setDirection(direction);
|
||||||
|
this.spotRange = range;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a SpotLight at the given position, with the given direction,
|
||||||
|
* the given color and the given inner and outer angles
|
||||||
|
* (controls the falloff of the light)
|
||||||
|
*
|
||||||
|
* @param position the position in world space.
|
||||||
|
* @param direction the direction of the light.
|
||||||
|
* @param range the spot light range
|
||||||
|
* @param color the light's color.
|
||||||
|
* @param innerAngle the inner angle of the spot light.
|
||||||
|
* @param outerAngle the outer angle of the spot light.
|
||||||
|
*
|
||||||
|
* @see SpotLight#setSpotInnerAngle(float)
|
||||||
|
* @see SpotLight#setSpotOuterAngle(float)
|
||||||
|
*/
|
||||||
|
public SpotLight(Vector3f position, Vector3f direction, float range, ColorRGBA color, float innerAngle, float outerAngle) {
|
||||||
|
super(color);
|
||||||
|
this.spotInnerAngle = innerAngle;
|
||||||
|
this.spotOuterAngle = outerAngle;
|
||||||
|
computeAngleParameters();
|
||||||
|
setPosition(position);
|
||||||
|
setDirection(direction);
|
||||||
|
this.spotRange = range;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void computeAngleParameters() {
|
private void computeAngleParameters() {
|
||||||
float innerCos = FastMath.cos(spotInnerAngle);
|
float innerCos = FastMath.cos(spotInnerAngle);
|
||||||
outerAngleCos = FastMath.cos(spotOuterAngle);
|
outerAngleCos = FastMath.cos(spotOuterAngle);
|
||||||
@ -102,9 +190,7 @@ public class SpotLight extends Light {
|
|||||||
if (this.spotRange > 0f) {
|
if (this.spotRange > 0f) {
|
||||||
// Check spot range first.
|
// Check spot range first.
|
||||||
// Sphere v. box collision
|
// Sphere v. box collision
|
||||||
if (FastMath.abs(box.getCenter().x - position.x) >= spotRange + box.getXExtent()
|
if (!Intersection.intersect(box, position, spotRange)) {
|
||||||
|| FastMath.abs(box.getCenter().y - position.y) >= spotRange + box.getYExtent()
|
|
||||||
|| FastMath.abs(box.getCenter().z - position.z) >= spotRange + box.getZExtent()) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -140,8 +226,48 @@ public class SpotLight extends Light {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean intersectsFrustum(Camera cam, TempVars vars) {
|
public boolean intersectsSphere(BoundingSphere sphere, TempVars vars) {
|
||||||
|
if (this.spotRange > 0f) {
|
||||||
|
// Check spot range first.
|
||||||
|
// Sphere v. sphere collision
|
||||||
|
if (!Intersection.intersect(sphere, position, spotRange)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float otherRadiusSquared = FastMath.sqr(sphere.getRadius());
|
||||||
|
float otherRadius = sphere.getRadius();
|
||||||
|
|
||||||
|
// Check if sphere is within spot angle.
|
||||||
|
// Cone v. sphere collision.
|
||||||
|
Vector3f E = direction.mult(otherRadius * outerAngleSinRcp, vars.vect1);
|
||||||
|
Vector3f U = position.subtract(E, vars.vect2);
|
||||||
|
Vector3f D = sphere.getCenter().subtract(U, vars.vect3);
|
||||||
|
|
||||||
|
float dsqr = D.dot(D);
|
||||||
|
float e = direction.dot(D);
|
||||||
|
|
||||||
|
if (e > 0f && e * e >= dsqr * outerAngleCosSqr) {
|
||||||
|
D = sphere.getCenter().subtract(position, vars.vect3);
|
||||||
|
dsqr = D.dot(D);
|
||||||
|
e = -direction.dot(D);
|
||||||
|
|
||||||
|
if (e > 0f && e * e >= dsqr * outerAngleSinSqr) {
|
||||||
|
return dsqr <= otherRadiusSquared;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean intersectsFrustum(Camera cam, TempVars vars) {
|
||||||
|
if (spotRange == 0) {
|
||||||
|
// The algorithm below does not support infinite spot range.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
Vector3f farPoint = vars.vect1.set(position).addLocal(vars.vect2.set(direction).multLocal(spotRange));
|
Vector3f farPoint = vars.vect1.set(position).addLocal(vars.vect2.set(direction).multLocal(spotRange));
|
||||||
for (int i = 5; i >= 0; i--) {
|
for (int i = 5; i >= 0; i--) {
|
||||||
//check origin against the plane
|
//check origin against the plane
|
||||||
@ -189,7 +315,7 @@ public class SpotLight extends Light {
|
|||||||
return direction;
|
return direction;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDirection(Vector3f direction) {
|
public final void setDirection(Vector3f direction) {
|
||||||
this.direction.set(direction);
|
this.direction.set(direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -197,7 +323,7 @@ public class SpotLight extends Light {
|
|||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPosition(Vector3f position) {
|
public final void setPosition(Vector3f position) {
|
||||||
this.position.set(position);
|
this.position.set(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1147,11 +1147,12 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
|
|||||||
*/
|
*/
|
||||||
public void render(Geometry geom, LightList lights, RenderManager rm) {
|
public void render(Geometry geom, LightList lights, RenderManager rm) {
|
||||||
autoSelectTechnique(rm);
|
autoSelectTechnique(rm);
|
||||||
|
TechniqueDef techDef = technique.getDef();
|
||||||
|
|
||||||
|
if (techDef.isNoRender()) return;
|
||||||
|
|
||||||
Renderer r = rm.getRenderer();
|
Renderer r = rm.getRenderer();
|
||||||
|
|
||||||
TechniqueDef techDef = technique.getDef();
|
|
||||||
|
|
||||||
if (rm.getForcedRenderState() != null) {
|
if (rm.getForcedRenderState() != null) {
|
||||||
r.applyRenderState(rm.getForcedRenderState());
|
r.applyRenderState(rm.getForcedRenderState());
|
||||||
} else {
|
} else {
|
||||||
|
@ -102,6 +102,7 @@ public class TechniqueDef implements Savable {
|
|||||||
private List<ShaderNode> shaderNodes;
|
private List<ShaderNode> shaderNodes;
|
||||||
private ShaderGenerationInfo shaderGenerationInfo;
|
private ShaderGenerationInfo shaderGenerationInfo;
|
||||||
|
|
||||||
|
private boolean noRender = false;
|
||||||
private RenderState renderState;
|
private RenderState renderState;
|
||||||
private RenderState forcedRenderState;
|
private RenderState forcedRenderState;
|
||||||
|
|
||||||
@ -201,6 +202,28 @@ public class TechniqueDef implements Savable {
|
|||||||
this.renderState = renderState;
|
this.renderState = renderState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets if this technique should not be used to render.
|
||||||
|
*
|
||||||
|
* @param noRender not render or render ?
|
||||||
|
*
|
||||||
|
* @see NoRender
|
||||||
|
*/
|
||||||
|
public void setNoRender(boolean noRender) {
|
||||||
|
this.noRender = noRender;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if this technique should not be used to render.
|
||||||
|
* (eg. to not render a material with default technique)
|
||||||
|
*
|
||||||
|
* @return true if this technique should not be rendered, false otherwise.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public boolean isNoRender(){
|
||||||
|
return noRender;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated jME3 always requires shaders now
|
* @deprecated jME3 always requires shaders now
|
||||||
*/
|
*/
|
||||||
@ -448,6 +471,7 @@ public class TechniqueDef implements Savable {
|
|||||||
oc.write(lightMode, "lightMode", LightMode.Disable);
|
oc.write(lightMode, "lightMode", LightMode.Disable);
|
||||||
oc.write(shadowMode, "shadowMode", ShadowMode.Disable);
|
oc.write(shadowMode, "shadowMode", ShadowMode.Disable);
|
||||||
oc.write(renderState, "renderState", null);
|
oc.write(renderState, "renderState", null);
|
||||||
|
oc.write(noRender, "noRender", false);
|
||||||
oc.write(usesNodes, "usesNodes", false);
|
oc.write(usesNodes, "usesNodes", false);
|
||||||
oc.writeSavableArrayList((ArrayList)shaderNodes,"shaderNodes", null);
|
oc.writeSavableArrayList((ArrayList)shaderNodes,"shaderNodes", null);
|
||||||
oc.write(shaderGenerationInfo, "shaderGenerationInfo", null);
|
oc.write(shaderGenerationInfo, "shaderGenerationInfo", null);
|
||||||
@ -470,6 +494,7 @@ public class TechniqueDef implements Savable {
|
|||||||
lightMode = ic.readEnum("lightMode", LightMode.class, LightMode.Disable);
|
lightMode = ic.readEnum("lightMode", LightMode.class, LightMode.Disable);
|
||||||
shadowMode = ic.readEnum("shadowMode", ShadowMode.class, ShadowMode.Disable);
|
shadowMode = ic.readEnum("shadowMode", ShadowMode.class, ShadowMode.Disable);
|
||||||
renderState = (RenderState) ic.readSavable("renderState", null);
|
renderState = (RenderState) ic.readSavable("renderState", null);
|
||||||
|
noRender = ic.readBoolean("noRender", false);
|
||||||
|
|
||||||
if (ic.getSavableVersion(TechniqueDef.class) == 0) {
|
if (ic.getSavableVersion(TechniqueDef.class) == 0) {
|
||||||
// Old version
|
// Old version
|
||||||
@ -525,6 +550,6 @@ public class TechniqueDef implements Savable {
|
|||||||
//todo: make toString return something usefull
|
//todo: make toString return something usefull
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "TechniqueDef{" + "requiredCaps=" + requiredCaps + ", name=" + name /*+ ", vertName=" + vertName + ", fragName=" + fragName + ", vertLanguage=" + vertLanguage + ", fragLanguage=" + fragLanguage */+ ", presetDefines=" + presetDefines + ", usesNodes=" + usesNodes + ", shaderNodes=" + shaderNodes + ", shaderGenerationInfo=" + shaderGenerationInfo + ", renderState=" + renderState + ", forcedRenderState=" + forcedRenderState + ", lightMode=" + lightMode + ", shadowMode=" + shadowMode + ", defineParams=" + defineParams + ", worldBinds=" + worldBinds + '}';
|
return "TechniqueDef{" + "requiredCaps=" + requiredCaps + ", name=" + name /*+ ", vertName=" + vertName + ", fragName=" + fragName + ", vertLanguage=" + vertLanguage + ", fragLanguage=" + fragLanguage */+ ", presetDefines=" + presetDefines + ", usesNodes=" + usesNodes + ", shaderNodes=" + shaderNodes + ", shaderGenerationInfo=" + shaderGenerationInfo + ", renderState=" + renderState + ", forcedRenderState=" + forcedRenderState + ", lightMode=" + lightMode + ", shadowMode=" + shadowMode + ", defineParams=" + defineParams + ", worldBinds=" + worldBinds + ", noRender=" + noRender + '}';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -87,8 +87,25 @@ final public class FastMath {
|
|||||||
return (number > 0) && (number & (number - 1)) == 0;
|
return (number > 0) && (number & (number - 1)) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the next power of two of the given number.
|
||||||
|
*
|
||||||
|
* E.g. for an input 100, this returns 128.
|
||||||
|
* Returns 1 for all numbers <= 1.
|
||||||
|
*
|
||||||
|
* @param number The number to obtain the POT for.
|
||||||
|
* @return The next power of two.
|
||||||
|
*/
|
||||||
public static int nearestPowerOfTwo(int number) {
|
public static int nearestPowerOfTwo(int number) {
|
||||||
return (int) Math.pow(2, Math.ceil(Math.log(number) / Math.log(2)));
|
number--;
|
||||||
|
number |= number >> 1;
|
||||||
|
number |= number >> 2;
|
||||||
|
number |= number >> 4;
|
||||||
|
number |= number >> 8;
|
||||||
|
number |= number >> 16;
|
||||||
|
number++;
|
||||||
|
number += (number == 0) ? 1 : 0;
|
||||||
|
return number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -154,53 +154,34 @@ public final class Matrix4f implements Savable, Cloneable, java.io.Serializable
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void fromFrame(Vector3f location, Vector3f direction, Vector3f up, Vector3f left) {
|
public void fromFrame(Vector3f location, Vector3f direction, Vector3f up, Vector3f left) {
|
||||||
loadIdentity();
|
|
||||||
|
|
||||||
TempVars vars = TempVars.get();
|
TempVars vars = TempVars.get();
|
||||||
|
try {
|
||||||
|
Vector3f fwdVector = vars.vect1.set(direction);
|
||||||
|
Vector3f leftVector = vars.vect2.set(fwdVector).crossLocal(up);
|
||||||
|
Vector3f upVector = vars.vect3.set(leftVector).crossLocal(fwdVector);
|
||||||
|
|
||||||
Vector3f f = vars.vect1.set(direction);
|
m00 = leftVector.x;
|
||||||
Vector3f s = vars.vect2.set(f).crossLocal(up);
|
m01 = leftVector.y;
|
||||||
Vector3f u = vars.vect3.set(s).crossLocal(f);
|
m02 = leftVector.z;
|
||||||
// s.normalizeLocal();
|
m03 = -leftVector.dot(location);
|
||||||
// u.normalizeLocal();
|
|
||||||
|
|
||||||
m00 = s.x;
|
m10 = upVector.x;
|
||||||
m01 = s.y;
|
m11 = upVector.y;
|
||||||
m02 = s.z;
|
m12 = upVector.z;
|
||||||
|
m13 = -upVector.dot(location);
|
||||||
|
|
||||||
m10 = u.x;
|
m20 = -fwdVector.x;
|
||||||
m11 = u.y;
|
m21 = -fwdVector.y;
|
||||||
m12 = u.z;
|
m22 = -fwdVector.z;
|
||||||
|
m23 = fwdVector.dot(location);
|
||||||
m20 = -f.x;
|
|
||||||
m21 = -f.y;
|
|
||||||
m22 = -f.z;
|
|
||||||
|
|
||||||
// m00 = -left.x;
|
|
||||||
// m10 = -left.y;
|
|
||||||
// m20 = -left.z;
|
|
||||||
//
|
|
||||||
// m01 = up.x;
|
|
||||||
// m11 = up.y;
|
|
||||||
// m21 = up.z;
|
|
||||||
//
|
|
||||||
// m02 = -direction.x;
|
|
||||||
// m12 = -direction.y;
|
|
||||||
// m22 = -direction.z;
|
|
||||||
//
|
|
||||||
|
|
||||||
Matrix4f transMatrix = vars.tempMat4;
|
|
||||||
transMatrix.loadIdentity();
|
|
||||||
transMatrix.m03 = -location.x;
|
|
||||||
transMatrix.m13 = -location.y;
|
|
||||||
transMatrix.m23 = -location.z;
|
|
||||||
this.multLocal(transMatrix);
|
|
||||||
|
|
||||||
|
m30 = 0f;
|
||||||
|
m31 = 0f;
|
||||||
|
m32 = 0f;
|
||||||
|
m33 = 1f;
|
||||||
|
} finally {
|
||||||
vars.release();
|
vars.release();
|
||||||
|
}
|
||||||
// transMatrix.multLocal(this);
|
|
||||||
|
|
||||||
// set(transMatrix);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -288,6 +288,29 @@ public final class Transform implements Savable, Cloneable, java.io.Serializable
|
|||||||
rot.set(0, 0, 0, 1);
|
rot.set(0, 0, 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int hash = 7;
|
||||||
|
hash = 89 * hash + rot.hashCode();
|
||||||
|
hash = 89 * hash + translation.hashCode();
|
||||||
|
hash = 89 * hash + scale.hashCode();
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (obj == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (getClass() != obj.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final Transform other = (Transform) obj;
|
||||||
|
return this.translation.equals(other.translation)
|
||||||
|
&& this.scale.equals(other.scale)
|
||||||
|
&& this.rot.equals(other.rot);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString(){
|
public String toString(){
|
||||||
return getClass().getSimpleName() + "[ " + translation.x + ", " + translation.y + ", " + translation.z + "]\n"
|
return getClass().getSimpleName() + "[ " + translation.x + ", " + translation.y + ", " + translation.z + "]\n"
|
||||||
@ -307,22 +330,21 @@ public final class Transform implements Savable, Cloneable, java.io.Serializable
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void write(JmeExporter e) throws IOException {
|
public void write(JmeExporter e) throws IOException {
|
||||||
OutputCapsule capsule = e.getCapsule(this);
|
OutputCapsule capsule = e.getCapsule(this);
|
||||||
capsule.write(rot, "rot", new Quaternion());
|
capsule.write(rot, "rot", Quaternion.IDENTITY);
|
||||||
capsule.write(translation, "translation", Vector3f.ZERO);
|
capsule.write(translation, "translation", Vector3f.ZERO);
|
||||||
capsule.write(scale, "scale", Vector3f.UNIT_XYZ);
|
capsule.write(scale, "scale", Vector3f.UNIT_XYZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void read(JmeImporter e) throws IOException {
|
public void read(JmeImporter e) throws IOException {
|
||||||
InputCapsule capsule = e.getCapsule(this);
|
InputCapsule capsule = e.getCapsule(this);
|
||||||
|
|
||||||
rot = (Quaternion)capsule.readSavable("rot", new Quaternion());
|
rot.set((Quaternion)capsule.readSavable("rot", Quaternion.IDENTITY));
|
||||||
translation = (Vector3f)capsule.readSavable("translation", null);
|
translation.set((Vector3f)capsule.readSavable("translation", Vector3f.ZERO));
|
||||||
if( translation == null ) {
|
scale.set((Vector3f)capsule.readSavable("scale", Vector3f.UNIT_XYZ));
|
||||||
translation = new Vector3f();
|
|
||||||
}
|
|
||||||
scale = (Vector3f)capsule.readSavable("scale", Vector3f.UNIT_XYZ);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -409,6 +409,19 @@ public abstract class Filter implements Savable {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override this method and return true if you want the scene (input) texture
|
||||||
|
* to use bilinear filtering or false to use nearest filtering.
|
||||||
|
*
|
||||||
|
* Typically filters that perform samples <em>in between</em> pixels
|
||||||
|
* should enable filtering.
|
||||||
|
*
|
||||||
|
* @return true to use linear filtering, false to use nearest filtering.
|
||||||
|
*/
|
||||||
|
protected boolean isRequiresBilinear() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* returns the list of the postRender passes
|
* returns the list of the postRender passes
|
||||||
* @return
|
* @return
|
||||||
|
@ -38,6 +38,7 @@ import com.jme3.renderer.*;
|
|||||||
import com.jme3.renderer.queue.RenderQueue;
|
import com.jme3.renderer.queue.RenderQueue;
|
||||||
import com.jme3.texture.FrameBuffer;
|
import com.jme3.texture.FrameBuffer;
|
||||||
import com.jme3.texture.Image.Format;
|
import com.jme3.texture.Image.Format;
|
||||||
|
import com.jme3.texture.Texture;
|
||||||
import com.jme3.texture.Texture2D;
|
import com.jme3.texture.Texture2D;
|
||||||
import com.jme3.ui.Picture;
|
import com.jme3.ui.Picture;
|
||||||
import com.jme3.util.SafeArrayList;
|
import com.jme3.util.SafeArrayList;
|
||||||
@ -285,6 +286,12 @@ public class FilterPostProcessor implements SceneProcessor, Savable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean wantsBilinear = filter.isRequiresBilinear();
|
||||||
|
if (wantsBilinear) {
|
||||||
|
tex.setMagFilter(Texture.MagFilter.Bilinear);
|
||||||
|
tex.setMinFilter(Texture.MinFilter.BilinearNoMipMaps);
|
||||||
|
}
|
||||||
|
|
||||||
buff = outputBuffer;
|
buff = outputBuffer;
|
||||||
if (i != lastFilterIndex) {
|
if (i != lastFilterIndex) {
|
||||||
buff = filter.getRenderFrameBuffer();
|
buff = filter.getRenderFrameBuffer();
|
||||||
@ -293,6 +300,11 @@ public class FilterPostProcessor implements SceneProcessor, Savable {
|
|||||||
}
|
}
|
||||||
renderProcessing(r, buff, mat);
|
renderProcessing(r, buff, mat);
|
||||||
filter.postFilter(r, buff);
|
filter.postFilter(r, buff);
|
||||||
|
|
||||||
|
if (wantsBilinear) {
|
||||||
|
tex.setMagFilter(Texture.MagFilter.Nearest);
|
||||||
|
tex.setMinFilter(Texture.MinFilter.NearestNoMipMaps);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -300,7 +312,7 @@ public class FilterPostProcessor implements SceneProcessor, Savable {
|
|||||||
public void postFrame(FrameBuffer out) {
|
public void postFrame(FrameBuffer out) {
|
||||||
|
|
||||||
FrameBuffer sceneBuffer = renderFrameBuffer;
|
FrameBuffer sceneBuffer = renderFrameBuffer;
|
||||||
if (renderFrameBufferMS != null && !renderer.getCaps().contains(Caps.OpenGL31)) {
|
if (renderFrameBufferMS != null && !renderer.getCaps().contains(Caps.OpenGL32)) {
|
||||||
renderer.copyFrameBuffer(renderFrameBufferMS, renderFrameBuffer, true);
|
renderer.copyFrameBuffer(renderFrameBufferMS, renderFrameBuffer, true);
|
||||||
} else if (renderFrameBufferMS != null) {
|
} else if (renderFrameBufferMS != null) {
|
||||||
sceneBuffer = renderFrameBufferMS;
|
sceneBuffer = renderFrameBufferMS;
|
||||||
@ -443,7 +455,7 @@ public class FilterPostProcessor implements SceneProcessor, Savable {
|
|||||||
//antialiasing on filters only supported in opengl 3 due to depth read problem
|
//antialiasing on filters only supported in opengl 3 due to depth read problem
|
||||||
if (numSamples > 1 && caps.contains(Caps.FrameBufferMultisample)) {
|
if (numSamples > 1 && caps.contains(Caps.FrameBufferMultisample)) {
|
||||||
renderFrameBufferMS = new FrameBuffer(width, height, numSamples);
|
renderFrameBufferMS = new FrameBuffer(width, height, numSamples);
|
||||||
if (caps.contains(Caps.OpenGL31)) {
|
if (caps.contains(Caps.OpenGL32)) {
|
||||||
Texture2D msColor = new Texture2D(width, height, numSamples, fbFormat);
|
Texture2D msColor = new Texture2D(width, height, numSamples, fbFormat);
|
||||||
Texture2D msDepth = new Texture2D(width, height, numSamples, Format.Depth);
|
Texture2D msDepth = new Texture2D(width, height, numSamples, Format.Depth);
|
||||||
renderFrameBufferMS.setDepthTexture(msDepth);
|
renderFrameBufferMS.setDepthTexture(msDepth);
|
||||||
@ -456,7 +468,7 @@ public class FilterPostProcessor implements SceneProcessor, Savable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (numSamples <= 1 || !caps.contains(Caps.OpenGL31)) {
|
if (numSamples <= 1 || !caps.contains(Caps.OpenGL32)) {
|
||||||
renderFrameBuffer = new FrameBuffer(width, height, 1);
|
renderFrameBuffer = new FrameBuffer(width, height, 1);
|
||||||
renderFrameBuffer.setDepthBuffer(Format.Depth);
|
renderFrameBuffer.setDepthBuffer(Format.Depth);
|
||||||
filterTexture = new Texture2D(width, height, fbFormat);
|
filterTexture = new Texture2D(width, height, fbFormat);
|
||||||
|
@ -77,4 +77,6 @@ public enum Limits {
|
|||||||
DepthTextureSamples,
|
DepthTextureSamples,
|
||||||
|
|
||||||
VertexUniformVectors,
|
VertexUniformVectors,
|
||||||
|
|
||||||
|
TextureAnisotropy,
|
||||||
}
|
}
|
||||||
|
@ -241,12 +241,12 @@ public class RenderContext {
|
|||||||
public IDList attribIndexList = new IDList();
|
public IDList attribIndexList = new IDList();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* depth tets function
|
* depth test function
|
||||||
*/
|
*/
|
||||||
public RenderState.TestFunction depthFunc = RenderState.TestFunction.LessOrEqual;
|
public RenderState.TestFunction depthFunc = RenderState.TestFunction.Less;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* alpha tets function
|
* alpha test function
|
||||||
*/
|
*/
|
||||||
public RenderState.TestFunction alphaFunc = RenderState.TestFunction.Greater;
|
public RenderState.TestFunction alphaFunc = RenderState.TestFunction.Greater;
|
||||||
|
|
||||||
@ -255,8 +255,6 @@ public class RenderContext {
|
|||||||
|
|
||||||
public ColorRGBA clearColor = new ColorRGBA(0,0,0,0);
|
public ColorRGBA clearColor = new ColorRGBA(0,0,0,0);
|
||||||
|
|
||||||
public boolean seamlessCubemap = false;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reset the RenderContext to default GL state
|
* Reset the RenderContext to default GL state
|
||||||
*/
|
*/
|
||||||
@ -308,6 +306,5 @@ public class RenderContext {
|
|||||||
depthFunc = RenderState.TestFunction.LessOrEqual;
|
depthFunc = RenderState.TestFunction.LessOrEqual;
|
||||||
alphaFunc = RenderState.TestFunction.Greater;
|
alphaFunc = RenderState.TestFunction.Greater;
|
||||||
clearColor.set(0,0,0,0);
|
clearColor.set(0,0,0,0);
|
||||||
seamlessCubemap = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -746,27 +746,43 @@ public class RenderManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the light filter to use when rendering Lighted Geometries
|
* Sets the light filter to use when rendering lit Geometries.
|
||||||
*
|
*
|
||||||
* @see LightFilter
|
* @see LightFilter
|
||||||
* @param lightFilter The light filter tose. Set it to null if you want all lights to be rendered
|
* @param lightFilter The light filter. Set it to null if you want all lights to be rendered.
|
||||||
*/
|
*/
|
||||||
public void setLightFilter(LightFilter lightFilter) {
|
public void setLightFilter(LightFilter lightFilter) {
|
||||||
this.lightFilter = lightFilter;
|
this.lightFilter = lightFilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines what light mode will be selected when a technique offers several light modes.
|
||||||
|
* @param preferredLightMode The light mode to use.
|
||||||
|
*/
|
||||||
public void setPreferredLightMode(TechniqueDef.LightMode preferredLightMode) {
|
public void setPreferredLightMode(TechniqueDef.LightMode preferredLightMode) {
|
||||||
this.preferredLightMode = preferredLightMode;
|
this.preferredLightMode = preferredLightMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the preferred light mode.
|
||||||
|
* @return the light mode.
|
||||||
|
*/
|
||||||
public TechniqueDef.LightMode getPreferredLightMode() {
|
public TechniqueDef.LightMode getPreferredLightMode() {
|
||||||
return preferredLightMode;
|
return preferredLightMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the number of lights used for each pass when the light mode is single pass.
|
||||||
|
* @return the number of lights.
|
||||||
|
*/
|
||||||
public int getSinglePassLightBatchSize() {
|
public int getSinglePassLightBatchSize() {
|
||||||
return singlePassLightBatchSize;
|
return singlePassLightBatchSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the number of lights to use for each pass when the light mode is single pass.
|
||||||
|
* @param singlePassLightBatchSize the number of lights.
|
||||||
|
*/
|
||||||
public void setSinglePassLightBatchSize(int singlePassLightBatchSize) {
|
public void setSinglePassLightBatchSize(int singlePassLightBatchSize) {
|
||||||
this.singlePassLightBatchSize = singlePassLightBatchSize;
|
this.singlePassLightBatchSize = singlePassLightBatchSize;
|
||||||
}
|
}
|
||||||
|
@ -161,6 +161,7 @@ public interface GL {
|
|||||||
public static final int GL_TEXTURE_CUBE_MAP_NEGATIVE_Y = 0x8518;
|
public static final int GL_TEXTURE_CUBE_MAP_NEGATIVE_Y = 0x8518;
|
||||||
public static final int GL_TEXTURE_CUBE_MAP_POSITIVE_Z = 0x8519;
|
public static final int GL_TEXTURE_CUBE_MAP_POSITIVE_Z = 0x8519;
|
||||||
public static final int GL_TEXTURE_CUBE_MAP_NEGATIVE_Z = 0x851A;
|
public static final int GL_TEXTURE_CUBE_MAP_NEGATIVE_Z = 0x851A;
|
||||||
|
public static final int GL_TEXTURE_BASE_LEVEL = 0x813C;
|
||||||
public static final int GL_TEXTURE_MAG_FILTER = 0x2800;
|
public static final int GL_TEXTURE_MAG_FILTER = 0x2800;
|
||||||
public static final int GL_TEXTURE_MAX_LEVEL = 0x813D;
|
public static final int GL_TEXTURE_MAX_LEVEL = 0x813D;
|
||||||
public static final int GL_TEXTURE_MIN_FILTER = 0x2801;
|
public static final int GL_TEXTURE_MIN_FILTER = 0x2801;
|
||||||
|
@ -44,7 +44,7 @@ public interface GL2 extends GL {
|
|||||||
public static final int GL_ALPHA_TEST = 0xBC0;
|
public static final int GL_ALPHA_TEST = 0xBC0;
|
||||||
public static final int GL_BGR = 0x80E0;
|
public static final int GL_BGR = 0x80E0;
|
||||||
public static final int GL_BGRA = 0x80E1;
|
public static final int GL_BGRA = 0x80E1;
|
||||||
public static final int GL_COMPARE_R_TO_TEXTURE = 0x884E;
|
public static final int GL_COMPARE_REF_TO_TEXTURE = 0x884E;
|
||||||
public static final int GL_DEPTH_COMPONENT24 = 0x81A6;
|
public static final int GL_DEPTH_COMPONENT24 = 0x81A6;
|
||||||
public static final int GL_DEPTH_COMPONENT32 = 0x81A7;
|
public static final int GL_DEPTH_COMPONENT32 = 0x81A7;
|
||||||
public static final int GL_DEPTH_TEXTURE_MODE = 0x884B;
|
public static final int GL_DEPTH_TEXTURE_MODE = 0x884B;
|
||||||
|
@ -68,6 +68,7 @@ public interface GLExt {
|
|||||||
public static final int GL_MAX_DEPTH_TEXTURE_SAMPLES = 0x910F;
|
public static final int GL_MAX_DEPTH_TEXTURE_SAMPLES = 0x910F;
|
||||||
public static final int GL_MAX_DRAW_BUFFERS_ARB = 0x8824;
|
public static final int GL_MAX_DRAW_BUFFERS_ARB = 0x8824;
|
||||||
public static final int GL_MAX_SAMPLES_EXT = 0x8D57;
|
public static final int GL_MAX_SAMPLES_EXT = 0x8D57;
|
||||||
|
public static final int GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT = 0x84FF;
|
||||||
public static final int GL_MULTISAMPLE_ARB = 0x809D;
|
public static final int GL_MULTISAMPLE_ARB = 0x809D;
|
||||||
public static final int GL_NUM_PROGRAM_BINARY_FORMATS = 0x87FE;
|
public static final int GL_NUM_PROGRAM_BINARY_FORMATS = 0x87FE;
|
||||||
public static final int GL_PIXEL_PACK_BUFFER_ARB = 0x88EB;
|
public static final int GL_PIXEL_PACK_BUFFER_ARB = 0x88EB;
|
||||||
|
@ -51,7 +51,9 @@ import com.jme3.texture.FrameBuffer;
|
|||||||
import com.jme3.texture.FrameBuffer.RenderBuffer;
|
import com.jme3.texture.FrameBuffer.RenderBuffer;
|
||||||
import com.jme3.texture.Image;
|
import com.jme3.texture.Image;
|
||||||
import com.jme3.texture.Texture;
|
import com.jme3.texture.Texture;
|
||||||
|
import com.jme3.texture.Texture.ShadowCompareMode;
|
||||||
import com.jme3.texture.Texture.WrapAxis;
|
import com.jme3.texture.Texture.WrapAxis;
|
||||||
|
import com.jme3.texture.image.LastTextureState;
|
||||||
import com.jme3.util.BufferUtils;
|
import com.jme3.util.BufferUtils;
|
||||||
import com.jme3.util.ListMap;
|
import com.jme3.util.ListMap;
|
||||||
import com.jme3.util.MipMapGenerator;
|
import com.jme3.util.MipMapGenerator;
|
||||||
@ -68,7 +70,7 @@ import java.util.regex.Matcher;
|
|||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import jme3tools.shader.ShaderDebug;
|
import jme3tools.shader.ShaderDebug;
|
||||||
|
|
||||||
public class GLRenderer implements Renderer {
|
public final class GLRenderer implements Renderer {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(GLRenderer.class.getName());
|
private static final Logger logger = Logger.getLogger(GLRenderer.class.getName());
|
||||||
private static final boolean VALIDATE_SHADER = false;
|
private static final boolean VALIDATE_SHADER = false;
|
||||||
@ -374,15 +376,18 @@ public class GLRenderer implements Renderer {
|
|||||||
|
|
||||||
if (hasExtension("GL_EXT_texture_filter_anisotropic")) {
|
if (hasExtension("GL_EXT_texture_filter_anisotropic")) {
|
||||||
caps.add(Caps.TextureFilterAnisotropic);
|
caps.add(Caps.TextureFilterAnisotropic);
|
||||||
|
limits.put(Limits.TextureAnisotropy, getInteger(GLExt.GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasExtension("GL_EXT_framebuffer_object") || gl3 != null) {
|
if (hasExtension("GL_EXT_framebuffer_object")
|
||||||
|
|| caps.contains(Caps.OpenGL30)
|
||||||
|
|| caps.contains(Caps.OpenGLES20)) {
|
||||||
caps.add(Caps.FrameBuffer);
|
caps.add(Caps.FrameBuffer);
|
||||||
|
|
||||||
limits.put(Limits.RenderBufferSize, getInteger(GLFbo.GL_MAX_RENDERBUFFER_SIZE_EXT));
|
limits.put(Limits.RenderBufferSize, getInteger(GLFbo.GL_MAX_RENDERBUFFER_SIZE_EXT));
|
||||||
limits.put(Limits.FrameBufferAttachments, getInteger(GLFbo.GL_MAX_COLOR_ATTACHMENTS_EXT));
|
limits.put(Limits.FrameBufferAttachments, getInteger(GLFbo.GL_MAX_COLOR_ATTACHMENTS_EXT));
|
||||||
|
|
||||||
if (hasExtension("GL_EXT_framebuffer_blit")) {
|
if (hasExtension("GL_EXT_framebuffer_blit") || caps.contains(Caps.OpenGL30)) {
|
||||||
caps.add(Caps.FrameBufferBlit);
|
caps.add(Caps.FrameBufferBlit);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -401,7 +406,7 @@ public class GLRenderer implements Renderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasExtension("GL_ARB_draw_buffers")) {
|
if (hasExtension("GL_ARB_draw_buffers") || caps.contains(Caps.OpenGL30)) {
|
||||||
limits.put(Limits.FrameBufferMrtAttachments, getInteger(GLExt.GL_MAX_DRAW_BUFFERS_ARB));
|
limits.put(Limits.FrameBufferMrtAttachments, getInteger(GLExt.GL_MAX_DRAW_BUFFERS_ARB));
|
||||||
if (limits.get(Limits.FrameBufferMrtAttachments) > 1) {
|
if (limits.get(Limits.FrameBufferMrtAttachments) > 1) {
|
||||||
caps.add(Caps.FrameBufferMRT);
|
caps.add(Caps.FrameBufferMRT);
|
||||||
@ -502,6 +507,11 @@ public class GLRenderer implements Renderer {
|
|||||||
// Initialize default state..
|
// Initialize default state..
|
||||||
gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1);
|
gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1);
|
||||||
|
|
||||||
|
if (caps.contains(Caps.SeamlessCubemap)) {
|
||||||
|
// Enable this globally. Should be OK.
|
||||||
|
gl.glEnable(GLExt.GL_TEXTURE_CUBE_MAP_SEAMLESS);
|
||||||
|
}
|
||||||
|
|
||||||
if (caps.contains(Caps.CoreProfile)) {
|
if (caps.contains(Caps.CoreProfile)) {
|
||||||
// Core Profile requires VAO to be bound.
|
// Core Profile requires VAO to be bound.
|
||||||
gl3.glGenVertexArrays(intBuf16);
|
gl3.glGenVertexArrays(intBuf16);
|
||||||
@ -607,13 +617,12 @@ public class GLRenderer implements Renderer {
|
|||||||
|
|
||||||
if (state.isDepthTest() && !context.depthTestEnabled) {
|
if (state.isDepthTest() && !context.depthTestEnabled) {
|
||||||
gl.glEnable(GL.GL_DEPTH_TEST);
|
gl.glEnable(GL.GL_DEPTH_TEST);
|
||||||
gl.glDepthFunc(convertTestFunction(context.depthFunc));
|
|
||||||
context.depthTestEnabled = true;
|
context.depthTestEnabled = true;
|
||||||
} else if (!state.isDepthTest() && context.depthTestEnabled) {
|
} else if (!state.isDepthTest() && context.depthTestEnabled) {
|
||||||
gl.glDisable(GL.GL_DEPTH_TEST);
|
gl.glDisable(GL.GL_DEPTH_TEST);
|
||||||
context.depthTestEnabled = false;
|
context.depthTestEnabled = false;
|
||||||
}
|
}
|
||||||
if (state.getDepthFunc() != context.depthFunc) {
|
if (state.isDepthTest() && state.getDepthFunc() != context.depthFunc) {
|
||||||
gl.glDepthFunc(convertTestFunction(state.getDepthFunc()));
|
gl.glDepthFunc(convertTestFunction(state.getDepthFunc()));
|
||||||
context.depthFunc = state.getDepthFunc();
|
context.depthFunc = state.getDepthFunc();
|
||||||
}
|
}
|
||||||
@ -1064,6 +1073,9 @@ public class GLRenderer implements Renderer {
|
|||||||
stringBuf.append("\n");
|
stringBuf.append("\n");
|
||||||
} else {
|
} else {
|
||||||
if (gles2) {
|
if (gles2) {
|
||||||
|
// request GLSL ES (1.00) when compiling under GLES2.
|
||||||
|
stringBuf.append("#version 100\n");
|
||||||
|
|
||||||
if (source.getType() == ShaderType.Fragment) {
|
if (source.getType() == ShaderType.Fragment) {
|
||||||
// GLES2 requires precision qualifier.
|
// GLES2 requires precision qualifier.
|
||||||
stringBuf.append("precision mediump float;\n");
|
stringBuf.append("precision mediump float;\n");
|
||||||
@ -1080,6 +1092,7 @@ public class GLRenderer implements Renderer {
|
|||||||
if (linearizeSrgbImages) {
|
if (linearizeSrgbImages) {
|
||||||
stringBuf.append("#define SRGB 1\n");
|
stringBuf.append("#define SRGB 1\n");
|
||||||
}
|
}
|
||||||
|
stringBuf.append("#define ").append(source.getType().name().toUpperCase()).append("_SHADER 1\n");
|
||||||
|
|
||||||
stringBuf.append(source.getDefines());
|
stringBuf.append(source.getDefines());
|
||||||
stringBuf.append(source.getSource());
|
stringBuf.append(source.getSource());
|
||||||
@ -1422,7 +1435,7 @@ public class GLRenderer implements Renderer {
|
|||||||
// NOTE: For depth textures, sets nearest/no-mips mode
|
// NOTE: For depth textures, sets nearest/no-mips mode
|
||||||
// Required to fix "framebuffer unsupported"
|
// Required to fix "framebuffer unsupported"
|
||||||
// for old NVIDIA drivers!
|
// for old NVIDIA drivers!
|
||||||
setupTextureParams(tex);
|
setupTextureParams(0, tex);
|
||||||
}
|
}
|
||||||
|
|
||||||
glfbo.glFramebufferTexture2DEXT(GLFbo.GL_FRAMEBUFFER_EXT,
|
glfbo.glFramebufferTexture2DEXT(GLFbo.GL_FRAMEBUFFER_EXT,
|
||||||
@ -1450,24 +1463,43 @@ public class GLRenderer implements Renderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void bindFrameBuffer(FrameBuffer fb) {
|
||||||
|
if (fb == null) {
|
||||||
|
if (context.boundFBO != 0) {
|
||||||
|
glfbo.glBindFramebufferEXT(GLFbo.GL_FRAMEBUFFER_EXT, 0);
|
||||||
|
statistics.onFrameBufferUse(null, true);
|
||||||
|
context.boundFBO = 0;
|
||||||
|
context.boundFB = null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
assert fb.getId() != -1 && fb.getId() != 0;
|
||||||
|
if (context.boundFBO != fb.getId()) {
|
||||||
|
glfbo.glBindFramebufferEXT(GLFbo.GL_FRAMEBUFFER_EXT, fb.getId());
|
||||||
|
context.boundFBO = fb.getId();
|
||||||
|
context.boundFB = fb;
|
||||||
|
statistics.onFrameBufferUse(fb, true);
|
||||||
|
} else {
|
||||||
|
statistics.onFrameBufferUse(fb, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void updateFrameBuffer(FrameBuffer fb) {
|
public void updateFrameBuffer(FrameBuffer fb) {
|
||||||
|
if (fb.getNumColorBuffers() == 0 && fb.getDepthBuffer() == null) {
|
||||||
|
throw new IllegalArgumentException("The framebuffer: " + fb
|
||||||
|
+ "\nDoesn't have any color/depth buffers");
|
||||||
|
}
|
||||||
|
|
||||||
int id = fb.getId();
|
int id = fb.getId();
|
||||||
if (id == -1) {
|
if (id == -1) {
|
||||||
// create FBO
|
|
||||||
glfbo.glGenFramebuffersEXT(intBuf1);
|
glfbo.glGenFramebuffersEXT(intBuf1);
|
||||||
id = intBuf1.get(0);
|
id = intBuf1.get(0);
|
||||||
fb.setId(id);
|
fb.setId(id);
|
||||||
objManager.registerObject(fb);
|
objManager.registerObject(fb);
|
||||||
|
|
||||||
statistics.onNewFrameBuffer();
|
statistics.onNewFrameBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (context.boundFBO != id) {
|
bindFrameBuffer(fb);
|
||||||
glfbo.glBindFramebufferEXT(GLFbo.GL_FRAMEBUFFER_EXT, id);
|
|
||||||
// binding an FBO automatically sets draw buf to GL_COLOR_ATTACHMENT0
|
|
||||||
context.boundDrawBuf = 0;
|
|
||||||
context.boundFBO = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
FrameBuffer.RenderBuffer depthBuf = fb.getDepthBuffer();
|
FrameBuffer.RenderBuffer depthBuf = fb.getDepthBuffer();
|
||||||
if (depthBuf != null) {
|
if (depthBuf != null) {
|
||||||
@ -1479,6 +1511,7 @@ public class GLRenderer implements Renderer {
|
|||||||
updateFrameBufferAttachment(fb, colorBuf);
|
updateFrameBufferAttachment(fb, colorBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setReadDrawBuffers(fb);
|
||||||
checkFrameBufferError();
|
checkFrameBufferError();
|
||||||
|
|
||||||
fb.clearUpdateNeeded();
|
fb.clearUpdateNeeded();
|
||||||
@ -1506,9 +1539,89 @@ public class GLRenderer implements Renderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setMainFrameBufferOverride(FrameBuffer fb) {
|
public void setMainFrameBufferOverride(FrameBuffer fb) {
|
||||||
|
mainFbOverride = null;
|
||||||
|
if (context.boundFBO == 0) {
|
||||||
|
// Main FB is now set to fb, make sure its bound
|
||||||
|
setFrameBuffer(fb);
|
||||||
|
}
|
||||||
mainFbOverride = fb;
|
mainFbOverride = fb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setReadDrawBuffers(FrameBuffer fb) {
|
||||||
|
if (gl2 == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final int NONE = -2;
|
||||||
|
final int INITIAL = -1;
|
||||||
|
final int MRT_OFF = 100;
|
||||||
|
|
||||||
|
if (fb == null) {
|
||||||
|
// Set Read/Draw buffers to initial value.
|
||||||
|
if (context.boundDrawBuf != INITIAL) {
|
||||||
|
gl2.glDrawBuffer(context.initialDrawBuf);
|
||||||
|
context.boundDrawBuf = INITIAL;
|
||||||
|
}
|
||||||
|
if (context.boundReadBuf != INITIAL) {
|
||||||
|
gl2.glReadBuffer(context.initialReadBuf);
|
||||||
|
context.boundReadBuf = INITIAL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (fb.getNumColorBuffers() == 0) {
|
||||||
|
// make sure to select NONE as draw buf
|
||||||
|
// no color buffer attached.
|
||||||
|
if (gl2 != null) {
|
||||||
|
if (context.boundDrawBuf != NONE) {
|
||||||
|
gl2.glDrawBuffer(GL.GL_NONE);
|
||||||
|
context.boundDrawBuf = NONE;
|
||||||
|
}
|
||||||
|
if (context.boundReadBuf != NONE) {
|
||||||
|
gl2.glReadBuffer(GL.GL_NONE);
|
||||||
|
context.boundReadBuf = NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (fb.getNumColorBuffers() > limits.get(Limits.FrameBufferAttachments)) {
|
||||||
|
throw new RendererException("Framebuffer has more color "
|
||||||
|
+ "attachments than are supported"
|
||||||
|
+ " by the video hardware!");
|
||||||
|
}
|
||||||
|
if (fb.isMultiTarget()) {
|
||||||
|
if (!caps.contains(Caps.FrameBufferMRT)) {
|
||||||
|
throw new RendererException("Multiple render targets "
|
||||||
|
+ " are not supported by the video hardware");
|
||||||
|
}
|
||||||
|
if (fb.getNumColorBuffers() > limits.get(Limits.FrameBufferMrtAttachments)) {
|
||||||
|
throw new RendererException("Framebuffer has more"
|
||||||
|
+ " multi targets than are supported"
|
||||||
|
+ " by the video hardware!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context.boundDrawBuf != MRT_OFF + fb.getNumColorBuffers()) {
|
||||||
|
intBuf16.clear();
|
||||||
|
for (int i = 0; i < fb.getNumColorBuffers(); i++) {
|
||||||
|
intBuf16.put(GLFbo.GL_COLOR_ATTACHMENT0_EXT + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
intBuf16.flip();
|
||||||
|
glext.glDrawBuffers(intBuf16);
|
||||||
|
context.boundDrawBuf = MRT_OFF + fb.getNumColorBuffers();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
RenderBuffer rb = fb.getColorBuffer(fb.getTargetIndex());
|
||||||
|
// select this draw buffer
|
||||||
|
if (gl2 != null) {
|
||||||
|
if (context.boundDrawBuf != rb.getSlot()) {
|
||||||
|
gl2.glDrawBuffer(GLFbo.GL_COLOR_ATTACHMENT0_EXT + rb.getSlot());
|
||||||
|
context.boundDrawBuf = rb.getSlot();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public void setFrameBuffer(FrameBuffer fb) {
|
public void setFrameBuffer(FrameBuffer fb) {
|
||||||
if (fb == null && mainFbOverride != null) {
|
if (fb == null && mainFbOverride != null) {
|
||||||
fb = mainFbOverride;
|
fb = mainFbOverride;
|
||||||
@ -1541,100 +1654,20 @@ public class GLRenderer implements Renderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (fb == null) {
|
if (fb == null) {
|
||||||
// unbind any fbos
|
bindFrameBuffer(null);
|
||||||
if (context.boundFBO != 0) {
|
setReadDrawBuffers(null);
|
||||||
glfbo.glBindFramebufferEXT(GLFbo.GL_FRAMEBUFFER_EXT, 0);
|
|
||||||
statistics.onFrameBufferUse(null, true);
|
|
||||||
|
|
||||||
context.boundFBO = 0;
|
|
||||||
}
|
|
||||||
// select back buffer
|
|
||||||
if (gl2 != null) {
|
|
||||||
if (context.boundDrawBuf != -1) {
|
|
||||||
gl2.glDrawBuffer(context.initialDrawBuf);
|
|
||||||
context.boundDrawBuf = -1;
|
|
||||||
}
|
|
||||||
if (context.boundReadBuf != -1) {
|
|
||||||
gl2.glReadBuffer(context.initialReadBuf);
|
|
||||||
context.boundReadBuf = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
context.boundFB = null;
|
|
||||||
} else {
|
} else {
|
||||||
if (fb.getNumColorBuffers() == 0 && fb.getDepthBuffer() == null) {
|
|
||||||
throw new IllegalArgumentException("The framebuffer: " + fb
|
|
||||||
+ "\nDoesn't have any color/depth buffers");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fb.isUpdateNeeded()) {
|
if (fb.isUpdateNeeded()) {
|
||||||
updateFrameBuffer(fb);
|
updateFrameBuffer(fb);
|
||||||
|
} else {
|
||||||
|
bindFrameBuffer(fb);
|
||||||
|
setReadDrawBuffers(fb);
|
||||||
}
|
}
|
||||||
|
|
||||||
// update viewport to reflect framebuffer's resolution
|
// update viewport to reflect framebuffer's resolution
|
||||||
setViewPort(0, 0, fb.getWidth(), fb.getHeight());
|
setViewPort(0, 0, fb.getWidth(), fb.getHeight());
|
||||||
|
|
||||||
if (context.boundFBO != fb.getId()) {
|
assert fb.getId() > 0;
|
||||||
glfbo.glBindFramebufferEXT(GLFbo.GL_FRAMEBUFFER_EXT, fb.getId());
|
|
||||||
statistics.onFrameBufferUse(fb, true);
|
|
||||||
|
|
||||||
context.boundFBO = fb.getId();
|
|
||||||
} else {
|
|
||||||
statistics.onFrameBufferUse(fb, false);
|
|
||||||
}
|
|
||||||
if (fb.getNumColorBuffers() == 0) {
|
|
||||||
// make sure to select NONE as draw buf
|
|
||||||
// no color buffer attached. select NONE
|
|
||||||
if (gl2 != null) {
|
|
||||||
if (context.boundDrawBuf != -2) {
|
|
||||||
gl2.glDrawBuffer(GL.GL_NONE);
|
|
||||||
context.boundDrawBuf = -2;
|
|
||||||
}
|
|
||||||
if (context.boundReadBuf != -2) {
|
|
||||||
gl2.glReadBuffer(GL.GL_NONE);
|
|
||||||
context.boundReadBuf = -2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (fb.getNumColorBuffers() > limits.get(Limits.FrameBufferAttachments)) {
|
|
||||||
throw new RendererException("Framebuffer has more color "
|
|
||||||
+ "attachments than are supported"
|
|
||||||
+ " by the video hardware!");
|
|
||||||
}
|
|
||||||
if (fb.isMultiTarget()) {
|
|
||||||
if (!caps.contains(Caps.FrameBufferMRT)) {
|
|
||||||
throw new RendererException("Multiple render targets "
|
|
||||||
+ " are not supported by the video hardware");
|
|
||||||
}
|
|
||||||
if (fb.getNumColorBuffers() > limits.get(Limits.FrameBufferMrtAttachments)) {
|
|
||||||
throw new RendererException("Framebuffer has more"
|
|
||||||
+ " multi targets than are supported"
|
|
||||||
+ " by the video hardware!");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (context.boundDrawBuf != 100 + fb.getNumColorBuffers()) {
|
|
||||||
intBuf16.clear();
|
|
||||||
for (int i = 0; i < fb.getNumColorBuffers(); i++) {
|
|
||||||
intBuf16.put(GLFbo.GL_COLOR_ATTACHMENT0_EXT + i);
|
|
||||||
}
|
|
||||||
|
|
||||||
intBuf16.flip();
|
|
||||||
glext.glDrawBuffers(intBuf16);
|
|
||||||
context.boundDrawBuf = 100 + fb.getNumColorBuffers();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
RenderBuffer rb = fb.getColorBuffer(fb.getTargetIndex());
|
|
||||||
// select this draw buffer
|
|
||||||
if (gl2 != null) {
|
|
||||||
if (context.boundDrawBuf != rb.getSlot()) {
|
|
||||||
gl2.glDrawBuffer(GLFbo.GL_COLOR_ATTACHMENT0_EXT + rb.getSlot());
|
|
||||||
context.boundDrawBuf = rb.getSlot();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
assert fb.getId() >= 0;
|
|
||||||
assert context.boundFBO == fb.getId();
|
assert context.boundFBO == fb.getId();
|
||||||
|
|
||||||
context.boundFB = fb;
|
context.boundFB = fb;
|
||||||
@ -1806,87 +1839,80 @@ public class GLRenderer implements Renderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("fallthrough")
|
@SuppressWarnings("fallthrough")
|
||||||
private void setupTextureParams(Texture tex) {
|
private void setupTextureParams(int unit, Texture tex) {
|
||||||
Image image = tex.getImage();
|
Image image = tex.getImage();
|
||||||
int target = convertTextureType(tex.getType(), image != null ? image.getMultiSamples() : 1, -1);
|
int target = convertTextureType(tex.getType(), image != null ? image.getMultiSamples() : 1, -1);
|
||||||
|
|
||||||
boolean haveMips = true;
|
boolean haveMips = true;
|
||||||
|
|
||||||
if (image != null) {
|
if (image != null) {
|
||||||
haveMips = image.isGeneratedMipmapsRequired() || image.hasMipmaps();
|
haveMips = image.isGeneratedMipmapsRequired() || image.hasMipmaps();
|
||||||
}
|
}
|
||||||
|
|
||||||
// filter things
|
LastTextureState curState = image.getLastTextureState();
|
||||||
if (image.getLastTextureState().magFilter != tex.getMagFilter()) {
|
|
||||||
int magFilter = convertMagFilter(tex.getMagFilter());
|
|
||||||
gl.glTexParameteri(target, GL.GL_TEXTURE_MAG_FILTER, magFilter);
|
|
||||||
image.getLastTextureState().magFilter = tex.getMagFilter();
|
|
||||||
}
|
|
||||||
if (image.getLastTextureState().minFilter != tex.getMinFilter()) {
|
|
||||||
int minFilter = convertMinFilter(tex.getMinFilter(), haveMips);
|
|
||||||
gl.glTexParameteri(target, GL.GL_TEXTURE_MIN_FILTER, minFilter);
|
|
||||||
image.getLastTextureState().minFilter = tex.getMinFilter();
|
|
||||||
}
|
|
||||||
if (caps.contains(Caps.SeamlessCubemap) && tex.getType() == Texture.Type.CubeMap) {
|
|
||||||
if (haveMips && !context.seamlessCubemap) {
|
|
||||||
// We can enable seamless cubemap filtering.
|
|
||||||
gl.glEnable(GLExt.GL_TEXTURE_CUBE_MAP_SEAMLESS);
|
|
||||||
context.seamlessCubemap = true;
|
|
||||||
} else if (!haveMips && context.seamlessCubemap) {
|
|
||||||
// For skyboxes (no mipmaps), disable seamless cubemap filtering.
|
|
||||||
gl.glDisable(GLExt.GL_TEXTURE_CUBE_MAP_SEAMLESS);
|
|
||||||
context.seamlessCubemap = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tex.getAnisotropicFilter() > 1) {
|
if (curState.magFilter != tex.getMagFilter()) {
|
||||||
if (caps.contains(Caps.TextureFilterAnisotropic)) {
|
bindTextureAndUnit(target, image, unit);
|
||||||
|
gl.glTexParameteri(target, GL.GL_TEXTURE_MAG_FILTER, convertMagFilter(tex.getMagFilter()));
|
||||||
|
curState.magFilter = tex.getMagFilter();
|
||||||
|
}
|
||||||
|
if (curState.minFilter != tex.getMinFilter()) {
|
||||||
|
bindTextureAndUnit(target, image, unit);
|
||||||
|
gl.glTexParameteri(target, GL.GL_TEXTURE_MIN_FILTER, convertMinFilter(tex.getMinFilter(), haveMips));
|
||||||
|
curState.minFilter = tex.getMinFilter();
|
||||||
|
}
|
||||||
|
if (caps.contains(Caps.TextureFilterAnisotropic)
|
||||||
|
&& curState.anisoFilter != tex.getAnisotropicFilter()) {
|
||||||
|
bindTextureAndUnit(target, image, unit);
|
||||||
gl.glTexParameterf(target,
|
gl.glTexParameterf(target,
|
||||||
GLExt.GL_TEXTURE_MAX_ANISOTROPY_EXT,
|
GLExt.GL_TEXTURE_MAX_ANISOTROPY_EXT,
|
||||||
tex.getAnisotropicFilter());
|
tex.getAnisotropicFilter());
|
||||||
}
|
curState.anisoFilter = tex.getAnisotropicFilter();
|
||||||
}
|
}
|
||||||
|
|
||||||
// repeat modes
|
|
||||||
switch (tex.getType()) {
|
switch (tex.getType()) {
|
||||||
case ThreeDimensional:
|
case ThreeDimensional:
|
||||||
case CubeMap: // cubemaps use 3D coords
|
case CubeMap: // cubemaps use 3D coords
|
||||||
if (gl2 != null && image.getLastTextureState().rWrap != tex.getWrap(WrapAxis.R)) {
|
if (gl2 != null && curState.rWrap != tex.getWrap(WrapAxis.R)) {
|
||||||
|
bindTextureAndUnit(target, image, unit);
|
||||||
gl2.glTexParameteri(target, GL2.GL_TEXTURE_WRAP_R, convertWrapMode(tex.getWrap(WrapAxis.R)));
|
gl2.glTexParameteri(target, GL2.GL_TEXTURE_WRAP_R, convertWrapMode(tex.getWrap(WrapAxis.R)));
|
||||||
image.getLastTextureState().rWrap = tex.getWrap(WrapAxis.R);
|
curState.rWrap = tex.getWrap(WrapAxis.R);
|
||||||
}
|
}
|
||||||
//There is no break statement on purpose here
|
//There is no break statement on purpose here
|
||||||
case TwoDimensional:
|
case TwoDimensional:
|
||||||
case TwoDimensionalArray:
|
case TwoDimensionalArray:
|
||||||
if (image.getLastTextureState().tWrap != tex.getWrap(WrapAxis.T)) {
|
if (curState.tWrap != tex.getWrap(WrapAxis.T)) {
|
||||||
|
bindTextureAndUnit(target, image, unit);
|
||||||
gl.glTexParameteri(target, GL.GL_TEXTURE_WRAP_T, convertWrapMode(tex.getWrap(WrapAxis.T)));
|
gl.glTexParameteri(target, GL.GL_TEXTURE_WRAP_T, convertWrapMode(tex.getWrap(WrapAxis.T)));
|
||||||
image.getLastTextureState().tWrap = tex.getWrap(WrapAxis.T);
|
image.getLastTextureState().tWrap = tex.getWrap(WrapAxis.T);
|
||||||
}
|
}
|
||||||
if (image.getLastTextureState().sWrap != tex.getWrap(WrapAxis.S)) {
|
if (curState.sWrap != tex.getWrap(WrapAxis.S)) {
|
||||||
|
bindTextureAndUnit(target, image, unit);
|
||||||
gl.glTexParameteri(target, GL.GL_TEXTURE_WRAP_S, convertWrapMode(tex.getWrap(WrapAxis.S)));
|
gl.glTexParameteri(target, GL.GL_TEXTURE_WRAP_S, convertWrapMode(tex.getWrap(WrapAxis.S)));
|
||||||
image.getLastTextureState().sWrap = tex.getWrap(WrapAxis.S);
|
curState.sWrap = tex.getWrap(WrapAxis.S);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new UnsupportedOperationException("Unknown texture type: " + tex.getType());
|
throw new UnsupportedOperationException("Unknown texture type: " + tex.getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
if(tex.isNeedCompareModeUpdate() && gl2 != null){
|
ShadowCompareMode texCompareMode = tex.getShadowCompareMode();
|
||||||
// R to Texture compare mode
|
if (gl2 != null && curState.shadowCompareMode != texCompareMode) {
|
||||||
if (tex.getShadowCompareMode() != Texture.ShadowCompareMode.Off) {
|
bindTextureAndUnit(target, image, unit);
|
||||||
gl2.glTexParameteri(target, GL2.GL_TEXTURE_COMPARE_MODE, GL2.GL_COMPARE_R_TO_TEXTURE);
|
if (texCompareMode != ShadowCompareMode.Off) {
|
||||||
gl2.glTexParameteri(target, GL2.GL_DEPTH_TEXTURE_MODE, GL2.GL_INTENSITY);
|
gl2.glTexParameteri(target, GL2.GL_TEXTURE_COMPARE_MODE, GL2.GL_COMPARE_REF_TO_TEXTURE);
|
||||||
if (tex.getShadowCompareMode() == Texture.ShadowCompareMode.GreaterOrEqual) {
|
if (texCompareMode == ShadowCompareMode.GreaterOrEqual) {
|
||||||
gl2.glTexParameteri(target, GL2.GL_TEXTURE_COMPARE_FUNC, GL.GL_GEQUAL);
|
gl2.glTexParameteri(target, GL2.GL_TEXTURE_COMPARE_FUNC, GL.GL_GEQUAL);
|
||||||
} else {
|
} else {
|
||||||
gl2.glTexParameteri(target, GL2.GL_TEXTURE_COMPARE_FUNC, GL.GL_LEQUAL);
|
gl2.glTexParameteri(target, GL2.GL_TEXTURE_COMPARE_FUNC, GL.GL_LEQUAL);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//restoring default value
|
|
||||||
gl2.glTexParameteri(target, GL2.GL_TEXTURE_COMPARE_MODE, GL.GL_NONE);
|
gl2.glTexParameteri(target, GL2.GL_TEXTURE_COMPARE_MODE, GL.GL_NONE);
|
||||||
}
|
}
|
||||||
tex.compareModeUpdated();
|
curState.shadowCompareMode = texCompareMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If at this point we didn't bind the texture, bind it now
|
||||||
|
bindTextureOnly(target, image, unit);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1944,6 +1970,50 @@ public class GLRenderer implements Renderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensures that the texture is bound to the given unit
|
||||||
|
* and that the unit is currently active (for modification).
|
||||||
|
*
|
||||||
|
* @param target The texture target, one of GL_TEXTURE_***
|
||||||
|
* @param img The image texture to bind
|
||||||
|
* @param unit At what unit to bind the texture.
|
||||||
|
*/
|
||||||
|
private void bindTextureAndUnit(int target, Image img, int unit) {
|
||||||
|
if (context.boundTextureUnit != unit) {
|
||||||
|
gl.glActiveTexture(GL.GL_TEXTURE0 + unit);
|
||||||
|
context.boundTextureUnit = unit;
|
||||||
|
}
|
||||||
|
if (context.boundTextures[unit] != img) {
|
||||||
|
gl.glBindTexture(target, img.getId());
|
||||||
|
context.boundTextures[unit] = img;
|
||||||
|
statistics.onTextureUse(img, true);
|
||||||
|
} else {
|
||||||
|
statistics.onTextureUse(img, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensures that the texture is bound to the given unit,
|
||||||
|
* but does not care if the unit is active (for rendering).
|
||||||
|
*
|
||||||
|
* @param target The texture target, one of GL_TEXTURE_***
|
||||||
|
* @param img The image texture to bind
|
||||||
|
* @param unit At what unit to bind the texture.
|
||||||
|
*/
|
||||||
|
private void bindTextureOnly(int target, Image img, int unit) {
|
||||||
|
if (context.boundTextures[unit] != img) {
|
||||||
|
if (context.boundTextureUnit != unit) {
|
||||||
|
gl.glActiveTexture(GL.GL_TEXTURE0 + unit);
|
||||||
|
context.boundTextureUnit = unit;
|
||||||
|
}
|
||||||
|
gl.glBindTexture(target, img.getId());
|
||||||
|
context.boundTextures[unit] = img;
|
||||||
|
statistics.onTextureUse(img, true);
|
||||||
|
} else {
|
||||||
|
statistics.onTextureUse(img, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Uploads the given image to the GL driver.
|
* Uploads the given image to the GL driver.
|
||||||
*
|
*
|
||||||
@ -1967,17 +2037,7 @@ public class GLRenderer implements Renderer {
|
|||||||
|
|
||||||
// bind texture
|
// bind texture
|
||||||
int target = convertTextureType(type, img.getMultiSamples(), -1);
|
int target = convertTextureType(type, img.getMultiSamples(), -1);
|
||||||
if (context.boundTextures[unit] != img) {
|
bindTextureAndUnit(target, img, unit);
|
||||||
if (context.boundTextureUnit != unit) {
|
|
||||||
gl.glActiveTexture(GL.GL_TEXTURE0 + unit);
|
|
||||||
context.boundTextureUnit = unit;
|
|
||||||
}
|
|
||||||
|
|
||||||
gl.glBindTexture(target, texId);
|
|
||||||
context.boundTextures[unit] = img;
|
|
||||||
|
|
||||||
statistics.onTextureUse(img, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!img.hasMipmaps() && img.isGeneratedMipmapsRequired()) {
|
if (!img.hasMipmaps() && img.isGeneratedMipmapsRequired()) {
|
||||||
// Image does not have mipmaps, but they are required.
|
// Image does not have mipmaps, but they are required.
|
||||||
@ -2086,6 +2146,7 @@ public class GLRenderer implements Renderer {
|
|||||||
img.clearUpdateNeeded();
|
img.clearUpdateNeeded();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void setTexture(int unit, Texture tex) {
|
public void setTexture(int unit, Texture tex) {
|
||||||
Image image = tex.getImage();
|
Image image = tex.getImage();
|
||||||
if (image.isUpdateNeeded() || (image.isGeneratedMipmapsRequired() && !image.isMipmapsGenerated())) {
|
if (image.isUpdateNeeded() || (image.isGeneratedMipmapsRequired() && !image.isMipmapsGenerated())) {
|
||||||
@ -2112,24 +2173,7 @@ public class GLRenderer implements Renderer {
|
|||||||
int texId = image.getId();
|
int texId = image.getId();
|
||||||
assert texId != -1;
|
assert texId != -1;
|
||||||
|
|
||||||
Image[] textures = context.boundTextures;
|
setupTextureParams(unit, tex);
|
||||||
|
|
||||||
int type = convertTextureType(tex.getType(), image.getMultiSamples(), -1);
|
|
||||||
if (textures[unit] != image) {
|
|
||||||
if (context.boundTextureUnit != unit) {
|
|
||||||
gl.glActiveTexture(GL.GL_TEXTURE0 + unit);
|
|
||||||
context.boundTextureUnit = unit;
|
|
||||||
}
|
|
||||||
|
|
||||||
gl.glBindTexture(type, texId);
|
|
||||||
textures[unit] = image;
|
|
||||||
|
|
||||||
statistics.onTextureUse(image, true);
|
|
||||||
} else {
|
|
||||||
statistics.onTextureUse(image, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
setupTextureParams(tex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void modifyTexture(Texture tex, Image pixels, int x, int y) {
|
public void modifyTexture(Texture tex, Image pixels, int x, int y) {
|
||||||
@ -2623,12 +2667,13 @@ public class GLRenderer implements Renderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clearVertexAttribs();
|
||||||
|
|
||||||
if (indices != null) {
|
if (indices != null) {
|
||||||
drawTriangleList(indices, mesh, count);
|
drawTriangleList(indices, mesh, count);
|
||||||
} else {
|
} else {
|
||||||
drawTriangleArray(mesh.getMode(), count, mesh.getVertexCount());
|
drawTriangleArray(mesh.getMode(), count, mesh.getVertexCount());
|
||||||
}
|
}
|
||||||
clearVertexAttribs();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void renderMesh(Mesh mesh, int lod, int count, VertexBuffer[] instanceData) {
|
public void renderMesh(Mesh mesh, int lod, int count, VertexBuffer[] instanceData) {
|
||||||
|
@ -36,8 +36,14 @@ import java.lang.reflect.Field;
|
|||||||
import java.lang.reflect.InvocationHandler;
|
import java.lang.reflect.InvocationHandler;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Proxy;
|
import java.lang.reflect.Proxy;
|
||||||
|
import java.nio.Buffer;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.CharBuffer;
|
||||||
|
import java.nio.DoubleBuffer;
|
||||||
|
import java.nio.FloatBuffer;
|
||||||
import java.nio.IntBuffer;
|
import java.nio.IntBuffer;
|
||||||
|
import java.nio.LongBuffer;
|
||||||
|
import java.nio.ShortBuffer;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -51,6 +57,17 @@ public final class GLTracer implements InvocationHandler {
|
|||||||
private final IntMap<String> constMap;
|
private final IntMap<String> constMap;
|
||||||
private static final HashMap<String, IntMap<Void>> nonEnumArgMap = new HashMap<String, IntMap<Void>>();
|
private static final HashMap<String, IntMap<Void>> nonEnumArgMap = new HashMap<String, IntMap<Void>>();
|
||||||
|
|
||||||
|
private static final String ANSI_RESET = "\u001B[0m";
|
||||||
|
private static final String ANSI_BRIGHT = "\u001B[1m";
|
||||||
|
private static final String ANSI_BLACK = "\u001B[30m";
|
||||||
|
private static final String ANSI_RED = "\u001B[31m";
|
||||||
|
private static final String ANSI_GREEN = "\u001B[32m";
|
||||||
|
private static final String ANSI_YELLOW = "\u001B[33m";
|
||||||
|
private static final String ANSI_BLUE = "\u001B[34m";
|
||||||
|
private static final String ANSI_MAGENTA = "\u001B[35m";
|
||||||
|
private static final String ANSI_CYAN = "\u001B[36m";
|
||||||
|
private static final String ANSI_WHITE = "\u001B[37m";
|
||||||
|
|
||||||
private static void noEnumArgs(String method, int... argSlots) {
|
private static void noEnumArgs(String method, int... argSlots) {
|
||||||
IntMap<Void> argSlotsMap = new IntMap<Void>();
|
IntMap<Void> argSlotsMap = new IntMap<Void>();
|
||||||
for (int argSlot : argSlots) {
|
for (int argSlot : argSlots) {
|
||||||
@ -174,100 +191,305 @@ public final class GLTracer implements InvocationHandler {
|
|||||||
new GLTracer(glInterface, constMap));
|
new GLTracer(glInterface, constMap));
|
||||||
}
|
}
|
||||||
|
|
||||||
private String translateInteger(String method, int value, int argIndex) {
|
private void printStyle(String style, String string) {
|
||||||
IntMap<Void> argSlotMap = nonEnumArgMap.get(method);
|
System.out.print(style + string + ANSI_RESET);
|
||||||
if (argSlotMap != null && argSlotMap.containsKey(argIndex)) {
|
|
||||||
return Integer.toString(value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void print(String string) {
|
||||||
|
System.out.print(string);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void printInt(int value) {
|
||||||
|
print(Integer.toString(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void printEnum(int value) {
|
||||||
String enumName = constMap.get(value);
|
String enumName = constMap.get(value);
|
||||||
if (enumName != null) {
|
if (enumName != null) {
|
||||||
return enumName;
|
if (enumName.startsWith("GL_")) {
|
||||||
|
enumName = enumName.substring(3);
|
||||||
|
}
|
||||||
|
if (enumName.endsWith("_EXT") || enumName.endsWith("_ARB")) {
|
||||||
|
enumName = enumName.substring(0, enumName.length() - 4);
|
||||||
|
}
|
||||||
|
printStyle(ANSI_GREEN, enumName);
|
||||||
} else {
|
} else {
|
||||||
return "GL_ENUM_" + Integer.toHexString(value);
|
printStyle(ANSI_GREEN, "ENUM_" + Integer.toHexString(value));
|
||||||
//throw new IllegalStateException("Untranslatable enum encountered on " + method +
|
|
||||||
// " at argument " + argIndex + " with value " + value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String translateString(String value) {
|
private void printIntOrEnum(String method, int value, int argIndex) {
|
||||||
return "\"" + value.replaceAll("\0", "\\\\0") + "\"";
|
IntMap<Void> argSlotMap = nonEnumArgMap.get(method);
|
||||||
|
if (argSlotMap != null && argSlotMap.containsKey(argIndex)) {
|
||||||
|
printInt(value);
|
||||||
|
} else {
|
||||||
|
printEnum(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
private void printNewLine() {
|
||||||
Object result = method.invoke(obj, args);
|
System.out.println();
|
||||||
String methodName = method.getName();
|
}
|
||||||
|
|
||||||
|
private void printString(String value) {
|
||||||
|
if (value.length() > 150) {
|
||||||
|
value = value.substring(0, 150) + "...";
|
||||||
|
}
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append(ANSI_YELLOW);
|
||||||
|
sb.append("\"");
|
||||||
|
sb.append(ANSI_RESET);
|
||||||
|
for (String line : value.split("\n")) {
|
||||||
|
sb.append(ANSI_YELLOW);
|
||||||
|
sb.append(line.replaceAll("\0", "\\\\0"));
|
||||||
|
sb.append(ANSI_RESET);
|
||||||
|
sb.append("\n");
|
||||||
|
}
|
||||||
|
if (sb.length() > 1 && sb.charAt(sb.length() - 1) == '\n') {
|
||||||
|
sb.setLength(sb.length() - 1);
|
||||||
|
}
|
||||||
|
sb.append(ANSI_YELLOW);
|
||||||
|
sb.append("\"");
|
||||||
|
sb.append(ANSI_RESET);
|
||||||
|
print(sb.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void printBoolean(boolean bool) {
|
||||||
|
printStyle(ANSI_BLUE, bool ? "true" : "false");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void printBuffer(Buffer buffer) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append(ANSI_MAGENTA);
|
||||||
|
if (buffer instanceof ByteBuffer) {
|
||||||
|
sb.append("byte");
|
||||||
|
} else if (buffer instanceof ShortBuffer) {
|
||||||
|
sb.append("short");
|
||||||
|
} else if (buffer instanceof CharBuffer) {
|
||||||
|
sb.append("char");
|
||||||
|
} else if (buffer instanceof FloatBuffer) {
|
||||||
|
sb.append("float");
|
||||||
|
} else if (buffer instanceof IntBuffer) {
|
||||||
|
sb.append("int");
|
||||||
|
} else if (buffer instanceof LongBuffer) {
|
||||||
|
sb.append("long");
|
||||||
|
} else if (buffer instanceof DoubleBuffer) {
|
||||||
|
sb.append("double");
|
||||||
|
} else {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
sb.append(ANSI_RESET);
|
||||||
|
sb.append("[");
|
||||||
|
|
||||||
|
if (buffer.position() == 0
|
||||||
|
&& buffer.limit() == buffer.capacity()) {
|
||||||
|
// Common case. Just print buffer size.
|
||||||
|
sb.append(buffer.capacity());
|
||||||
|
} else {
|
||||||
|
sb.append("pos=").append(buffer.position());
|
||||||
|
sb.append(" lim=").append(buffer.limit());
|
||||||
|
sb.append(" cap=").append(buffer.capacity());
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.append("]");
|
||||||
|
print(sb.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void printMethodName(String methodName) {
|
||||||
if (methodName.startsWith("gl")) {
|
if (methodName.startsWith("gl")) {
|
||||||
System.out.print(methodName);
|
// GL calls which actually draw (as opposed to change state)
|
||||||
System.out.print("(");
|
// will be printed in darker color
|
||||||
if (args != null) {
|
methodName = methodName.substring(2);
|
||||||
Class<?>[] paramTypes = method.getParameterTypes();
|
if (methodName.equals("Clear")
|
||||||
|
|| methodName.equals("DrawRangeElements")) {
|
||||||
|
print(methodName);
|
||||||
|
} else {
|
||||||
|
if (methodName.endsWith("EXT")) {
|
||||||
|
methodName = methodName.substring(0, methodName.length() - 3);
|
||||||
|
}
|
||||||
|
printStyle(ANSI_BRIGHT, methodName);
|
||||||
|
}
|
||||||
|
} else if (methodName.equals("resetStats")) {
|
||||||
|
printStyle(ANSI_RED, "-- frame boundary --");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void printArgsClear(int mask) {
|
||||||
|
boolean needAPipe = false;
|
||||||
|
print("(");
|
||||||
|
if ((mask & GL.GL_COLOR_BUFFER_BIT) != 0) {
|
||||||
|
printStyle(ANSI_GREEN, "COLOR_BUFFER_BIT");
|
||||||
|
needAPipe = true;
|
||||||
|
}
|
||||||
|
if ((mask & GL.GL_DEPTH_BUFFER_BIT) != 0) {
|
||||||
|
if (needAPipe) {
|
||||||
|
print(" | ");
|
||||||
|
}
|
||||||
|
printStyle(ANSI_GREEN, "DEPTH_BUFFER_BIT");
|
||||||
|
}
|
||||||
|
if ((mask & GL.GL_STENCIL_BUFFER_BIT) != 0) {
|
||||||
|
if (needAPipe) {
|
||||||
|
print(" | ");
|
||||||
|
}
|
||||||
|
printStyle(ANSI_GREEN, "STENCIL_BUFFER_BIT");
|
||||||
|
}
|
||||||
|
print(")");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void printArgsGetInteger(Object[] args) {
|
||||||
|
print("(");
|
||||||
|
int param = (Integer)args[0];
|
||||||
|
IntBuffer ib = (IntBuffer) args[1];
|
||||||
|
printEnum(param);
|
||||||
|
print(", ");
|
||||||
|
printOut();
|
||||||
|
if (param == GL2.GL_DRAW_BUFFER || param == GL2.GL_READ_BUFFER) {
|
||||||
|
printEnum(ib.get(0));
|
||||||
|
} else {
|
||||||
|
printInt(ib.get(0));
|
||||||
|
}
|
||||||
|
print(")");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void printArgsTexParameter(Object[] args) {
|
||||||
|
print("(");
|
||||||
|
|
||||||
|
int target = (Integer) args[0];
|
||||||
|
int param = (Integer) args[1];
|
||||||
|
int value = (Integer) args[2];
|
||||||
|
|
||||||
|
printEnum(target);
|
||||||
|
print(", ");
|
||||||
|
printEnum(param);
|
||||||
|
print(", ");
|
||||||
|
|
||||||
|
if (param == GL.GL_TEXTURE_BASE_LEVEL
|
||||||
|
|| param == GL.GL_TEXTURE_MAX_LEVEL) {
|
||||||
|
printInt(value);
|
||||||
|
} else {
|
||||||
|
printEnum(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
print(")");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void printOut() {
|
||||||
|
printStyle(ANSI_CYAN, "out=");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void printResult(String methodName, Object result, Class<?> returnType) {
|
||||||
|
if (returnType != void.class) {
|
||||||
|
print(" = ");
|
||||||
|
if (result instanceof String) {
|
||||||
|
printString((String) result);
|
||||||
|
} else if (returnType == int.class) {
|
||||||
|
int val = (Integer) result;
|
||||||
|
printIntOrEnum(methodName, val, -1);
|
||||||
|
} else if (returnType == boolean.class) {
|
||||||
|
printBoolean((Boolean)result);
|
||||||
|
} else {
|
||||||
|
print(" = ???");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void printNull() {
|
||||||
|
printStyle(ANSI_BLUE, "null");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void printArgs(String methodName, Object[] args, Class<?>[] paramTypes) {
|
||||||
|
if (methodName.equals("glClear")) {
|
||||||
|
printArgsClear((Integer)args[0]);
|
||||||
|
return;
|
||||||
|
} else if (methodName.equals("glTexParameteri")) {
|
||||||
|
printArgsTexParameter(args);
|
||||||
|
return;
|
||||||
|
} else if (methodName.equals("glGetInteger")) {
|
||||||
|
printArgsGetInteger(args);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args == null) {
|
||||||
|
print("()");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
print("(");
|
||||||
for (int i = 0; i < args.length; i++) {
|
for (int i = 0; i < args.length; i++) {
|
||||||
if (paramTypes[i] == int.class) {
|
if (paramTypes[i] == int.class) {
|
||||||
int val = (Integer)args[i];
|
int val = (Integer)args[i];
|
||||||
System.out.print(translateInteger(methodName, val, i));
|
printIntOrEnum(methodName, val, i);
|
||||||
|
} else if (paramTypes[i] == boolean.class) {
|
||||||
|
printBoolean((Boolean)args[i]);
|
||||||
} else if (paramTypes[i] == String.class) {
|
} else if (paramTypes[i] == String.class) {
|
||||||
System.out.print(translateString((String)args[i]));
|
printString((String)args[i]);
|
||||||
} else if (paramTypes[i] == String[].class) {
|
} else if (paramTypes[i] == String[].class) {
|
||||||
String[] arr = (String[]) args[i];
|
String[] arr = (String[]) args[i];
|
||||||
if (arr.length == 1) {
|
if (arr.length == 1) {
|
||||||
if (arr[0].length() > 150) {
|
printString(arr[0]);
|
||||||
System.out.print("\"" + arr[0].substring(0, 150) + "...\"");
|
|
||||||
} else {
|
} else {
|
||||||
System.out.print("\"" + arr[0] + "\"");
|
print("string[" + arr.length + "]");
|
||||||
}
|
|
||||||
} else {
|
|
||||||
System.out.print("String[" + arr.length + "]");
|
|
||||||
}
|
}
|
||||||
} else if (args[i] instanceof IntBuffer) {
|
} else if (args[i] instanceof IntBuffer) {
|
||||||
IntBuffer buf = (IntBuffer) args[i];
|
IntBuffer buf = (IntBuffer) args[i];
|
||||||
if (buf.capacity() == 16) {
|
if (buf.capacity() == 16) {
|
||||||
int val = buf.get(0);
|
int val = buf.get(0);
|
||||||
System.out.print("out=" + translateInteger(methodName, val, i));
|
printOut();
|
||||||
|
printIntOrEnum(methodName, val, i);
|
||||||
} else if (buf.capacity() == 1) {
|
} else if (buf.capacity() == 1) {
|
||||||
System.out.print("out=" + buf.get(0));
|
printOut();
|
||||||
|
print(Integer.toString(buf.get(0)));
|
||||||
} else {
|
} else {
|
||||||
System.out.print(args[i]);
|
printBuffer(buf);
|
||||||
}
|
}
|
||||||
} else if (args[i] instanceof ByteBuffer) {
|
} else if (args[i] instanceof ByteBuffer) {
|
||||||
ByteBuffer bb = (ByteBuffer)args[i];
|
ByteBuffer bb = (ByteBuffer)args[i];
|
||||||
if (bb.capacity() == 250) {
|
if (bb.capacity() == 250) {
|
||||||
if (bb.get(0) != 0) {
|
printOut();
|
||||||
System.out.print("out=GL_TRUE");
|
printBoolean(bb.get(0) != 0);
|
||||||
} else {
|
} else {
|
||||||
System.out.print("out=GL_FALSE");
|
printBuffer(bb);
|
||||||
}
|
}
|
||||||
|
} else if (args[i] instanceof Buffer) {
|
||||||
|
printBuffer((Buffer)args[i]);
|
||||||
|
} else if (args[i] != null) {
|
||||||
|
print(args[i].toString());
|
||||||
} else {
|
} else {
|
||||||
System.out.print(args[i]);
|
printNull();
|
||||||
}
|
|
||||||
} else {
|
|
||||||
System.out.print(args[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i != args.length - 1) {
|
if (i != args.length - 1) {
|
||||||
System.out.print(", ");
|
System.out.print(", ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
print(")");
|
||||||
}
|
}
|
||||||
|
|
||||||
System.out.print(")");
|
@Override
|
||||||
|
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||||
|
String methodName = method.getName();
|
||||||
|
printMethodName(methodName);
|
||||||
|
|
||||||
if (method.getReturnType() != void.class) {
|
if (methodName.startsWith("gl")) {
|
||||||
if (result instanceof String) {
|
try {
|
||||||
System.out.println(" = " + translateString((String)result));
|
// Try to evaluate result first, so we can see output values.
|
||||||
} else if (method.getReturnType() == int.class) {
|
Object result = method.invoke(obj, args);
|
||||||
int val = (Integer)result;
|
printArgs(methodName, args, method.getParameterTypes());
|
||||||
System.out.println(" = " + translateInteger(methodName, val, -1));
|
printResult(methodName, result, method.getReturnType());
|
||||||
} else if (method.getReturnType() == boolean.class) {
|
printNewLine();
|
||||||
boolean val = (Boolean)result;
|
|
||||||
if (val) System.out.println(" = GL_TRUE");
|
|
||||||
else System.out.println(" = GL_FALSE");
|
|
||||||
} else {
|
|
||||||
System.out.println(" = ???");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
System.out.println();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
return result;
|
||||||
|
} catch (Throwable ex) {
|
||||||
|
// Execution failed, print args anyway
|
||||||
|
// but output values will be incorrect.
|
||||||
|
printArgs(methodName, args, method.getParameterTypes());
|
||||||
|
printNewLine();
|
||||||
|
System.out.println("\tException occurred!");
|
||||||
|
System.out.println(ex.toString());
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printNewLine();
|
||||||
|
return method.invoke(obj, args);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -90,6 +90,8 @@ final class TextureUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public GLImageFormat getImageFormatWithError(Format fmt, boolean isSrgb) {
|
public GLImageFormat getImageFormatWithError(Format fmt, boolean isSrgb) {
|
||||||
|
//if the passed format is one kind of depth there isno point in getting the srgb format;
|
||||||
|
isSrgb = isSrgb && fmt != Format.Depth && fmt != Format.Depth16 && fmt != Format.Depth24 && fmt != Format.Depth24Stencil8 && fmt != Format.Depth32 && fmt != Format.Depth32F;
|
||||||
GLImageFormat glFmt = getImageFormat(fmt, isSrgb);
|
GLImageFormat glFmt = getImageFormat(fmt, isSrgb);
|
||||||
if (glFmt == null && isSrgb) {
|
if (glFmt == null && isSrgb) {
|
||||||
glFmt = getImageFormat(fmt, false);
|
glFmt = getImageFormat(fmt, false);
|
||||||
|
@ -119,19 +119,6 @@ public class BatchNode extends GeometryGroupNode {
|
|||||||
setNeedsFullRebatch(true);
|
setNeedsFullRebatch(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateGeometricState() {
|
|
||||||
if (!children.isEmpty()) {
|
|
||||||
for (Batch batch : batches.getArray()) {
|
|
||||||
if (batch.needMeshUpdate) {
|
|
||||||
batch.geometry.updateModelBound();
|
|
||||||
batch.geometry.updateWorldBound();
|
|
||||||
batch.needMeshUpdate = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
super.updateGeometricState();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Matrix4f getTransformMatrix(Geometry g){
|
protected Matrix4f getTransformMatrix(Geometry g){
|
||||||
return g.cachedWorldMat;
|
return g.cachedWorldMat;
|
||||||
@ -169,7 +156,7 @@ public class BatchNode extends GeometryGroupNode {
|
|||||||
nvb.updateData(normBuf);
|
nvb.updateData(normBuf);
|
||||||
|
|
||||||
|
|
||||||
batch.needMeshUpdate = true;
|
batch.geometry.updateModelBound();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -234,7 +221,7 @@ public class BatchNode extends GeometryGroupNode {
|
|||||||
|
|
||||||
batch.geometry.setMesh(m);
|
batch.geometry.setMesh(m);
|
||||||
batch.geometry.getMesh().updateCounts();
|
batch.geometry.getMesh().updateCounts();
|
||||||
batch.geometry.getMesh().updateBound();
|
batch.geometry.updateModelBound();
|
||||||
batches.add(batch);
|
batches.add(batch);
|
||||||
}
|
}
|
||||||
if (batches.size() > 0) {
|
if (batches.size() > 0) {
|
||||||
@ -457,6 +444,7 @@ public class BatchNode extends GeometryGroupNode {
|
|||||||
int maxWeights = -1;
|
int maxWeights = -1;
|
||||||
|
|
||||||
Mesh.Mode mode = null;
|
Mesh.Mode mode = null;
|
||||||
|
float lineWidth = 1f;
|
||||||
for (Geometry geom : geometries) {
|
for (Geometry geom : geometries) {
|
||||||
totalVerts += geom.getVertexCount();
|
totalVerts += geom.getVertexCount();
|
||||||
totalTris += geom.getTriangleCount();
|
totalTris += geom.getTriangleCount();
|
||||||
@ -465,6 +453,7 @@ public class BatchNode extends GeometryGroupNode {
|
|||||||
maxVertCount = geom.getVertexCount();
|
maxVertCount = geom.getVertexCount();
|
||||||
}
|
}
|
||||||
Mesh.Mode listMode;
|
Mesh.Mode listMode;
|
||||||
|
float listLineWidth = 1f;
|
||||||
int components;
|
int components;
|
||||||
switch (geom.getMesh().getMode()) {
|
switch (geom.getMesh().getMode()) {
|
||||||
case Points:
|
case Points:
|
||||||
@ -475,6 +464,7 @@ public class BatchNode extends GeometryGroupNode {
|
|||||||
case LineStrip:
|
case LineStrip:
|
||||||
case Lines:
|
case Lines:
|
||||||
listMode = Mesh.Mode.Lines;
|
listMode = Mesh.Mode.Lines;
|
||||||
|
listLineWidth = geom.getMesh().getLineWidth();
|
||||||
components = 2;
|
components = 2;
|
||||||
break;
|
break;
|
||||||
case TriangleFan:
|
case TriangleFan:
|
||||||
@ -506,11 +496,19 @@ public class BatchNode extends GeometryGroupNode {
|
|||||||
+ " primitive types: " + mode + " != " + listMode);
|
+ " primitive types: " + mode + " != " + listMode);
|
||||||
}
|
}
|
||||||
mode = listMode;
|
mode = listMode;
|
||||||
|
if (mode == Mesh.Mode.Lines) {
|
||||||
|
if (lineWidth != 1f && listLineWidth != lineWidth) {
|
||||||
|
throw new UnsupportedOperationException("When using Mesh Line mode, cannot combine meshes with different line width "
|
||||||
|
+ lineWidth + " != " + listLineWidth);
|
||||||
|
}
|
||||||
|
lineWidth = listLineWidth;
|
||||||
|
}
|
||||||
compsForBuf[VertexBuffer.Type.Index.ordinal()] = components;
|
compsForBuf[VertexBuffer.Type.Index.ordinal()] = components;
|
||||||
}
|
}
|
||||||
|
|
||||||
outMesh.setMaxNumWeights(maxWeights);
|
outMesh.setMaxNumWeights(maxWeights);
|
||||||
outMesh.setMode(mode);
|
outMesh.setMode(mode);
|
||||||
|
outMesh.setLineWidth(lineWidth);
|
||||||
if (totalVerts >= 65536) {
|
if (totalVerts >= 65536) {
|
||||||
// make sure we create an UnsignedInt buffer so
|
// make sure we create an UnsignedInt buffer so
|
||||||
// we can fit all of the meshes
|
// we can fit all of the meshes
|
||||||
@ -748,7 +746,6 @@ public class BatchNode extends GeometryGroupNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Geometry geometry;
|
Geometry geometry;
|
||||||
boolean needMeshUpdate = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setNeedsFullRebatch(boolean needsFullRebatch) {
|
protected void setNeedsFullRebatch(boolean needsFullRebatch) {
|
||||||
|
@ -570,6 +570,35 @@ public class Node extends Spatial {
|
|||||||
// optimization: try collideWith BoundingVolume to avoid possibly redundant tests on children
|
// optimization: try collideWith BoundingVolume to avoid possibly redundant tests on children
|
||||||
// number 4 in condition is somewhat arbitrary. When there is only one child, the boundingVolume test is redundant at all.
|
// number 4 in condition is somewhat arbitrary. When there is only one child, the boundingVolume test is redundant at all.
|
||||||
// The idea is when there are few children, it can be too expensive to test boundingVolume first.
|
// The idea is when there are few children, it can be too expensive to test boundingVolume first.
|
||||||
|
/*
|
||||||
|
I'm removing this change until some issues can be addressed and I really
|
||||||
|
think it needs to be implemented a better way anyway.
|
||||||
|
|
||||||
|
First, it causes issues for anyone doing collideWith() with BoundingVolumes
|
||||||
|
and expecting it to trickle down to the children. For example, children
|
||||||
|
with BoundingSphere bounding volumes and collideWith(BoundingSphere). Doing
|
||||||
|
a collision check at the parent level then has to do a BoundingSphere to BoundingBox
|
||||||
|
collision which isn't resolved. (Having to come up with a collision point in that
|
||||||
|
case is tricky and the first sign that this is the wrong approach.)
|
||||||
|
|
||||||
|
Second, the rippling changes this caused to 'optimize' collideWith() for this
|
||||||
|
special use-case are another sign that this approach was a bit dodgy. The whole
|
||||||
|
idea of calculating a full collision just to see if the two shapes collide at all
|
||||||
|
is very wasteful.
|
||||||
|
|
||||||
|
A proper implementation should support a simpler boolean check that doesn't do
|
||||||
|
all of that calculation. For example, if 'other' is also a BoundingVolume (ie: 99.9%
|
||||||
|
of all non-Ray cases) then a direct BV to BV intersects() test can be done. So much
|
||||||
|
faster. And if 'other' _is_ a Ray then the BV.intersects(Ray) call can be done.
|
||||||
|
|
||||||
|
I don't have time to do it right now but I'll at least un-break a bunch of peoples'
|
||||||
|
code until it can be 'optimized' properly. Hopefully it's not too late to back out
|
||||||
|
the other dodgy ripples this caused. -pspeed (hindsight-expert ;))
|
||||||
|
|
||||||
|
Note: the code itself is relatively simple to implement but I don't have time to
|
||||||
|
a) test it, and b) see if '> 4' is still a decent check for it. Could be it's fast
|
||||||
|
enough to do all the time for > 1.
|
||||||
|
|
||||||
if (children.size() > 4)
|
if (children.size() > 4)
|
||||||
{
|
{
|
||||||
BoundingVolume bv = this.getWorldBound();
|
BoundingVolume bv = this.getWorldBound();
|
||||||
@ -578,6 +607,7 @@ public class Node extends Spatial {
|
|||||||
// collideWith without CollisionResults parameter used to avoid allocation when possible
|
// collideWith without CollisionResults parameter used to avoid allocation when possible
|
||||||
if (bv.collideWith(other) == 0) return 0;
|
if (bv.collideWith(other) == 0) return 0;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
for (Spatial child : children.getArray()){
|
for (Spatial child : children.getArray()){
|
||||||
total += child.collideWith(other, results);
|
total += child.collideWith(other, results);
|
||||||
}
|
}
|
||||||
|
@ -99,6 +99,7 @@ public class Grid extends Mesh {
|
|||||||
|
|
||||||
updateBound();
|
updateBound();
|
||||||
updateCounts();
|
updateCounts();
|
||||||
|
setStatic();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,7 @@ import com.jme3.math.Vector3f;
|
|||||||
import com.jme3.scene.Mesh;
|
import com.jme3.scene.Mesh;
|
||||||
import com.jme3.scene.VertexBuffer;
|
import com.jme3.scene.VertexBuffer;
|
||||||
import com.jme3.scene.VertexBuffer.Type;
|
import com.jme3.scene.VertexBuffer.Type;
|
||||||
|
import com.jme3.scene.VertexBuffer.Usage;
|
||||||
import com.jme3.util.BufferUtils;
|
import com.jme3.util.BufferUtils;
|
||||||
import java.nio.FloatBuffer;
|
import java.nio.FloatBuffer;
|
||||||
|
|
||||||
@ -62,6 +63,7 @@ public class WireFrustum extends Mesh {
|
|||||||
3, 7,
|
3, 7,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
getBuffer(Type.Index).setUsage(Usage.Static);
|
||||||
setMode(Mode.Lines);
|
setMode(Mode.Lines);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,6 +198,12 @@ public class Curve extends Mesh {
|
|||||||
* points
|
* points
|
||||||
*/
|
*/
|
||||||
private void createNurbMesh(int nbSubSegments) {
|
private void createNurbMesh(int nbSubSegments) {
|
||||||
|
if(spline.getControlPoints() != null && spline.getControlPoints().size() > 0) {
|
||||||
|
if(nbSubSegments == 0) {
|
||||||
|
nbSubSegments = spline.getControlPoints().size() + 1;
|
||||||
|
} else {
|
||||||
|
nbSubSegments = spline.getControlPoints().size() * nbSubSegments + 1;
|
||||||
|
}
|
||||||
float minKnot = spline.getMinNurbKnot();
|
float minKnot = spline.getMinNurbKnot();
|
||||||
float maxKnot = spline.getMaxNurbKnot();
|
float maxKnot = spline.getMaxNurbKnot();
|
||||||
float deltaU = (maxKnot - minKnot) / nbSubSegments;
|
float deltaU = (maxKnot - minKnot) / nbSubSegments;
|
||||||
@ -228,6 +234,7 @@ public class Curve extends Mesh {
|
|||||||
this.updateBound();
|
this.updateBound();
|
||||||
this.updateCounts();
|
this.updateCounts();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void createLinearMesh() {
|
private void createLinearMesh() {
|
||||||
float[] array = new float[spline.getControlPoints().size() * 3];
|
float[] array = new float[spline.getControlPoints().size() * 3];
|
||||||
|
@ -389,6 +389,7 @@ public class Cylinder extends Mesh {
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateBound();
|
updateBound();
|
||||||
|
setStatic();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -124,6 +124,7 @@ public class Quad extends Mesh {
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateBound();
|
updateBound();
|
||||||
|
setStatic();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -299,7 +299,6 @@ public class Sphere extends Mesh {
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateBound();
|
updateBound();
|
||||||
setStatic();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -400,6 +399,7 @@ public class Sphere extends Mesh {
|
|||||||
this.interior = interior;
|
this.interior = interior;
|
||||||
setGeometryData();
|
setGeometryData();
|
||||||
setIndexData();
|
setIndexData();
|
||||||
|
setStatic();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void read(JmeImporter e) throws IOException {
|
public void read(JmeImporter e) throws IOException {
|
||||||
|
@ -459,7 +459,7 @@ public abstract class AbstractShadowRenderer implements SceneProcessor, Savable
|
|||||||
debug = true;
|
debug = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract void getReceivers(GeometryList lightReceivers);
|
protected abstract void getReceivers(GeometryList lightReceivers);
|
||||||
|
|
||||||
public void postFrame(FrameBuffer out) {
|
public void postFrame(FrameBuffer out) {
|
||||||
if (skipPostPass) {
|
if (skipPostPass) {
|
||||||
|
@ -192,7 +192,7 @@ public class DirectionalLightShadowRenderer extends AbstractShadowRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void getReceivers(GeometryList lightReceivers) {
|
protected void getReceivers(GeometryList lightReceivers) {
|
||||||
if (lightReceivers.size()==0) {
|
if (lightReceivers.size()==0) {
|
||||||
for (Spatial scene : viewPort.getScenes()) {
|
for (Spatial scene : viewPort.getScenes()) {
|
||||||
ShadowUtil.getGeometriesInCamFrustum(scene, viewPort.getCamera(), RenderQueue.ShadowMode.Receive, lightReceivers);
|
ShadowUtil.getGeometriesInCamFrustum(scene, viewPort.getCamera(), RenderQueue.ShadowMode.Receive, lightReceivers);
|
||||||
|
@ -139,7 +139,7 @@ public class PointLightShadowRenderer extends AbstractShadowRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void getReceivers(GeometryList lightReceivers) {
|
protected void getReceivers(GeometryList lightReceivers) {
|
||||||
lightReceivers.clear();
|
lightReceivers.clear();
|
||||||
for (Spatial scene : viewPort.getScenes()) {
|
for (Spatial scene : viewPort.getScenes()) {
|
||||||
ShadowUtil.getLitGeometriesInViewPort(scene, viewPort.getCamera(), shadowCams, RenderQueue.ShadowMode.Receive, lightReceivers);
|
ShadowUtil.getLitGeometriesInViewPort(scene, viewPort.getCamera(), shadowCams, RenderQueue.ShadowMode.Receive, lightReceivers);
|
||||||
|
@ -151,7 +151,7 @@ public class SpotLightShadowRenderer extends AbstractShadowRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void getReceivers(GeometryList lightReceivers) {
|
protected void getReceivers(GeometryList lightReceivers) {
|
||||||
lightReceivers.clear();
|
lightReceivers.clear();
|
||||||
Camera[] cameras = new Camera[1];
|
Camera[] cameras = new Camera[1];
|
||||||
cameras[0] = shadowCam;
|
cameras[0] = shadowCam;
|
||||||
|
@ -54,6 +54,8 @@ import java.util.prefs.Preferences;
|
|||||||
*/
|
*/
|
||||||
public final class AppSettings extends HashMap<String, Object> {
|
public final class AppSettings extends HashMap<String, Object> {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
private static final AppSettings defaults = new AppSettings(false);
|
private static final AppSettings defaults = new AppSettings(false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -109,6 +111,33 @@ public final class AppSettings extends HashMap<String, Object> {
|
|||||||
*/
|
*/
|
||||||
public static final String ANDROID_OPENAL_SOFT = "OpenAL_SOFT";
|
public static final String ANDROID_OPENAL_SOFT = "OpenAL_SOFT";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use JogAmp's JOGL as the display system, with the OpenGL forward compatible profile
|
||||||
|
* <p>
|
||||||
|
* N.B: This backend is EXPERIMENTAL
|
||||||
|
*
|
||||||
|
* @see AppSettings#setRenderer(java.lang.String)
|
||||||
|
*/
|
||||||
|
public static final String JOGL_OPENGL_FORWARD_COMPATIBLE = "JOGL_OPENGL_FORWARD_COMPATIBLE";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use JogAmp's JOGL as the display system with the backward compatible profile
|
||||||
|
* <p>
|
||||||
|
* N.B: This backend is EXPERIMENTAL
|
||||||
|
*
|
||||||
|
* @see AppSettings#setRenderer(java.lang.String)
|
||||||
|
*/
|
||||||
|
public static final String JOGL_OPENGL_BACKWARD_COMPATIBLE = "JOGL_OPENGL_BACKWARD_COMPATIBLE";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use JogAmp's JOAL as the display system
|
||||||
|
* <p>
|
||||||
|
* N.B: This backend is EXPERIMENTAL
|
||||||
|
*
|
||||||
|
* @see AppSettings#setRenderer(java.lang.String)
|
||||||
|
*/
|
||||||
|
public static final String JOAL = "JOAL";
|
||||||
|
|
||||||
static {
|
static {
|
||||||
defaults.put("Width", 640);
|
defaults.put("Width", 640);
|
||||||
defaults.put("Height", 480);
|
defaults.put("Height", 480);
|
||||||
@ -118,7 +147,7 @@ public final class AppSettings extends HashMap<String, Object> {
|
|||||||
defaults.put("StencilBits", 0);
|
defaults.put("StencilBits", 0);
|
||||||
defaults.put("Samples", 0);
|
defaults.put("Samples", 0);
|
||||||
defaults.put("Fullscreen", false);
|
defaults.put("Fullscreen", false);
|
||||||
defaults.put("Title", "jMonkey Engine 3.0");
|
defaults.put("Title", JmeVersion.FULL_NAME);
|
||||||
defaults.put("Renderer", LWJGL_OPENGL2);
|
defaults.put("Renderer", LWJGL_OPENGL2);
|
||||||
defaults.put("AudioRenderer", LWJGL_OPENAL);
|
defaults.put("AudioRenderer", LWJGL_OPENAL);
|
||||||
defaults.put("DisableJoysticks", true);
|
defaults.put("DisableJoysticks", true);
|
||||||
|
@ -153,6 +153,10 @@ public abstract class JmeSystemDelegate {
|
|||||||
return false;
|
return false;
|
||||||
} else if (arch.equals("universal")) {
|
} else if (arch.equals("universal")) {
|
||||||
return false;
|
return false;
|
||||||
|
} else if (arch.equals("aarch32")) {
|
||||||
|
return false;
|
||||||
|
} else if (arch.equals("aarch64")) {
|
||||||
|
return true;
|
||||||
} else if (arch.equals("arm")) {
|
} else if (arch.equals("arm")) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
|
66
jme3-core/src/main/java/com/jme3/system/JmeVersion.java
Normal file
66
jme3-core/src/main/java/com/jme3/system/JmeVersion.java
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2015 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.system;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pulls in version info from the version.properties file.
|
||||||
|
*
|
||||||
|
* @author Kirill Vainer
|
||||||
|
*/
|
||||||
|
public class JmeVersion {
|
||||||
|
|
||||||
|
private static final Logger logger = Logger.getLogger(JmeVersion.class.getName());
|
||||||
|
private static final Properties props = new Properties();
|
||||||
|
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
props.load(JmeVersion.class.getResourceAsStream("version.properties"));
|
||||||
|
} catch (IOException ex) {
|
||||||
|
logger.log(Level.WARNING, "Unable to read version info!", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final String BUILD_DATE = props.getProperty("build.date", "1900-01-01");
|
||||||
|
public static final String BRANCH_NAME = props.getProperty("git.branch", "unknown");
|
||||||
|
public static final String GIT_HASH = props.getProperty("git.hash", "");
|
||||||
|
public static final String GIT_SHORT_HASH = props.getProperty("git.hash.short", "");
|
||||||
|
public static final String GIT_TAG = props.getProperty("git.tag", "");
|
||||||
|
public static final String VERSION_NUMBER = props.getProperty("version.number", "");
|
||||||
|
public static final String VERSION_TAG = props.getProperty("version.tag", "");
|
||||||
|
public static final String VERSION_FULL = props.getProperty("version.full", "");
|
||||||
|
public static final String FULL_NAME = props.getProperty("name.full", "jMonkeyEngine (unknown version)");
|
||||||
|
}
|
@ -88,6 +88,11 @@ public enum Platform {
|
|||||||
*/
|
*/
|
||||||
Android_ARM7,
|
Android_ARM7,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Android ARM8
|
||||||
|
*/
|
||||||
|
Android_ARM8,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Android x86
|
* Android x86
|
||||||
*/
|
*/
|
||||||
|
@ -1041,6 +1041,7 @@ public class Image extends NativeObject implements Savable /*, Cloneable*/ {
|
|||||||
capsule.write(mipMapSizes, "mipMapSizes", null);
|
capsule.write(mipMapSizes, "mipMapSizes", null);
|
||||||
capsule.write(multiSamples, "multiSamples", 1);
|
capsule.write(multiSamples, "multiSamples", 1);
|
||||||
capsule.writeByteBufferArrayList(data, "data", null);
|
capsule.writeByteBufferArrayList(data, "data", null);
|
||||||
|
capsule.write(colorSpace, "colorSpace", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void read(JmeImporter e) throws IOException {
|
public void read(JmeImporter e) throws IOException {
|
||||||
@ -1052,6 +1053,7 @@ public class Image extends NativeObject implements Savable /*, Cloneable*/ {
|
|||||||
mipMapSizes = capsule.readIntArray("mipMapSizes", null);
|
mipMapSizes = capsule.readIntArray("mipMapSizes", null);
|
||||||
multiSamples = capsule.readInt("multiSamples", 1);
|
multiSamples = capsule.readInt("multiSamples", 1);
|
||||||
data = (ArrayList<ByteBuffer>) capsule.readByteBufferArrayList("data", null);
|
data = (ArrayList<ByteBuffer>) capsule.readByteBufferArrayList("data", null);
|
||||||
|
colorSpace = capsule.readEnum("colorSpace", ColorSpace.class, null);
|
||||||
|
|
||||||
if (mipMapSizes != null) {
|
if (mipMapSizes != null) {
|
||||||
needGeneratedMips = false;
|
needGeneratedMips = false;
|
||||||
|
@ -316,7 +316,6 @@ public abstract class Texture implements CloneableSmartAsset, Savable, Cloneable
|
|||||||
private MinFilter minificationFilter = MinFilter.BilinearNoMipMaps;
|
private MinFilter minificationFilter = MinFilter.BilinearNoMipMaps;
|
||||||
private MagFilter magnificationFilter = MagFilter.Bilinear;
|
private MagFilter magnificationFilter = MagFilter.Bilinear;
|
||||||
private ShadowCompareMode shadowCompareMode = ShadowCompareMode.Off;
|
private ShadowCompareMode shadowCompareMode = ShadowCompareMode.Off;
|
||||||
private boolean needCompareModeUpdate = false;
|
|
||||||
private int anisotropicFilter;
|
private int anisotropicFilter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -404,7 +403,6 @@ public abstract class Texture implements CloneableSmartAsset, Savable, Cloneable
|
|||||||
"compareMode can not be null.");
|
"compareMode can not be null.");
|
||||||
}
|
}
|
||||||
this.shadowCompareMode = compareMode;
|
this.shadowCompareMode = compareMode;
|
||||||
needCompareModeUpdate = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -489,7 +487,7 @@ public abstract class Texture implements CloneableSmartAsset, Savable, Cloneable
|
|||||||
/**
|
/**
|
||||||
* @return the anisotropic filtering level for this texture. Default value
|
* @return the anisotropic filtering level for this texture. Default value
|
||||||
* is 0 (use value from config),
|
* is 0 (use value from config),
|
||||||
* 1 means 1x (no anisotrophy), 2 means x2, 4 is x4, etc.
|
* 1 means 1x (no anisotropy), 2 means x2, 4 is x4, etc.
|
||||||
*/
|
*/
|
||||||
public int getAnisotropicFilter() {
|
public int getAnisotropicFilter() {
|
||||||
return anisotropicFilter;
|
return anisotropicFilter;
|
||||||
@ -636,14 +634,4 @@ public abstract class Texture implements CloneableSmartAsset, Savable, Cloneable
|
|||||||
magnificationFilter = capsule.readEnum("magnificationFilter",
|
magnificationFilter = capsule.readEnum("magnificationFilter",
|
||||||
MagFilter.class, MagFilter.Bilinear);
|
MagFilter.class, MagFilter.Bilinear);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isNeedCompareModeUpdate() {
|
|
||||||
return needCompareModeUpdate;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void compareModeUpdated() {
|
|
||||||
this.needCompareModeUpdate = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,8 @@ public class DefaultImageRaster extends ImageRaster {
|
|||||||
|
|
||||||
private void rangeCheck(int x, int y) {
|
private void rangeCheck(int x, int y) {
|
||||||
if (x < 0 || y < 0 || x >= width || y >= height) {
|
if (x < 0 || y < 0 || x >= width || y >= height) {
|
||||||
throw new IllegalArgumentException("x and y must be inside the image dimensions");
|
throw new IllegalArgumentException("x and y must be inside the image dimensions:"
|
||||||
|
+ x + ", " + y + " in:" + width + ", " + height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,9 +45,11 @@ public final class LastTextureState {
|
|||||||
public Texture.WrapMode sWrap, tWrap, rWrap;
|
public Texture.WrapMode sWrap, tWrap, rWrap;
|
||||||
public Texture.MagFilter magFilter;
|
public Texture.MagFilter magFilter;
|
||||||
public Texture.MinFilter minFilter;
|
public Texture.MinFilter minFilter;
|
||||||
|
public int anisoFilter;
|
||||||
|
public Texture.ShadowCompareMode shadowCompareMode;
|
||||||
|
|
||||||
public LastTextureState() {
|
public LastTextureState() {
|
||||||
// All parameters initialized to null (meaning unset).
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reset() {
|
public void reset() {
|
||||||
@ -56,5 +58,10 @@ public final class LastTextureState {
|
|||||||
rWrap = null;
|
rWrap = null;
|
||||||
magFilter = null;
|
magFilter = null;
|
||||||
minFilter = null;
|
minFilter = null;
|
||||||
|
anisoFilter = 0;
|
||||||
|
|
||||||
|
// The default in OpenGL is OFF, so we avoid setting this per texture
|
||||||
|
// if its not used.
|
||||||
|
shadowCompareMode = Texture.ShadowCompareMode.Off;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,7 @@ import com.jme3.math.Quaternion;
|
|||||||
import com.jme3.math.Vector2f;
|
import com.jme3.math.Vector2f;
|
||||||
import com.jme3.math.Vector3f;
|
import com.jme3.math.Vector3f;
|
||||||
import com.jme3.math.Vector4f;
|
import com.jme3.math.Vector4f;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.lang.ref.PhantomReference;
|
import java.lang.ref.PhantomReference;
|
||||||
import java.lang.ref.Reference;
|
import java.lang.ref.Reference;
|
||||||
import java.lang.ref.ReferenceQueue;
|
import java.lang.ref.ReferenceQueue;
|
||||||
@ -1010,11 +1011,15 @@ public final class BufferUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static ByteBuffer createByteBuffer(String data) {
|
public static ByteBuffer createByteBuffer(String data) {
|
||||||
byte[] bytes = data.getBytes();
|
try {
|
||||||
|
byte[] bytes = data.getBytes("UTF-8");
|
||||||
ByteBuffer bb = createByteBuffer(bytes.length);
|
ByteBuffer bb = createByteBuffer(bytes.length);
|
||||||
bb.put(bytes);
|
bb.put(bytes);
|
||||||
bb.flip();
|
bb.flip();
|
||||||
return bb;
|
return bb;
|
||||||
|
} catch (UnsupportedEncodingException ex) {
|
||||||
|
throw new UnsupportedOperationException(ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -43,21 +43,6 @@ import java.util.Map.Entry;
|
|||||||
*/
|
*/
|
||||||
public final class ListMap<K, V> extends AbstractMap<K, V> implements Cloneable, Serializable {
|
public final class ListMap<K, V> extends AbstractMap<K, V> implements Cloneable, Serializable {
|
||||||
|
|
||||||
public static void main(String[] args){
|
|
||||||
Map<String, String> map = new ListMap<String, String>();
|
|
||||||
map.put( "bob", "hello");
|
|
||||||
System.out.println(map.get("bob"));
|
|
||||||
map.remove("bob");
|
|
||||||
System.out.println(map.size());
|
|
||||||
|
|
||||||
map.put("abc", "1");
|
|
||||||
map.put("def", "2");
|
|
||||||
map.put("ghi", "3");
|
|
||||||
map.put("jkl", "4");
|
|
||||||
map.put("mno", "5");
|
|
||||||
System.out.println(map.get("ghi"));
|
|
||||||
}
|
|
||||||
|
|
||||||
private final static class ListMapEntry<K, V> implements Map.Entry<K, V>, Cloneable {
|
private final static class ListMapEntry<K, V> implements Map.Entry<K, V>, Cloneable {
|
||||||
|
|
||||||
private final K key;
|
private final K key;
|
||||||
|
@ -42,7 +42,6 @@ import java.io.*;
|
|||||||
public class LittleEndien extends InputStream implements DataInput {
|
public class LittleEndien extends InputStream implements DataInput {
|
||||||
|
|
||||||
protected BufferedInputStream in;
|
protected BufferedInputStream in;
|
||||||
protected BufferedReader inRead;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new LittleEndien reader from the given input stream. The
|
* Creates a new LittleEndien reader from the given input stream. The
|
||||||
@ -51,7 +50,6 @@ public class LittleEndien extends InputStream implements DataInput {
|
|||||||
*/
|
*/
|
||||||
public LittleEndien(InputStream in) {
|
public LittleEndien(InputStream in) {
|
||||||
this.in = new BufferedInputStream(in);
|
this.in = new BufferedInputStream(in);
|
||||||
inRead = new BufferedReader(new InputStreamReader(in));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int read() throws IOException {
|
public int read() throws IOException {
|
||||||
@ -141,7 +139,7 @@ public class LittleEndien extends InputStream implements DataInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String readLine() throws IOException {
|
public String readLine() throws IOException {
|
||||||
return inRead.readLine();
|
throw new IOException("Unsupported operation");
|
||||||
}
|
}
|
||||||
|
|
||||||
public String readUTF() throws IOException {
|
public String readUTF() throws IOException {
|
||||||
|
@ -612,9 +612,9 @@ public class TangentBinormalGenerator {
|
|||||||
normal.normalizeLocal();
|
normal.normalizeLocal();
|
||||||
|
|
||||||
return new TriangleData(
|
return new TriangleData(
|
||||||
tangent,
|
tangent.clone(),
|
||||||
binormal,
|
binormal.clone(),
|
||||||
normal);
|
normal.clone());
|
||||||
} finally {
|
} finally {
|
||||||
tmp.release();
|
tmp.release();
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#import "Common/ShaderLib/GLSLCompat.glsllib"
|
||||||
|
|
||||||
#ifdef TEXTURE
|
#ifdef TEXTURE
|
||||||
uniform sampler2D m_Texture;
|
uniform sampler2D m_Texture;
|
||||||
varying vec2 texCoord;
|
varying vec2 texCoord;
|
||||||
|
@ -6,6 +6,20 @@ MaterialDef Default GUI {
|
|||||||
Boolean VertexColor (UseVertexColor)
|
Boolean VertexColor (UseVertexColor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Technique {
|
||||||
|
VertexShader GLSL150: Common/MatDefs/Gui/Gui.vert
|
||||||
|
FragmentShader GLSL150: Common/MatDefs/Gui/Gui.frag
|
||||||
|
|
||||||
|
WorldParameters {
|
||||||
|
WorldViewProjectionMatrix
|
||||||
|
}
|
||||||
|
|
||||||
|
Defines {
|
||||||
|
TEXTURE : Texture
|
||||||
|
VERTEX_COLOR : VertexColor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Technique {
|
Technique {
|
||||||
VertexShader GLSL100: Common/MatDefs/Gui/Gui.vert
|
VertexShader GLSL100: Common/MatDefs/Gui/Gui.vert
|
||||||
FragmentShader GLSL100: Common/MatDefs/Gui/Gui.frag
|
FragmentShader GLSL100: Common/MatDefs/Gui/Gui.frag
|
||||||
@ -20,7 +34,4 @@ MaterialDef Default GUI {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Technique {
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@ -1,3 +1,5 @@
|
|||||||
|
#import "Common/ShaderLib/GLSLCompat.glsllib"
|
||||||
|
|
||||||
uniform mat4 g_WorldViewProjectionMatrix;
|
uniform mat4 g_WorldViewProjectionMatrix;
|
||||||
uniform vec4 m_Color;
|
uniform vec4 m_Color;
|
||||||
|
|
||||||
|
@ -37,6 +37,7 @@ varying vec3 SpecularSum;
|
|||||||
#endif
|
#endif
|
||||||
#if (defined(PARALLAXMAP) || (defined(NORMALMAP_PARALLAX) && defined(NORMALMAP))) && !defined(VERTEX_LIGHTING)
|
#if (defined(PARALLAXMAP) || (defined(NORMALMAP_PARALLAX) && defined(NORMALMAP))) && !defined(VERTEX_LIGHTING)
|
||||||
uniform float m_ParallaxHeight;
|
uniform float m_ParallaxHeight;
|
||||||
|
varying vec3 vViewDirPrlx;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef LIGHTMAP
|
#ifdef LIGHTMAP
|
||||||
@ -78,18 +79,18 @@ void main(){
|
|||||||
#ifdef STEEP_PARALLAX
|
#ifdef STEEP_PARALLAX
|
||||||
#ifdef NORMALMAP_PARALLAX
|
#ifdef NORMALMAP_PARALLAX
|
||||||
//parallax map is stored in the alpha channel of the normal map
|
//parallax map is stored in the alpha channel of the normal map
|
||||||
newTexCoord = steepParallaxOffset(m_NormalMap, vViewDir, texCoord, m_ParallaxHeight);
|
newTexCoord = steepParallaxOffset(m_NormalMap, vViewDirPrlx, texCoord, m_ParallaxHeight);
|
||||||
#else
|
#else
|
||||||
//parallax map is a texture
|
//parallax map is a texture
|
||||||
newTexCoord = steepParallaxOffset(m_ParallaxMap, vViewDir, texCoord, m_ParallaxHeight);
|
newTexCoord = steepParallaxOffset(m_ParallaxMap, vViewDirPrlx, texCoord, m_ParallaxHeight);
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
#ifdef NORMALMAP_PARALLAX
|
#ifdef NORMALMAP_PARALLAX
|
||||||
//parallax map is stored in the alpha channel of the normal map
|
//parallax map is stored in the alpha channel of the normal map
|
||||||
newTexCoord = classicParallaxOffset(m_NormalMap, vViewDir, texCoord, m_ParallaxHeight);
|
newTexCoord = classicParallaxOffset(m_NormalMap, vViewDirPrlx, texCoord, m_ParallaxHeight);
|
||||||
#else
|
#else
|
||||||
//parallax map is a texture
|
//parallax map is a texture
|
||||||
newTexCoord = classicParallaxOffset(m_ParallaxMap, vViewDir, texCoord, m_ParallaxHeight);
|
newTexCoord = classicParallaxOffset(m_ParallaxMap, vViewDirPrlx, texCoord, m_ParallaxHeight);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
@ -153,8 +154,9 @@ void main(){
|
|||||||
#ifdef VERTEX_LIGHTING
|
#ifdef VERTEX_LIGHTING
|
||||||
vec2 light = vertexLightValues.xy;
|
vec2 light = vertexLightValues.xy;
|
||||||
#ifdef COLORRAMP
|
#ifdef COLORRAMP
|
||||||
light.x = texture2D(m_ColorRamp, vec2(light.x, 0.0)).r;
|
diffuseColor.rgb *= texture2D(m_ColorRamp, vec2(light.x, 0.0)).rgb;
|
||||||
light.y = texture2D(m_ColorRamp, vec2(light.y, 0.0)).r;
|
specularColor.rgb *= texture2D(m_ColorRamp, vec2(light.y, 0.0)).rgb;
|
||||||
|
light.xy = vec2(1.0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
gl_FragColor.rgb = AmbientSum * diffuseColor.rgb +
|
gl_FragColor.rgb = AmbientSum * diffuseColor.rgb +
|
||||||
@ -184,6 +186,7 @@ void main(){
|
|||||||
#ifdef COLORRAMP
|
#ifdef COLORRAMP
|
||||||
diffuseColor.rgb *= texture2D(m_ColorRamp, vec2(light.x, 0.0)).rgb;
|
diffuseColor.rgb *= texture2D(m_ColorRamp, vec2(light.x, 0.0)).rgb;
|
||||||
specularColor.rgb *= texture2D(m_ColorRamp, vec2(light.y, 0.0)).rgb;
|
specularColor.rgb *= texture2D(m_ColorRamp, vec2(light.y, 0.0)).rgb;
|
||||||
|
light.xy = vec2(1.0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Workaround, since it is not possible to modify varying variables
|
// Workaround, since it is not possible to modify varying variables
|
||||||
|
@ -48,6 +48,10 @@ varying vec3 lightVec;
|
|||||||
uniform vec4 g_LightDirection;
|
uniform vec4 g_LightDirection;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if (defined(PARALLAXMAP) || (defined(NORMALMAP_PARALLAX) && defined(NORMALMAP))) && !defined(VERTEX_LIGHTING)
|
||||||
|
varying vec3 vViewDirPrlx;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef USE_REFLECTION
|
#ifdef USE_REFLECTION
|
||||||
uniform vec3 g_CameraPosition;
|
uniform vec3 g_CameraPosition;
|
||||||
|
|
||||||
@ -107,17 +111,25 @@ void main(){
|
|||||||
wvLightPos.w = g_LightPosition.w;
|
wvLightPos.w = g_LightPosition.w;
|
||||||
vec4 lightColor = g_LightColor;
|
vec4 lightColor = g_LightColor;
|
||||||
|
|
||||||
#if defined(NORMALMAP) && !defined(VERTEX_LIGHTING)
|
#if (defined(NORMALMAP) || defined(PARALLAXMAP)) && !defined(VERTEX_LIGHTING)
|
||||||
vec3 wvTangent = normalize(TransformNormal(modelSpaceTan));
|
vec3 wvTangent = normalize(TransformNormal(modelSpaceTan));
|
||||||
vec3 wvBinormal = cross(wvNormal, wvTangent);
|
vec3 wvBinormal = cross(wvNormal, wvTangent);
|
||||||
mat3 tbnMat = mat3(wvTangent, wvBinormal * inTangent.w,wvNormal);
|
mat3 tbnMat = mat3(wvTangent, wvBinormal * inTangent.w,wvNormal);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(NORMALMAP) && !defined(VERTEX_LIGHTING)
|
||||||
vViewDir = -wvPosition * tbnMat;
|
vViewDir = -wvPosition * tbnMat;
|
||||||
|
#if (defined(PARALLAXMAP) || (defined(NORMALMAP_PARALLAX) && defined(NORMALMAP)))
|
||||||
|
vViewDirPrlx = vViewDir;
|
||||||
|
#endif
|
||||||
lightComputeDir(wvPosition, lightColor.w, wvLightPos, vLightDir, lightVec);
|
lightComputeDir(wvPosition, lightColor.w, wvLightPos, vLightDir, lightVec);
|
||||||
vLightDir.xyz = (vLightDir.xyz * tbnMat).xyz;
|
vLightDir.xyz = (vLightDir.xyz * tbnMat).xyz;
|
||||||
#elif !defined(VERTEX_LIGHTING)
|
#elif !defined(VERTEX_LIGHTING)
|
||||||
vNormal = wvNormal;
|
vNormal = wvNormal;
|
||||||
vViewDir = viewDir;
|
vViewDir = viewDir;
|
||||||
|
#if defined(PARALLAXMAP)
|
||||||
|
vViewDirPrlx = -wvPosition * tbnMat;
|
||||||
|
#endif
|
||||||
lightComputeDir(wvPosition, lightColor.w, wvLightPos, vLightDir, lightVec);
|
lightComputeDir(wvPosition, lightColor.w, wvLightPos, vLightDir, lightVec);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
Exception This material definition is deprecated. Please use Unshaded.j3md instead.
|
||||||
MaterialDef Colored Textured {
|
MaterialDef Colored Textured {
|
||||||
|
|
||||||
MaterialParameters {
|
MaterialParameters {
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#import "Common/ShaderLib/GLSLCompat.glsllib"
|
||||||
|
|
||||||
#if defined(HAS_GLOWMAP) || defined(HAS_COLORMAP) || (defined(HAS_LIGHTMAP) && !defined(SEPARATE_TEXCOORD))
|
#if defined(HAS_GLOWMAP) || defined(HAS_COLORMAP) || (defined(HAS_LIGHTMAP) && !defined(SEPARATE_TEXCOORD))
|
||||||
#define NEED_TEXCOORD1
|
#define NEED_TEXCOORD1
|
||||||
#endif
|
#endif
|
||||||
|
@ -54,8 +54,8 @@ MaterialDef Unshaded {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Technique {
|
Technique {
|
||||||
VertexShader GLSL100: Common/MatDefs/Misc/Unshaded.vert
|
VertexShader GLSL150: Common/MatDefs/Misc/Unshaded.vert
|
||||||
FragmentShader GLSL100: Common/MatDefs/Misc/Unshaded.frag
|
FragmentShader GLSL150: Common/MatDefs/Misc/Unshaded.frag
|
||||||
|
|
||||||
WorldParameters {
|
WorldParameters {
|
||||||
WorldViewProjectionMatrix
|
WorldViewProjectionMatrix
|
||||||
@ -76,6 +76,25 @@ MaterialDef Unshaded {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Technique {
|
Technique {
|
||||||
|
VertexShader GLSL100: Common/MatDefs/Misc/Unshaded.vert
|
||||||
|
FragmentShader GLSL100: Common/MatDefs/Misc/Unshaded.frag
|
||||||
|
|
||||||
|
WorldParameters {
|
||||||
|
WorldViewProjectionMatrix
|
||||||
|
ViewProjectionMatrix
|
||||||
|
ViewMatrix
|
||||||
|
}
|
||||||
|
|
||||||
|
Defines {
|
||||||
|
INSTANCING : UseInstancing
|
||||||
|
SEPARATE_TEXCOORD : SeparateTexCoord
|
||||||
|
HAS_COLORMAP : ColorMap
|
||||||
|
HAS_LIGHTMAP : LightMap
|
||||||
|
HAS_VERTEXCOLOR : VertexColor
|
||||||
|
HAS_COLOR : Color
|
||||||
|
NUM_BONES : NumberOfBones
|
||||||
|
DISCARD_ALPHA : AlphaDiscardThreshold
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Technique PreNormalPass {
|
Technique PreNormalPass {
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#import "Common/ShaderLib/GLSLCompat.glsllib"
|
||||||
#import "Common/ShaderLib/Skinning.glsllib"
|
#import "Common/ShaderLib/Skinning.glsllib"
|
||||||
#import "Common/ShaderLib/Instancing.glsllib"
|
#import "Common/ShaderLib/Instancing.glsllib"
|
||||||
|
|
||||||
|
@ -1,35 +1,25 @@
|
|||||||
MaterialDef UnshadedNodes {
|
MaterialDef UnshadedNodes {
|
||||||
|
|
||||||
MaterialParameters {
|
MaterialParameters {
|
||||||
Texture2D ColorMap
|
Texture2D ColorMap
|
||||||
Texture2D LightMap
|
Texture2D LightMap
|
||||||
Color Color (Color)
|
Color Color (Color)
|
||||||
Boolean VertexColor (UseVertexColor)
|
Boolean VertexColor (UseVertexColor)
|
||||||
Boolean SeparateTexCoord
|
Boolean SeparateTexCoord
|
||||||
|
|
||||||
// Alpha threshold for fragment discarding
|
|
||||||
Float AlphaDiscardThreshold (AlphaTestFallOff)
|
Float AlphaDiscardThreshold (AlphaTestFallOff)
|
||||||
|
|
||||||
// For hardware skinning
|
|
||||||
Int NumberOfBones
|
Int NumberOfBones
|
||||||
Matrix4Array BoneMatrices
|
Matrix4Array BoneMatrices
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Technique {
|
Technique {
|
||||||
|
|
||||||
WorldParameters {
|
WorldParameters {
|
||||||
WorldViewProjectionMatrix
|
WorldViewProjectionMatrix
|
||||||
//used for fog
|
|
||||||
WorldViewMatrix
|
WorldViewMatrix
|
||||||
}
|
}
|
||||||
|
|
||||||
VertexShaderNodes {
|
VertexShaderNodes {
|
||||||
ShaderNode GpuSkinning {
|
ShaderNode GpuSkinning {
|
||||||
Definition : BasicGPUSkinning : Common/MatDefs/ShaderNodes/HardwareSkinning/HardwareSkinning.j3sn
|
Definition : BasicGPUSkinning : Common/MatDefs/ShaderNodes/HardwareSkinning/HardwareSkinning.j3sn
|
||||||
Condition : NumberOfBones
|
Condition : NumberOfBones
|
||||||
InputMapping {
|
InputMapping {
|
||||||
modelPosition = Global.position;
|
modelPosition = Global.position
|
||||||
boneMatrices = MatParam.BoneMatrices
|
boneMatrices = MatParam.BoneMatrices
|
||||||
boneWeight = Attr.inHWBoneWeight
|
boneWeight = Attr.inHWBoneWeight
|
||||||
boneIndex = Attr.inHWBoneIndex
|
boneIndex = Attr.inHWBoneIndex
|
||||||
@ -53,20 +43,49 @@ MaterialDef UnshadedNodes {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
FragmentShaderNodes {
|
FragmentShaderNodes {
|
||||||
ShaderNode UnshadedFrag{
|
ShaderNode MatColorMult {
|
||||||
Definition: Unshaded : Common/MatDefs/ShaderNodes/Common/Unshaded.j3sn
|
Definition : ColorMult : Common/MatDefs/ShaderNodes/Basic/ColorMult.j3sn
|
||||||
InputMapping{
|
InputMappings {
|
||||||
texCoord = UnshadedVert.texCoord1: ColorMap
|
color1 = MatParam.Color
|
||||||
vertColor = UnshadedVert.vertColor: VertexColor
|
color2 = Global.outColor
|
||||||
matColor = MatParam.Color: Color
|
|
||||||
colorMap = MatParam.ColorMap: ColorMap
|
|
||||||
color = Global.outColor
|
|
||||||
}
|
}
|
||||||
OutputMapping{
|
OutputMappings {
|
||||||
Global.outColor = color
|
Global.outColor = outColor
|
||||||
}
|
}
|
||||||
|
Condition : Color
|
||||||
|
}
|
||||||
|
ShaderNode VertColorMult {
|
||||||
|
Definition : ColorMult : Common/MatDefs/ShaderNodes/Basic/ColorMult.j3sn
|
||||||
|
InputMappings {
|
||||||
|
color1 = UnshadedVert.vertColor
|
||||||
|
color2 = Global.outColor
|
||||||
|
}
|
||||||
|
OutputMappings {
|
||||||
|
Global.outColor = outColor
|
||||||
|
}
|
||||||
|
Condition : VertexColor
|
||||||
|
}
|
||||||
|
ShaderNode ColorMapTF {
|
||||||
|
Definition : TextureFetch : Common/MatDefs/ShaderNodes/Basic/TextureFetch.j3sn
|
||||||
|
InputMappings {
|
||||||
|
texCoord = UnshadedVert.texCoord1
|
||||||
|
textureMap = MatParam.ColorMap
|
||||||
|
}
|
||||||
|
OutputMappings {
|
||||||
|
}
|
||||||
|
Condition : ColorMap
|
||||||
|
}
|
||||||
|
ShaderNode ColorMapMult {
|
||||||
|
Definition : ColorMult : Common/MatDefs/ShaderNodes/Basic/ColorMult.j3sn
|
||||||
|
InputMappings {
|
||||||
|
color1 = ColorMapTF.outColor
|
||||||
|
color2 = Global.outColor
|
||||||
|
}
|
||||||
|
OutputMappings {
|
||||||
|
Global.outColor = outColor
|
||||||
|
}
|
||||||
|
Condition : ColorMap
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderNode AlphaDiscardThreshold {
|
ShaderNode AlphaDiscardThreshold {
|
||||||
Definition : AlphaDiscard : Common/MatDefs/ShaderNodes/Basic/AlphaDiscard.j3sn
|
Definition : AlphaDiscard : Common/MatDefs/ShaderNodes/Basic/AlphaDiscard.j3sn
|
||||||
Condition : AlphaDiscardThreshold
|
Condition : AlphaDiscardThreshold
|
||||||
@ -75,23 +94,28 @@ MaterialDef UnshadedNodes {
|
|||||||
threshold = MatParam.AlphaDiscardThreshold
|
threshold = MatParam.AlphaDiscardThreshold
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ShaderNode LightMap{
|
ShaderNode LightMapTF {
|
||||||
Definition: LightMapping : Common/MatDefs/ShaderNodes/LightMapping/LightMapping.j3sn
|
Definition : TextureFetch : Common/MatDefs/ShaderNodes/Basic/TextureFetch.j3sn
|
||||||
Condition: LightMap
|
InputMappings {
|
||||||
InputMapping{
|
textureMap = MatParam.LightMap
|
||||||
texCoord = UnshadedVert.texCoord1: !SeparateTexCoord
|
|
||||||
texCoord = UnshadedVert.texCoord2 : SeparateTexCoord
|
texCoord = UnshadedVert.texCoord2 : SeparateTexCoord
|
||||||
lightMap = MatParam.LightMap
|
texCoord = UnshadedVert.texCoord1 : !SeparateTexCoord
|
||||||
color = Global.outColor
|
|
||||||
}
|
}
|
||||||
OutputMapping{
|
OutputMappings {
|
||||||
Global.outColor = color
|
}
|
||||||
|
Condition : LightMap
|
||||||
|
}
|
||||||
|
ShaderNode LightMapMult {
|
||||||
|
Definition : ColorMult : Common/MatDefs/ShaderNodes/Basic/ColorMult.j3sn
|
||||||
|
OutputMappings {
|
||||||
|
Global.outColor = outColor
|
||||||
|
}
|
||||||
|
InputMappings {
|
||||||
|
color1 = LightMapTF.outColor
|
||||||
|
color2 = Global.outColor
|
||||||
|
}
|
||||||
|
Condition : LightMap
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -2,14 +2,15 @@ ShaderNodeDefinitions{
|
|||||||
ShaderNodeDefinition TextureFetch {
|
ShaderNodeDefinition TextureFetch {
|
||||||
Type: Fragment
|
Type: Fragment
|
||||||
Shader GLSL100: Common/MatDefs/ShaderNodes/Basic/texture.frag
|
Shader GLSL100: Common/MatDefs/ShaderNodes/Basic/texture.frag
|
||||||
|
Shader GLSL150: Common/MatDefs/ShaderNodes/Basic/texture15.frag
|
||||||
Documentation{
|
Documentation{
|
||||||
Fetches a color value in the given texture acording to given texture coordinates
|
Fetches a color value in the given texture acording to given texture coordinates
|
||||||
@input texture the texture to read
|
@input textureMap the texture to read
|
||||||
@input texCoord the texture coordinates
|
@input texCoord the texture coordinates
|
||||||
@output outColor the fetched color
|
@output outColor the fetched color
|
||||||
}
|
}
|
||||||
Input {
|
Input {
|
||||||
sampler2D texture
|
sampler2D textureMap
|
||||||
vec2 texCoord
|
vec2 texCoord
|
||||||
}
|
}
|
||||||
Output {
|
Output {
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
void main(){
|
void main(){
|
||||||
outColor = texture2D(texture,texCoord);
|
outColor = texture2D(textureMap,texCoord);
|
||||||
}
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
void main(){
|
||||||
|
outColor = texture(textureMap,texCoord);
|
||||||
|
}
|
@ -1,14 +0,0 @@
|
|||||||
#if _VERSION_ >= 150
|
|
||||||
out vec4 outFragColor;
|
|
||||||
# define texture1D texture
|
|
||||||
# define texture2D texture
|
|
||||||
# define texture3D texture
|
|
||||||
# define texture2DLod texture
|
|
||||||
# if defined VERTEX_SHADER
|
|
||||||
# define varying out
|
|
||||||
# define attribute in
|
|
||||||
# elif defined FRAGMENT_SHADER
|
|
||||||
# define varying in
|
|
||||||
# define gl_FragColor outFragColor
|
|
||||||
# endif
|
|
||||||
#endif
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user