diff --git a/.github/actions/tools/bintray.sh b/.github/actions/tools/bintray.sh
new file mode 100644
index 0000000000..0c7d4e6ddf
--- /dev/null
+++ b/.github/actions/tools/bintray.sh
@@ -0,0 +1,93 @@
+#!/bin/bash
+
+# bintray_createPackage [REPO] [PACKAGE] [USER] [PASSWORD] [GIT REPO] [LICENSE]
+function bintray_createPackage {
+ repo="$1"
+ package="$2"
+ user="$3"
+ password="$4"
+ srcrepo="$5"
+ license="$6"
+
+ repoUrl="https://api.bintray.com/packages/$repo"
+ if [ "`curl -u$user:$password -H Content-Type:application/json -H Accept:application/json \
+ --write-out %{http_code} --silent --output /dev/null -X GET \"$repoUrl/$package\"`" != "200" ];
+ then
+
+ if [ "$srcrepo" != "" -a "$license" != "" ];
+ then
+ echo "Package does not exist... create."
+ data="{
+ \"name\": \"${package}\",
+ \"labels\": [],
+ \"licenses\": [\"${license}\"],
+ \"vcs_url\": \"${srcrepo}\"
+ }"
+
+
+ curl -u$user:$password -H "Content-Type:application/json" -H "Accept:application/json" -X POST \
+ -d "${data}" "$repoUrl"
+ else
+ echo "Package does not exist... you need to specify a repo and license for it to be created."
+ fi
+ else
+ echo "The package already exists. Skip."
+ fi
+}
+
+# uploadFile file destination [REPO] "content" [PACKAGE] [USER] [PASSWORD] [SRCREPO] [LICENSE]
+function bintray_uploadFile {
+ file="$1"
+ dest="$2"
+
+ echo "Upload $file to $dest"
+
+ repo="$3"
+ type="$4"
+ package="$5"
+
+ user="$6"
+ password="$7"
+
+ srcrepo="$8"
+ license="$9"
+ publish="${10}"
+
+ bintray_createPackage $repo $package $user $password $srcrepo $license
+
+ url="https://api.bintray.com/$type/$repo/$package/$dest"
+ if [ "$publish" = "true" ]; then url="$url;publish=1"; fi
+
+ curl -T "$file" -u$user:$password "$url"
+
+}
+
+function bintray_uploadAll {
+ path="$1"
+ destpath="$2"
+ repo="$3"
+ type="$4"
+ package="$5"
+
+ user="$6"
+ password="$7"
+
+ srcrepo="$8"
+ license="$9"
+ publish="${10}"
+
+ cdir="$PWD"
+ cd "$path"
+
+ files="`find . -type f -print`"
+ IFS="
+"
+ set -f
+ for f in $files; do
+ destfile="$destpath/${f:2}"
+ bintray_uploadFile $f $destfile $repo $type $package $user $password $srcrepo $license $publish
+ done
+ set +f
+ unset IFS
+ cd "$cdir"
+}
diff --git a/.github/actions/tools/uploadToMaven.sh b/.github/actions/tools/uploadToMaven.sh
new file mode 100644
index 0000000000..1c817a6152
--- /dev/null
+++ b/.github/actions/tools/uploadToMaven.sh
@@ -0,0 +1,85 @@
+#!/bin/bash
+#############################################
+#
+# Usage
+# uploadAllToMaven path/of/dist/maven https://api.bintray.com/maven/riccardo/sandbox-maven/ riccardo $BINTRAY_PASSWORD gitrepo license
+# Note: gitrepo and license are needed only when uploading to bintray if you want to create missing packages automatically
+# gitrepo must be a valid source repository
+# license must be a license supported by bintray eg "BSD 3-Clause"
+# or
+# uploadAllToMaven path/of/dist/maven $GITHUB_PACKAGE_REPOSITORY user password
+#
+#############################################
+root="`dirname ${BASH_SOURCE[0]}`"
+source $root/bintray.sh
+
+set -e
+function uploadToMaven {
+ file="$1"
+ destfile="$2"
+ repourl="$3"
+ user="$4"
+ password="$5"
+ srcrepo="$6"
+ license="$7"
+
+ auth=""
+
+ if [ "$user" != "token" ];
+ then
+ echo "Upload with username $user and password"
+ auth="-u$user:$password"
+ else
+ echo "Upload with token"
+ auth="-H \"Authorization: token $password\""
+ fi
+
+
+ if [[ $repourl == https\:\/\/api.bintray.com\/* ]];
+ then
+ package="`dirname $destfile`"
+ version="`basename $package`"
+ package="`dirname $package`"
+ package="`basename $package`"
+
+ if [ "$user" = "" -o "$password" = "" ];
+ then
+ echo "Error! You need username and password to upload to bintray"
+ exit 1
+ fi
+ echo "Detected bintray"
+
+ bintrayRepo="${repourl/https\:\/\/api.bintray.com\/maven/}"
+ echo "Create package on $bintrayRepo"
+
+ bintray_createPackage $bintrayRepo $package $user $password $srcrepo $license
+
+ repourl="$repourl/$package"
+ fi
+
+ cmd="curl -T \"$file\" $auth \
+ \"$repourl/$destfile\" \
+ -vvv"
+
+ echo "Run $cmd"
+ eval "$cmd"
+}
+export -f uploadToMaven
+
+function uploadAllToMaven {
+ path="$1"
+ cdir="$PWD"
+ cd "$path"
+ files="`find . \( -name "*.jar" -o -name "*.pom" \) -type f -print`"
+ IFS="
+"
+ set -f
+ for art in $files; do
+ art="${art:2}"
+ uploadToMaven "$art" "$art" ${@:2}
+ done
+ set +f
+ unset IFS
+
+ cd "$cdir"
+}
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
new file mode 100644
index 0000000000..8782a24e63
--- /dev/null
+++ b/.github/workflows/main.yml
@@ -0,0 +1,548 @@
+######################################################################################
+# JME CI/CD
+######################################################################################
+# Quick overview of what is going on in this script:
+# - Build natives for android
+# - Build natives for linux arm
+# - Build natives for windows,mac,linux x86_64 and x86
+# - Merge the natives, build the engine, create the zip release, maven artifacts, javadoc and native snapshot
+# - (only when there is a change in the native code) Deploy the native snapshot to bintray
+# - (only when building a release) Deploy everything else to github releases, github packet registry and bintray
+# - (only when building a release) Update javadoc.jmonkeyengine.org
+# Note:
+# All the actions/upload-artifact and actions/download-artifact steps are used to pass
+# stuff between jobs, github actions has some sort of storage that is local to the
+# running workflow, we use it to store the result of each job since the filesystem
+# is not maintained between jobs.
+################# CONFIGURATIONS #####################################################
+# >> Configure BINTRAY RELEASE & NATIVE SNAPSHOT
+# Configure the following secrets/variables (customize the values with your own)
+# BINTRAY_GENERIC_REPO=riccardoblsandbox/jmonkeyengine-files
+# BINTRAY_MAVEN_REPO=riccardoblsandbox/jmonkeyengine
+# BINTRAY_USER=riccardo
+# BINTRAY_APIKEY=XXXXXX
+# BINTRAY_LICENSE="BSD 3-Clause"
+# >> Configure PACKAGE REGISTRY RELEASE
+# Nothing to do here, everything is autoconfigured to work with the account/org that
+# is running the build.
+# >> Configure JAVADOC
+# JAVADOC_GHPAGES_REPO="riccardoblsandbox/javadoc.jmonkeyengine.org.git"
+# Generate a deloy key
+# ssh-keygen -t rsa -b 4096 -C "actions@users.noreply.github.com" -f javadoc_deploy
+# Set
+# JAVADOC_GHPAGES_DEPLOY_PRIVKEY="......."
+# In github repo -> Settings, use javadoc_deploy.pub as Deploy key with write access
+######################################################################################
+# Resources:
+# - Github actions docs: https://help.github.com/en/articles/about-github-actions
+# - Package registry docs: https://help.github.com/en/articles/about-github-package-registry
+# - Official actions: https://github.com/actions
+# - Community actions: https://github.com/sdras/awesome-actions
+######################################################################################
+# - Riccardo Balbo
+######################################################################################
+
+name: Build jMonkeyEngine
+on:
+ push:
+ branches:
+ - master
+ - newbuild
+ - v3.3.*
+ - v3.2
+ - v3.2.*
+ pull_request:
+ release:
+ types: [published]
+
+jobs:
+
+ # Builds the natives on linux arm
+ BuildLinuxArmNatives:
+ name: Build natives for linux (arm)
+ runs-on: ubuntu-18.04
+ container:
+ image: riccardoblb/buildenv-jme3:linuxArm
+
+ steps:
+ - name: Clone the repo
+ uses: actions/checkout@v1
+ with:
+ fetch-depth: 1
+
+ - name: Build
+ run: |
+ # Build
+ # Note: since this is crossbuild we use the buildForPlatforms filter to tell
+ # the buildscript wich platforms it should build for.
+ gradle -PuseCommitHashAsVersionName=true --no-daemon -PbuildForPlatforms=LinuxArm,LinuxArmHF,LinuxArm64 -PbuildNativeProjects=true \
+ :jme3-bullet-native:assemble
+
+ - name: Upload natives
+ uses: actions/upload-artifact@master
+ with:
+ name: linuxarm-natives
+ path: build/native
+
+ # Build the natives on android
+ BuildAndroidNatives:
+ name: Build natives for android
+ runs-on: ubuntu-18.04
+ container:
+ image: riccardoblb/buildenv-jme3:android
+
+ steps:
+ - name: Clone the repo
+ uses: actions/checkout@v1
+ with:
+ fetch-depth: 1
+
+ - name: Build
+ run: |
+ gradle -PuseCommitHashAsVersionName=true --no-daemon -PbuildNativeProjects=true \
+ :jme3-android-native:assemble \
+ :jme3-bullet-native-android:assemble
+
+ - name: Upload natives
+ uses: actions/upload-artifact@master
+ with:
+ name: android-natives
+ path: build/native
+
+ # Build the natives
+ BuildNatives:
+ strategy:
+ fail-fast: true
+ matrix:
+ os: [ubuntu-18.04,windows-2019,macOS-latest]
+ jdk: [8.x.x]
+ include:
+ - os: ubuntu-18.04
+ osName: linux
+ - os: windows-2019
+ osName: windows
+ - os: macOS-latest
+ osName: mac
+
+ name: Build natives for ${{ matrix.osName }}
+ runs-on: ${{ matrix.os }}
+ steps:
+
+ - name: Clone the repo
+ uses: actions/checkout@v1
+ with:
+ fetch-depth: 1
+
+ - name: Prepare java environment
+ uses: actions/setup-java@v1
+ with:
+ java-version: ${{ matrix.jdk }}
+ architecture: x64
+
+ - name: Build Natives
+ shell: bash
+ env:
+ OS_NAME: ${{ matrix.osName }}
+ run: |
+ # Install dependencies
+ if [ "$OS_NAME" = "mac" ];
+ then
+ echo "Prepare mac"
+
+ elif [ "$OS_NAME" = "linux" ];
+ then
+ echo "Prepare linux"
+ sudo apt-get update
+ sudo apt-get install -y gcc-multilib g++-multilib
+ else
+ echo "Prepare windows"
+ fi
+
+ # Build
+ gradle -PuseCommitHashAsVersionName=true --no-daemon -PbuildNativeProjects=true -Dmaven.repo.local="$PWD/dist/maven" \
+ build \
+ :jme3-bullet-native:build
+
+ # Upload natives to be used later by the BuildJMonkey job
+ - name: Upload natives
+ uses: actions/upload-artifact@master
+ with:
+ name: ${{ matrix.osName }}-natives
+ path: build/native
+
+
+ # Build the engine, we only deploy from ubuntu-18.04 jdk8
+ BuildJMonkey:
+ needs: [BuildNatives,BuildAndroidNatives]
+ name: Build on ${{ matrix.osName }} jdk${{ matrix.jdk }}
+ runs-on: ${{ matrix.os }}
+ strategy:
+ fail-fast: true
+ matrix:
+ os: [ubuntu-18.04,windows-2019,macOS-latest]
+ jdk: [8.x.x,11.x.x]
+ include:
+ - os: ubuntu-18.04
+ osName: linux
+ deploy: true
+ - os: windows-2019
+ osName: windows
+ - os: macOS-latest
+ osName: mac
+ - jdk: 11.x.x
+ deploy: false
+
+ steps:
+ - name: Clone the repo
+ uses: actions/checkout@v1
+ with:
+ fetch-depth: 1
+
+ - name: Setup the java environment
+ uses: actions/setup-java@v1
+ with:
+ java-version: ${{ matrix.jdk }}
+ architecture: x64
+
+ - name: Download natives for linux
+ uses: actions/download-artifact@master
+ with:
+ name: linux-natives
+ path: build/native
+
+ - name: Download natives for windows
+ uses: actions/download-artifact@master
+ with:
+ name: windows-natives
+ path: build/native
+
+ - name: Download natives for mac
+ uses: actions/download-artifact@master
+ with:
+ name: mac-natives
+ path: build/native
+
+ - name: Download natives for android
+ uses: actions/download-artifact@master
+ with:
+ name: android-natives
+ path: build/native
+
+ - name: Download natives for linux (arm)
+ uses: actions/download-artifact@master
+ with:
+ name: linuxarm-natives
+ path: build/native
+
+ - name: Build Engine
+ shell: bash
+ run: |
+ # Build
+ gradle -PuseCommitHashAsVersionName=true -PskipPrebuildLibraries=true build
+
+ if [ "${{ matrix.deploy }}" = "true" ];
+ then
+ # We are going to need "zip"
+ sudo apt-get update
+ sudo apt-get install -y zip
+
+ # Create the zip release and the javadoc
+ gradle -PuseCommitHashAsVersionName=true -PskipPrebuildLibraries=true mergedJavadoc createZipDistribution
+
+ # We prepare the release for deploy
+ mkdir -p ./dist/release/
+ mv build/distributions/*.zip dist/release/
+
+ # Create the maven artifacts
+ mkdir -p ./dist/maven/
+ gradle -PuseCommitHashAsVersionName=true -PskipPrebuildLibraries=true install -Dmaven.repo.local="$PWD/dist/maven"
+
+ # Zip the natives into a single archive (we are going to use this to deploy native snapshots)
+ echo "Create native zip"
+ cdir="$PWD"
+ cd "build/native"
+ zip -r "$cdir/dist/jme3-natives.zip" *
+ cd "$cdir"
+ echo "Done"
+ fi
+
+ # Used later by DeploySnapshot
+ - name: Upload merged natives
+ if: matrix.deploy==true
+ uses: actions/upload-artifact@master
+ with:
+ name: natives
+ path: dist/jme3-natives.zip
+
+ # Upload maven artifacts to be used later by the deploy job
+ - name: Upload maven artifacts
+ if: matrix.deploy==true
+ uses: actions/upload-artifact@master
+ with:
+ name: maven
+ path: dist/maven
+
+ - name: Upload javadoc
+ if: matrix.deploy==true
+ uses: actions/upload-artifact@master
+ with:
+ name: javadoc
+ path: dist/javadoc
+
+ # Upload release archive to be used later by the deploy job
+ - name: Upload release
+ if: github.event_name == 'release' && matrix.deploy==true
+ uses: actions/upload-artifact@master
+ with:
+ name: release
+ path: dist/release
+
+ # This job deploys the native snapshot.
+ # The snapshot is downloaded when people build the engine without setting buildNativeProject
+ # this is useful for people that want to build only the java part and don't have
+ # all the stuff needed to compile natives.
+ DeploySnapshot:
+ needs: [BuildJMonkey]
+ name: "Deploy snapshot"
+ runs-on: ubuntu-18.04
+ if: github.event_name == 'push'
+ steps:
+
+ # We clone the repo manually, since we are going to push back a reference to the snapshot
+ - name: Clone the repo
+ run: |
+ branch="${GITHUB_REF//refs\/heads\//}"
+ if [ "$branch" != "" ];
+ then
+ git clone --single-branch --branch "$branch" https://github.com/${GITHUB_REPOSITORY}.git .
+ fi
+
+ - name: Download merged natives
+ uses: actions/download-artifact@master
+ with:
+ name: natives
+ path: dist/
+
+ - name: Deploy natives snapshot
+ run: |
+ source .github/actions/tools/bintray.sh
+ NATIVE_CHANGES="yes"
+ branch="${GITHUB_REF//refs\/heads\//}"
+ if [ "$branch" != "" ];
+ then
+ if [ -f "natives-snapshot.properties" ];
+ then
+ nativeSnapshot=`cat "natives-snapshot.properties"`
+ nativeSnapshot="${nativeSnapshot#*=}"
+
+ # We deploy ONLY if GITHUB_SHA (the current commit hash) is newer than $nativeSnapshot
+ if [ "`git rev-list --count $nativeSnapshot..$GITHUB_SHA`" = "0" ];
+ then
+ NATIVE_CHANGES=""
+ else
+ # We check if the native code changed.
+ echo "Detect changes"
+ NATIVE_CHANGES="$(git diff-tree --name-only "$GITHUB_SHA" "$nativeSnapshot" -- jme3-bullet-native/)"
+ if [ "$NATIVE_CHANGES" = "" ];then NATIVE_CHANGES="$(git diff-tree --name-only "$GITHUB_SHA" "$nativeSnapshot" -- jme3-android-native/)"; fi
+ if [ "$NATIVE_CHANGES" = "" ];then NATIVE_CHANGES="$(git diff-tree --name-only "$GITHUB_SHA" "$nativeSnapshot" -- jme3-bullet-native-android/)"; fi
+ if [ "$NATIVE_CHANGES" = "" ];then NATIVE_CHANGES="$(git diff-tree --name-only "$GITHUB_SHA" "$nativeSnapshot" -- jme3-bullet/)"; fi
+ fi
+ fi
+
+ # We do nothing if there is no change
+ if [ "$NATIVE_CHANGES" = "" ];
+ then
+ echo "No changes, skip."
+ else
+ if [ "${{ secrets.BINTRAY_GENERIC_REPO }}" = "" ];
+ then
+ echo "Configure the following secrets to enable native snapshot deployment"
+ echo "BINTRAY_GENERIC_REPO, BINTRAY_USER, BINTRAY_APIKEY"
+ else
+ # Deploy snapshot
+ bintray_uploadFile dist/jme3-natives.zip \
+ $GITHUB_SHA/$GITHUB_SHA/jme3-natives.zip \
+ ${{ secrets.BINTRAY_GENERIC_REPO }} "content" "natives" \
+ ${{ secrets.BINTRAY_USER }} \
+ ${{ secrets.BINTRAY_APIKEY }} \
+ "https://github.com/${GITHUB_REPOSITORY}" \
+ "${{ secrets.BINTRAY_LICENSE }}" "true"
+
+ # We reference the snapshot by writing its commit hash in natives-snapshot.properties
+ echo "natives.snapshot=$GITHUB_SHA" > natives-snapshot.properties
+
+ # We commit the updated natives-snapshot.properties
+ git config --global user.name "Github Actions"
+ git config --global user.email "actions@users.noreply.github.com"
+
+ git add natives-snapshot.properties
+
+ git commit -m "[skip ci] update natives snapshot"
+
+ # Pull rebase from the remote repo, just in case there was a push in the meantime
+ git pull -q --rebase
+
+ # We need to calculate the header for git authentication
+ header=$(echo -n "ad-m:${{ secrets.GITHUB_TOKEN }}" | base64)
+
+ # Push
+ (git -c http.extraheader="AUTHORIZATION: basic $header" push origin "$branch" || true)
+
+ fi
+ fi
+ fi
+
+ # This job deploys the release
+ DeployRelease:
+ needs: [BuildJMonkey]
+ name: Deploy Release
+ runs-on: ubuntu-18.04
+ if: github.event_name == 'release'
+ steps:
+
+ # We need to clone everything again for uploadToMaven.sh ...
+ - name: Clone the repo
+ uses: actions/checkout@v1
+ with:
+ fetch-depth: 1
+
+ # Download all the stuff...
+ - name: Download maven artifacts
+ uses: actions/download-artifact@master
+ with:
+ name: maven
+ path: dist/maven
+
+ - name: Download release
+ uses: actions/download-artifact@master
+ with:
+ name: release
+ path: dist/release
+
+ - name: Deploy to github releases
+ run: |
+ # We need to get the release id (yeah, it's not the same as the tag)
+ echo "${GITHUB_EVENT_PATH}"
+ cat ${GITHUB_EVENT_PATH}
+ releaseId=$(jq --raw-output '.release.id' ${GITHUB_EVENT_PATH})
+
+ # Now that we have the id, we just upload the release zip from before
+ echo "Upload to release $releaseId"
+ filename="$(ls dist/release/*.zip)"
+ url="https://uploads.github.com/repos/${GITHUB_REPOSITORY}/releases/$releaseId/assets?name=$(basename $filename)"
+ echo "Upload to $url"
+ curl -L \
+ -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
+ -H "Content-Type: application/zip" \
+ --data-binary @"$filename" \
+ "$url"
+
+ - name: Deploy to bintray
+ run: |
+ source .github/actions/tools/uploadToMaven.sh
+ if [ "${{ secrets.BINTRAY_MAVEN_REPO }}" = "" ];
+ then
+ echo "Configure the following secrets to enable bintray deployment"
+ echo "BINTRAY_MAVEN_REPO, BINTRAY_USER, BINTRAY_APIKEY"
+ else
+ uploadAllToMaven dist/maven/ https://api.bintray.com/maven/${{ secrets.BINTRAY_MAVEN_REPO }} ${{ secrets.BINTRAY_USER }} ${{ secrets.BINTRAY_APIKEY }} "https://github.com/${GITHUB_REPOSITORY}" "${{ secrets.BINTRAY_LICENSE }}"
+ fi
+
+ # - name: Deploy to github package registry
+ # run: |
+ # source .github/actions/tools/uploadToMaven.sh
+ # registry="https://maven.pkg.github.com/$GITHUB_REPOSITORY"
+ # echo "Deploy to github package registry $registry"
+ # uploadAllToMaven dist/maven/ $registry "token" ${{ secrets.GITHUB_TOKEN }}
+
+ # Deploy the javadoc
+ DeployJavaDoc:
+ needs: [BuildJMonkey]
+ name: Deploy Javadoc
+ runs-on: ubuntu-18.04
+ if: github.event_name == 'release'
+ steps:
+
+ # We are going to need a deploy key for this, since we need
+ # to push to a different repo
+ - name: Set ssh key
+ run: |
+ mkdir -p ~/.ssh/
+ echo "${{ secrets.JAVADOC_GHPAGES_DEPLOY_PRIVKEY }}" > $HOME/.ssh/deploy.key
+ chmod 600 $HOME/.ssh/deploy.key
+
+ # We clone the javadoc repo
+ - name: Clone gh-pages
+ run: |
+ branch="gh-pages"
+ export GIT_SSH_COMMAND="ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i $HOME/.ssh/deploy.key"
+ git clone --single-branch --branch "$branch" git@github.com:${{ secrets.JAVADOC_GHPAGES_REPO }} .
+
+ # Download the javadoc in the new directory "newdoc"
+ - name: Download javadoc
+ uses: actions/download-artifact@master
+ with:
+ name: javadoc
+ path: newdoc
+
+ # The actual deploy
+ - name: Deploy to github pages
+ run: |
+ set -f
+ IFS=$'\n'
+
+ # Get the tag for this release
+ version="`if [[ $GITHUB_REF == refs\/tags* ]]; then echo ${GITHUB_REF//refs\/tags\//}; fi`"
+
+ # If there is no tag, then we do nothing.
+ if [ "$version" != "" ];
+ then
+ echo "Deploy as $version"
+
+ # Remove any older version of the javadoc for this tag
+ if [ -d "$version" ];then rm -Rf "$version"; fi
+
+ # Rename newdoc with the version name
+ mv newdoc "$version"
+
+ # if there isn't an index.txt we create one (we need this to list the versions)
+ if [ ! -f "index.txt" ]; then echo "" > index.txt ; fi
+ index="`cat index.txt`"
+
+ # Check if this version is already in index.txt
+ addNew=true
+ for v in $index;
+ do
+ if [ "$v" = "$version" ];
+ then
+ echo "$v" "$version"
+ addNew=false
+ break
+ fi
+ done
+
+ # If not, we add it to the beginning
+ if [ "$addNew" = "true" ];
+ then
+ echo -e "$version\n$index" > index.txt
+ index="`cat index.txt`"
+ fi
+
+ # Regenerate the pages
+ chmod +x make.sh
+ ./make.sh
+
+ # Configure git to use the deploy key
+ export GIT_SSH_COMMAND="ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i $HOME/.ssh/deploy.key"
+
+ # Commit the changes
+ git config --global user.name "Github Actions"
+ git config --global user.email "actions@users.noreply.github.com"
+
+ git add .
+ git commit -m "$version"
+
+ branch="gh-pages"
+ git push origin "$branch" --force
+
+ fi
diff --git a/.gitignore b/.gitignore
index 6bed74f10e..1e5bf3f071 100644
--- a/.gitignore
+++ b/.gitignore
@@ -33,15 +33,7 @@
/jme3-android-native/OpenALSoft.zip
/jme3-android-native/src/native/jme_decode/STBI/
/jme3-android-native/src/native/jme_decode/Tremor/
-/jme3-android-native/src/native/jme_decode/com_jme3_audio_plugins_NativeVorbisFile.h
-/jme3-android-native/src/native/jme_decode/com_jme3_texture_plugins_AndroidNativeImageLoader.h
/jme3-android-native/stb_image.h
-!/jme3-bullet-native/libs/native/windows/x86_64/bulletjme.dll
-!/jme3-bullet-native/libs/native/windows/x86/bulletjme.dll
-!/jme3-bullet-native/libs/native/osx/x86/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_64/libbulletjme.so
/jme3-examples/private/
!/jme3-vr/src/main/resources/**/*.dylib
!/jme3-vr/src/main/resources/**/*.so
@@ -49,4 +41,8 @@
!/jme3-vr/src/main/resources/**/*.dll
!/jme3-vr/src/main/resources/**/*.pdb
/buildMaven.bat
-
+/private
+.travis.yml
+appveyor.yml
+javadoc_deploy
+javadoc_deploy.pub
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index c0e3bd6e9b..0000000000
--- a/.travis.yml
+++ /dev/null
@@ -1,85 +0,0 @@
-language: java
-sudo: true
-
-branches:
- only:
- - master
- - /^v3.3.*$/
- - v3.2
- - /^v3.2.*$/
-
-matrix:
- include:
- - os: linux
- jdk: oraclejdk8
- env: UPLOAD=true UPLOAD_NATIVE=true
- - os: linux
- jdk: openjdk11
- dist: xenial
- - os: osx
- osx_image: xcode9.3
- env: UPLOAD_NATIVE=true
-
-addons:
- ssh_known_hosts: github.com
- hosts:
- - travisci
- hostname: travisci
- apt:
- packages:
- - gcc-multilib
- - g++-multilib
-
-before_install:
- - '[ -n "$UPLOAD" ] && git fetch --unshallow || :'
-
-before_cache:
- - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
- - rm -fr $HOME/.gradle/caches/*/plugin-resolution/
-
-cache:
- directories:
- - $HOME/.gradle/caches/
- - $HOME/.gradle/wrapper/
-
-install:
- - '[ -n "$UPLOAD_NATIVE" ] && ./gradlew -PbuildNativeProjects=true assemble || ./gradlew assemble'
-
-script:
- - ./gradlew check
-
-after_success:
- - '[ "$TRAVIS_PULL_REQUEST" == "false" ] && [ -n "$UPLOAD_NATIVE" ] && ./private/upload_native.sh || :'
- - '[ -n "$TRAVIS_TAG" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ] && [ -n "$UPLOAD" ] && ./gradlew bintrayUpload || :'
-
-notifications:
- slack:
- on_success: change
- on_failure: always
- rooms:
- secure: "PWEk4+VL986c3gAjWp12nqyifvxCjBqKoESG9d7zWh1uiTLadTHhZJRMdsye36FCpz/c/Jt7zCRO/5y7FaubQptnRrkrRfjp5f99MJRzQVXnUAM+y385qVkXKRKd/PLpM7XPm4AvjvxHCyvzX2wamRvul/TekaXKB9Ti5FCN87s="
-
-before_deploy:
- - ./gradlew createZipDistribution
- - export RELEASE_DIST=$(ls build/distributions/*.zip)
-
-deploy:
- provider: releases
- api_key:
- secure: PuEsJd6juXBH29ByITW3ntSAyrwWs0IeFvXJ5Y2YlhojhSMtTwkoWeB6YmDJWP4fhzbajk4TQ1HlOX2IxJXSW/8ShOEIUlGXz9fHiST0dkSM+iRAUgC5enCLW5ITPTiem7eY9ZhS9miIam7ngce9jHNMh75PTzZrEJtezoALT9w=
- file_glob: true
- file: "${RELEASE_DIST}"
- skip_cleanup: true
- on:
- repo: jMonkeyEngine/jmonkeyengine
- tags: true
-
-# before_install:
- # required libs for android build tools
- # sudo apt-get update
- # sudo apt-get install -qq p7zip-full
- # sudo apt-get install -qq --force-yes libgd2-xpm ia32-libs ia32-libs-multiarch
- # newest Android NDK
- # wget http://dl.google.com/android/ndk/android-ndk-r10c-linux-x86_64.bin -O ndk.bin
- # 7z x ndk.bin -y > /dev/null
- # export ANDROID_NDK=`pwd`/android-ndk-r10c
\ No newline at end of file
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 7234481dd8..47fd3f7002 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -9,6 +9,8 @@ Communication always comes first. **All** code changes and other contributions s
### New Contributors
+Check out the [Projects](https://github.com/jMonkeyEngine/jmonkeyengine/projects/1) tab, where the team has prioritized issues that you as a new contributor can undertake that will familiarize you to the workflow of contributing. This highlights some issues the team thinks would be a good start for new contributors but you are free to contribute on any other issues or integration you wish.
+
When you're ready to submit your code, just make a [pull request](https://help.github.com/articles/using-pull-requests).
- Do not commit your code until you have received proper feedback.
@@ -22,6 +24,15 @@ p.s. We will try hold ourselves to a [certain standard](http://www.defmacro.org/
Developers in the Contributors team can push directly to Main instead of submitting pull requests, however for new features it is often a good idea to do a pull request as a means to get a last code review.
+## Customs around integration, branching, tagging, and releases
+
+- Most pull requests are integrated directly into the master branch of the repository.
+- Integrators should note, unless the history of the pull request is important, it should be integrated to a single commit using “squash and merge”. If the history is important, favor “rebase and merge”. Don’t create a merge commit unless GitHub cannot rebase the PR.
+- For each major release (such as v3.0 or v3.3), an appropriately named release branch is created in the repository.
+- For each minor (or “dot-dot”) release (such as v3.2.3), an appropriately named tag is created in the repository.
+- In general, library changes that plausibly might break existing apps appear only in major releases, not minor ones.
+
+
## Building the engine
1. Install [Gradle](http://www.gradle.org/)
diff --git a/README.md b/README.md
index d6f6517589..bc63883568 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,9 @@
jMonkeyEngine
=============
-[](https://travis-ci.org/jMonkeyEngine/jmonkeyengine)
+[](https://github.com/jMonkeyEngine/jmonkeyengine/actions)
-jMonkeyEngine is a 3D game engine for adventurous Java developers. It’s open-source, cross-platform, and cutting-edge. 3.2.2 is the latest stable version of the jMonkeyEngine 3 SDK, a complete game development suite. We'll release 3.2.x updates until the major 3.3 release arrives.
+jMonkeyEngine is a 3-D game engine for adventurous Java developers. It’s open-source, cross-platform, and cutting-edge. 3.2.4 is the latest stable version of the jMonkeyEngine 3 SDK, a complete game development suite. We'll release 3.2.x updates until the major 3.3 release arrives.
The engine is used by several commercial game studios and computer-science courses. Here's a taste:
@@ -11,17 +11,15 @@ The engine is used by several commercial game studios and computer-science cours
- [jME powered games on IndieDB](http://www.indiedb.com/engines/jmonkeyengine/games)
- [Maker's Tale](http://steamcommunity.com/sharedfiles/filedetails/?id=93461954t)
- - [Boardtastic 2](https://play.google.com/store/apps/details?id=com.boardtastic.skateboarding)
- - [Copod](http://herebeben.com/copod)
- - [Attack of the Gelatinous Blob](http://attackofthegelatinousblob.com/)
- - [Chaos](http://4realms.net/)
+ - [Boardtastic 2](https://boardtastic-2.fileplanet.com/apk)
+ - [Attack of the Gelatinous Blob](https://attack-gelatinous-blob.softwareandgames.com/)
- [Mythruna](http://mythruna.com/)
- - [PirateHell](http://www.desura.com/games/piratehell)
- - [3089 (on steam)](http://store.steampowered.com/app/263360/)
- - [3079 (on steam)](http://store.steampowered.com/app/259620/)
- - [Lightspeed Frontier](http://www.lightspeedfrontier.com/)
+ - [PirateHell (on Steam)](https://store.steampowered.com/app/321080/Pirate_Hell/)
+ - [3089 (on Steam)](http://store.steampowered.com/app/263360/)
+ - [3079 (on Steam)](http://store.steampowered.com/app/259620/)
+ - [Lightspeed Frontier (on Steam)](https://store.steampowered.com/app/548650/Lightspeed_Frontier/)
- [Skullstone](http://www.skullstonegame.com/)
- - [Spoxel](https://store.steampowered.com/app/746880/Spoxel/)
+ - [Spoxel (on Steam)](https://store.steampowered.com/app/746880/Spoxel/)
## Getting started
diff --git a/appveyor.yml b/appveyor.yml
deleted file mode 100644
index 00c9d5c265..0000000000
--- a/appveyor.yml
+++ /dev/null
@@ -1,63 +0,0 @@
-version: 1.0.{build}.{branch}
-
-branches:
- only:
- - master
- - v3.2
-
-only_commits:
- files:
- - jme3-bullet-native/
- - appveyor.yml
- - gradle.properties
-
-skip_tags: true
-
-max_jobs: 1
-
-clone_depth: 1
-
-image: Visual Studio 2013
-
-environment:
- encrypted_f0a0b284e2e8_iv:
- secure: aImQXs4g7zMXm1nWRvlh2wPK1UQvozS1fOVNthpyoEDFZ2FvBSdXqh5NPbGh44+F
- encrypted_f0a0b284e2e8_key:
- secure: Ek2lqC2e19qQDRRdlvnYyLFBq3TNj6YwKTAPuJ2VElJsxi9lQg+9ZP+VbP4kbHTx6Zaa++vtmOuxLZL7gdILrEEPa1Jix2BBLBfcxBUxe6w=
-
-install:
-- cmd: >-
- set GRADLE_LOCK=C:\Users\appveyor\.gradle\caches\modules-2\modules-2.lock
-
- if exist %GRADLE_LOCK% del %GRADLE_LOCK%
-
-build_script:
- - cmd: gradlew.bat -PbuildNativeProjects=true :jme3-bullet-native:assemble
-
-cache:
-- C:\Users\appveyor\.gradle\caches
-- C:\Users\appveyor\.gradle\wrapper
-- jme3-bullet-native\bullet3.zip -> gradle.properties
-
-test: off
-deploy: off
-
-on_success:
-- cmd: >-
- if not defined encrypted_f0a0b284e2e8_key appveyor exit
-
- openssl aes-256-cbc -K %encrypted_f0a0b284e2e8_key% -iv %encrypted_f0a0b284e2e8_iv% -in private\key.enc -out c:\users\appveyor\.ssh\id_rsa -d
-
- git config --global user.email "appveyor"
-
- git config --global user.name "appveyor"
-
- git checkout -q %APPVEYOR_REPO_BRANCH%
-
- git add -- jme3-bullet-native/libs/native/windows/
-
- git commit -m "[ci skip] bullet: update windows natives"
-
- git pull -q --rebase
-
- git push git@github.com:jMonkeyEngine/jmonkeyengine.git
diff --git a/build.gradle b/build.gradle
index 3ccd202a90..db97fb4756 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,3 +1,6 @@
+import java.nio.file.Files;
+import java.nio.file.StandardCopyOption;
+
buildscript {
repositories {
google()
@@ -9,6 +12,13 @@ buildscript {
}
}
+allprojects {
+ repositories {
+ google()
+ jcenter()
+ }
+}
+
apply plugin: 'base'
apply from: file('version.gradle')
@@ -102,8 +112,8 @@ task mergedJavadoc(type: Javadoc, description: 'Creates Javadoc from all the pro
source subprojects.collect {project ->
project.sourceSets*.allJava
}
-// classpath = files(subprojects.collect {project ->
-// project.sourceSets*.compileClasspath})
+ classpath = files(subprojects.collect {project ->
+ project.sourceSets*.compileClasspath})
// source {
// subprojects*.sourceSets*.main*.allSource
// }
@@ -112,6 +122,11 @@ task mergedJavadoc(type: Javadoc, description: 'Creates Javadoc from all the pro
}
}
+clean.dependsOn('cleanMergedJavadoc')
+task cleanMergedJavadoc(type: Delete) {
+ delete file('dist/javadoc')
+}
+
task mergedSource(type: Copy){
}
@@ -141,6 +156,64 @@ task configureAndroidNDK {
}
}
+gradle.rootProject.ext.set("usePrebuildNatives", buildNativeProjects!="true");
+
+if(skipPrebuildLibraries!="true"&&buildNativeProjects!="true"){
+ String rootPath = rootProject.projectDir.absolutePath
+
+ Properties nativesSnasphotProp = new Properties()
+ File nativesSnasphotPropF=new File("${rootPath}/natives-snapshot.properties");
+
+ if(nativesSnasphotPropF.exists()){
+
+ nativesSnasphotPropF.withInputStream { nativesSnasphotProp.load(it) }
+
+ String nativesSnasphot=nativesSnasphotProp.getProperty("natives.snapshot");
+ String nativesUrl=PREBUILD_NATIVES_URL.replace('${natives.snapshot}',nativesSnasphot)
+ println "Use natives snapshot: "+nativesUrl
+
+ String nativesZipFile="${rootPath}" + File.separator + "build"+ File.separator +nativesSnasphot+"-natives.zip"
+ String nativesPath="${rootPath}" + File.separator + "build"+ File.separator +"native"
+
+
+ task getNativesZipFile {
+ outputs.file nativesZipFile
+ doFirst {
+ File target = file(nativesZipFile);
+ println("Download natives from "+nativesUrl+" to "+nativesZipFile);
+ target.getParentFile().mkdirs();
+ ant.get(src: nativesUrl, dest: target);
+ }
+ }
+
+ task extractPrebuiltNatives {
+ inputs.file nativesZipFile
+ outputs.dir nativesPath
+ dependsOn getNativesZipFile
+
+ doFirst {
+ for(File src : zipTree(nativesZipFile)){
+ String srcRel=src.getAbsolutePath().substring((int)(nativesZipFile.length()+1));
+ srcRel=srcRel.substring(srcRel.indexOf( File.separator)+1);
+
+ File dest=new File(nativesPath+File.separator+srcRel);
+ boolean doCopy = !(dest.exists() && dest.lastModified() > src.lastModified())
+ if (doCopy) {
+ println("Copy "+src+" "+dest);
+ dest.getParentFile().mkdirs();
+ Files.copy(src.toPath(), dest.toPath(), StandardCopyOption.REPLACE_EXISTING);
+ }
+ }
+ }
+ }
+ build.dependsOn extractPrebuiltNatives
+ }
+}
+
+
+
+
+
//class IncrementalReverseTask extends DefaultTask {
// @InputDirectory
// def File inputDir
diff --git a/common-android-app.gradle b/common-android-app.gradle
index ff5dea0b16..35d5ecaf7a 100644
--- a/common-android-app.gradle
+++ b/common-android-app.gradle
@@ -1,7 +1,7 @@
apply plugin: 'com.android.application'
group = 'org.jmonkeyengine'
-version = jmeVersion + '-' + jmeVersionTag
+version = jmeFullVersion
sourceCompatibility = '1.6'
diff --git a/common.gradle b/common.gradle
index 80b22904d7..21ffc4d015 100644
--- a/common.gradle
+++ b/common.gradle
@@ -3,10 +3,11 @@
//
apply plugin: 'java'
+apply plugin: 'groovy'
apply plugin: 'maven'
group = 'org.jmonkeyengine'
-version = jmePomVersion
+version = jmeFullVersion
sourceCompatibility = '1.8'
[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
@@ -24,10 +25,22 @@ repositories {
dependencies {
// Adding dependencies here will add the dependencies to each subproject.
testCompile group: 'junit', name: 'junit', version: '4.12'
- testCompile group: 'org.mockito', name: 'mockito-core', version: '1.10.19'
+ testCompile group: 'org.mockito', name: 'mockito-core', version: '3.0.0'
testCompile group: 'org.easytesting', name: 'fest-assert-core', version: '2.0M10'
+ testCompile 'org.codehaus.groovy:groovy-all:2.5.8'
}
+
+// Uncomment if you want to see the status of every test that is run and
+// the test output.
+/*
+test {
+ testLogging {
+ events "passed", "skipped", "failed", "standardOut", "standardError"
+ }
+}
+*/
+
jar {
manifest {
attributes 'Implementation-Title': 'jMonkeyEngine',
@@ -38,9 +51,9 @@ jar {
javadoc {
failOnError = false
options.memberLevel = org.gradle.external.javadoc.JavadocMemberLevel.PROTECTED
- options.docTitle = "jMonkeyEngine ${jmeMainVersion} ${project.name} Javadoc"
- options.windowTitle = "jMonkeyEngine ${jmeMainVersion} ${project.name} Javadoc"
- options.header = "jMonkeyEngine ${jmeMainVersion} ${project.name}"
+ options.docTitle = "jMonkeyEngine ${jmeFullVersion} ${project.name} Javadoc"
+ options.windowTitle = "jMonkeyEngine ${jmeFullVersion} ${project.name} Javadoc"
+ options.header = "jMonkeyEngine ${jmeFullVersion} ${project.name}"
options.author = "true"
options.use = "true"
options.charSet = "UTF-8"
diff --git a/gradle.properties b/gradle.properties
index 38b86a10f6..82c99b55ac 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,11 +1,12 @@
-# Version number used for plugins, only 3 numbers (e.g. 3.1.3)
-jmeVersion = 3.3.0
-# Version used for application and settings folder, no spaces!
-jmeMainVersion = 3.3
-# Version addition pre-alpha-svn, Stable, Beta
-jmeVersionTag = SNAPSHOT
-# Increment this each time jmeVersionTag changes but jmeVersion stays the same
-jmeVersionTagID = 2
+# Version number: Major.Minor (e.g. 3.3)
+jmeVersion = 3.3
+
+# Leave empty to autogenerate
+# (use -PjmeVersionName="myVersion" from commandline to specify a custom version name )
+jmeVersionName =
+
+# If true, the version name will contain the commit hash
+useCommitHashAsVersionName = false
# specify if JavaDoc should be built
buildJavaDoc = true
@@ -14,18 +15,22 @@ buildJavaDoc = true
buildNativeProjects = false
buildAndroidExamples = false
+buildForPlatforms = Linux64,Linux32,Windows64,Windows32,Mac64
+# Forcefully ignore prebuilt libraries
+skipPrebuildLibraries=false
# Path to android NDK for building native libraries
#ndkPath=/Users/normenhansen/Documents/Code-Import/android-ndk-r7
ndkPath = /opt/android-ndk-r16b
# Path for downloading native Bullet
-bulletUrl = https://github.com/bulletphysics/bullet3/archive/2.87.zip
-bulletFolder = bullet3-2.87
+# 2.88+
+bulletUrl = https://github.com/bulletphysics/bullet3/archive/28039903b14c2aec28beff5b3609c9308b17e76a.zip
+bulletFolder = bullet3-28039903b14c2aec28beff5b3609c9308b17e76a
bulletZipFile = bullet3.zip
# POM settings
POM_NAME=jMonkeyEngine
-POM_DESCRIPTION=jMonkeyEngine is a 3D game engine for adventurous Java developers
+POM_DESCRIPTION=jMonkeyEngine is a 3-D game engine for adventurous Java developers
POM_URL=http://jmonkeyengine.org
POM_SCM_URL=https://github.com/jMonkeyEngine/jmonkeyengine
POM_SCM_CONNECTION=scm:git:git://github.com/jMonkeyEngine/jmonkeyengine.git
@@ -39,3 +44,4 @@ POM_INCEPTION_YEAR=2009
bintray_user=
bintray_api_key=
+PREBUILD_NATIVES_URL=https://dl.bintray.com/jmonkeyengine/files/${natives.snapshot}/jme3-natives.zip
diff --git a/jme3-android-examples/build.gradle b/jme3-android-examples/build.gradle
index 023b662f04..17be807ebb 100644
--- a/jme3-android-examples/build.gradle
+++ b/jme3-android-examples/build.gradle
@@ -1,8 +1,8 @@
apply plugin: 'com.android.application'
android {
- compileSdkVersion 23
- buildToolsVersion "23.0.3"
+ compileSdkVersion 28
+ buildToolsVersion "28.0.3"
lintOptions {
// Fix nifty gui referencing "java.awt" package.
@@ -13,7 +13,7 @@ android {
defaultConfig {
applicationId "org.jmonkeyengine.jme3androidexamples"
minSdkVersion 15 // Android 4.0.3 ICE CREAM SANDWICH
- targetSdkVersion 22 // Android 5.1 LOLLIPOP
+ targetSdkVersion 28 // Android 9 PIE
versionCode 1
versionName "1.0" // TODO: from settings.gradle
}
@@ -25,6 +25,11 @@ android {
}
}
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
sourceSets {
main {
java {
@@ -42,7 +47,7 @@ android {
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
- compile 'com.android.support:appcompat-v7:23.3.0'
+ compile 'com.android.support:appcompat-v7:28.0.0'
compile project(':jme3-core')
compile project(':jme3-android')
diff --git a/jme3-android-examples/src/main/java/org/jmonkeyengine/jme3androidexamples/JmeFragment.java b/jme3-android-examples/src/main/java/org/jmonkeyengine/jme3androidexamples/JmeFragment.java
index 907dd4e6ac..0e2faeea3a 100644
--- a/jme3-android-examples/src/main/java/org/jmonkeyengine/jme3androidexamples/JmeFragment.java
+++ b/jme3-android-examples/src/main/java/org/jmonkeyengine/jme3androidexamples/JmeFragment.java
@@ -62,15 +62,15 @@ public JmeFragment() {
public void onCreate(Bundle savedInstanceState) {
Bundle bundle=getArguments();
- appClass = bundle.getString(SELECTED_APP_CLASS);
+ appClass = bundle.getString(MainActivity.SELECTED_APP_CLASS);
// Log.d(this.getClass().getSimpleName(), "AppClass: " + appClass);
- joystickEventsEnabled = bundle.getBoolean(ENABLE_JOYSTICK_EVENTS);
+ joystickEventsEnabled = bundle.getBoolean(MainActivity.ENABLE_JOYSTICK_EVENTS);
// Log.d(this.getClass().getSimpleName(), "JoystickEventsEnabled: " + joystickEventsEnabled);
- keyEventsEnabled = bundle.getBoolean(ENABLE_KEY_EVENTS);
+ keyEventsEnabled = bundle.getBoolean(MainActivity.ENABLE_KEY_EVENTS);
// Log.d(this.getClass().getSimpleName(), "KeyEventsEnabled: " + keyEventsEnabled);
- mouseEventsEnabled = bundle.getBoolean(ENABLE_MOUSE_EVENTS);
+ mouseEventsEnabled = bundle.getBoolean(MainActivity.ENABLE_MOUSE_EVENTS);
// Log.d(this.getClass().getSimpleName(), "MouseEventsEnabled: " + mouseEventsEnabled);
- boolean verboseLogging = bundle.getBoolean(VERBOSE_LOGGING);
+ boolean verboseLogging = bundle.getBoolean(MainActivity.VERBOSE_LOGGING);
// Log.d(this.getClass().getSimpleName(), "VerboseLogging: " + verboseLogging);
if (verboseLogging) {
// Set the default logging level (default=Level.INFO, Level.ALL=All Debug Info)
diff --git a/jme3-android-native/.gitignore b/jme3-android-native/.gitignore
new file mode 100644
index 0000000000..9010f892c2
--- /dev/null
+++ b/jme3-android-native/.gitignore
@@ -0,0 +1,2 @@
+# The headers are autogenerated and nobody should try to commit them...
+src/native/headers
diff --git a/jme3-android-native/build.gradle b/jme3-android-native/build.gradle
index 0ca99df778..50e6f94178 100644
--- a/jme3-android-native/build.gradle
+++ b/jme3-android-native/build.gradle
@@ -46,4 +46,4 @@ ext {
apply from: file('openalsoft.gradle')
// apply from: file('stb_image.gradle')
// apply from: file('tremor.gradle')
-apply from: file('decode.gradle')
\ No newline at end of file
+apply from: file('decode.gradle')
diff --git a/jme3-android-native/decode.gradle b/jme3-android-native/decode.gradle
index f5ab90a00a..07d93a04af 100644
--- a/jme3-android-native/decode.gradle
+++ b/jme3-android-native/decode.gradle
@@ -8,10 +8,12 @@ String decodeBuildJniDir = decodeBuildDir + File.separator + 'jni'
String decodeBuildLibsDir = decodeBuildDir + File.separator + 'libs'
// Pre-compiled libs directory
-String decodePreCompiledLibsDir = 'libs' + File.separator + 'decode'
+def rootPath = rootProject.projectDir.absolutePath
+String decodePreCompiledLibsDir = rootPath + File.separator + 'build' + File.separator + 'native' + File.separator + 'android' + File.separator + 'decode'
// jME Android Native source files path
String decodeSourceDir = 'src/native/jme_decode'
+String jmeHeaders = 'src/native/headers'
task downloadStbImage(type: MyDownload) {
sourceUrl = stbiUrl
@@ -45,24 +47,13 @@ task copyTremorFiles(type: Copy) {
into outputDir
}
-// Generate headers via javac -h
-task generateJavahHeaders(type: Exec) {
- def files0 = fileTree("src/main/java/").filter { it.isFile() && it.getName().endsWith(".java") }.files
- def files1 = fileTree("src/common/java/").filter { it.isFile() && it.getName().endsWith(".java") }.files
- def files2 = fileTree("../jme3-core/src/main/java/").filter { it.isFile() && it.getName().endsWith(".java") }.files
- def files3 = fileTree("../jme3-core/src/plugins/java/").filter { it.isFile() && it.getName().endsWith(".java") }.files
- def files4 = fileTree("../jme3-core/src/tools/java/").filter { it.isFile() && it.getName().endsWith(".java") }.files
- def files5 = fileTree("../jme3-terrain/src/main/java/").filter { it.isFile() && it.getName().endsWith(".java") }.files
- def filesList = "\"" + files0.join("\"\n\"") + "\"\n\"" + files1.join("\"\n\"") + "\"\n\"" + files2.join("\"\n\"") + "\"\n\"" + files3.join("\"\n\"") + "\"\n\"" + files4.join("\"\n\"") + "\"\n\"" + files5.join("\"\n\"") + "\""
- new File("$projectDir/java_classes.jtxt").text = filesList.replaceAll(java.util.regex.Pattern.quote("\\"), java.util.regex.Matcher.quoteReplacement("/"))
- executable org.gradle.internal.jvm.Jvm.current().getExecutable('javac')
- args '-h', decodeSourceDir
- args "@$projectDir/java_classes.jtxt"
- args '-d', decodeClassesBuildDir
+task copyJmeHeadersDecode(type: Copy) {
+ from file(jmeHeaders)
+ into file(decodeBuildJniDir + File.separator + "headers")
}
// Copy jME Android native files to jni directory
-task copySourceToBuild(type: Copy, dependsOn:[copyTremorFiles, copyStbiFiles, generateJavahHeaders]) {
+task copySourceToBuild(type: Copy, dependsOn:[copyTremorFiles, copyStbiFiles, copyJmeHeadersDecode]) {
def sourceDir = file(decodeSourceDir)
def outputDir = file(decodeBuildJniDir)
diff --git a/jme3-android-native/libs/decode/arm64-v8a/libdecodejme.so b/jme3-android-native/libs/decode/arm64-v8a/libdecodejme.so
deleted file mode 100755
index b8aa7b6a41..0000000000
Binary files a/jme3-android-native/libs/decode/arm64-v8a/libdecodejme.so and /dev/null differ
diff --git a/jme3-android-native/libs/decode/armeabi-v7a/libdecodejme.so b/jme3-android-native/libs/decode/armeabi-v7a/libdecodejme.so
deleted file mode 100755
index e7e55030e3..0000000000
Binary files a/jme3-android-native/libs/decode/armeabi-v7a/libdecodejme.so and /dev/null differ
diff --git a/jme3-android-native/libs/decode/armeabi/libdecodejme.so b/jme3-android-native/libs/decode/armeabi/libdecodejme.so
deleted file mode 100755
index c6de180093..0000000000
Binary files a/jme3-android-native/libs/decode/armeabi/libdecodejme.so and /dev/null differ
diff --git a/jme3-android-native/libs/decode/mips/libdecodejme.so b/jme3-android-native/libs/decode/mips/libdecodejme.so
deleted file mode 100755
index 230e753a44..0000000000
Binary files a/jme3-android-native/libs/decode/mips/libdecodejme.so and /dev/null differ
diff --git a/jme3-android-native/libs/decode/mips64/libdecodejme.so b/jme3-android-native/libs/decode/mips64/libdecodejme.so
deleted file mode 100755
index e60aa07f54..0000000000
Binary files a/jme3-android-native/libs/decode/mips64/libdecodejme.so and /dev/null differ
diff --git a/jme3-android-native/libs/decode/x86/libdecodejme.so b/jme3-android-native/libs/decode/x86/libdecodejme.so
deleted file mode 100755
index 22256712d6..0000000000
Binary files a/jme3-android-native/libs/decode/x86/libdecodejme.so and /dev/null differ
diff --git a/jme3-android-native/libs/decode/x86_64/libdecodejme.so b/jme3-android-native/libs/decode/x86_64/libdecodejme.so
deleted file mode 100755
index fac6ecd801..0000000000
Binary files a/jme3-android-native/libs/decode/x86_64/libdecodejme.so and /dev/null differ
diff --git a/jme3-android-native/libs/openalsoft/arm64-v8a/libopenalsoftjme.so b/jme3-android-native/libs/openalsoft/arm64-v8a/libopenalsoftjme.so
deleted file mode 100755
index 907bd76ec1..0000000000
Binary files a/jme3-android-native/libs/openalsoft/arm64-v8a/libopenalsoftjme.so and /dev/null differ
diff --git a/jme3-android-native/libs/openalsoft/armeabi-v7a/libopenalsoftjme.so b/jme3-android-native/libs/openalsoft/armeabi-v7a/libopenalsoftjme.so
deleted file mode 100755
index 7d78532ff4..0000000000
Binary files a/jme3-android-native/libs/openalsoft/armeabi-v7a/libopenalsoftjme.so and /dev/null differ
diff --git a/jme3-android-native/libs/openalsoft/armeabi/libopenalsoftjme.so b/jme3-android-native/libs/openalsoft/armeabi/libopenalsoftjme.so
deleted file mode 100755
index ddeef5b405..0000000000
Binary files a/jme3-android-native/libs/openalsoft/armeabi/libopenalsoftjme.so and /dev/null differ
diff --git a/jme3-android-native/libs/openalsoft/mips/libopenalsoftjme.so b/jme3-android-native/libs/openalsoft/mips/libopenalsoftjme.so
deleted file mode 100755
index 76bcef4a9d..0000000000
Binary files a/jme3-android-native/libs/openalsoft/mips/libopenalsoftjme.so and /dev/null differ
diff --git a/jme3-android-native/libs/openalsoft/mips64/libopenalsoftjme.so b/jme3-android-native/libs/openalsoft/mips64/libopenalsoftjme.so
deleted file mode 100755
index 3c028aa7f6..0000000000
Binary files a/jme3-android-native/libs/openalsoft/mips64/libopenalsoftjme.so and /dev/null differ
diff --git a/jme3-android-native/libs/openalsoft/x86/libopenalsoftjme.so b/jme3-android-native/libs/openalsoft/x86/libopenalsoftjme.so
deleted file mode 100755
index 0664fc7844..0000000000
Binary files a/jme3-android-native/libs/openalsoft/x86/libopenalsoftjme.so and /dev/null differ
diff --git a/jme3-android-native/libs/openalsoft/x86_64/libopenalsoftjme.so b/jme3-android-native/libs/openalsoft/x86_64/libopenalsoftjme.so
deleted file mode 100755
index 6926d74563..0000000000
Binary files a/jme3-android-native/libs/openalsoft/x86_64/libopenalsoftjme.so and /dev/null differ
diff --git a/jme3-android-native/openalsoft.gradle b/jme3-android-native/openalsoft.gradle
index ed4eeacfdb..d8e5e836e2 100644
--- a/jme3-android-native/openalsoft.gradle
+++ b/jme3-android-native/openalsoft.gradle
@@ -14,10 +14,12 @@ String openalsoftBuildJniDir = openalsoftBuildDir + File.separator + 'jni'
String openalsoftBuildLibsDir = openalsoftBuildDir + File.separator + 'libs'
//Pre-compiled libs directory
-String openalsoftPreCompiledLibsDir = 'libs' + File.separator + 'openalsoft'
+def rootPath = rootProject.projectDir.absolutePath
+String openalsoftPreCompiledLibsDir = rootPath + File.separator + 'build' + File.separator + 'native' + File.separator + 'android' + File.separator + 'openalsoft'
// jME Android Native source files path
String openalsoftJmeAndroidPath = 'src/native/jme_openalsoft'
+String jmeHeaders = 'src/native/headers'
// Download external source files if not available
task downloadOpenALSoft(type: MyDownload) {
@@ -62,8 +64,14 @@ copyOpenALSoft.dependsOn {
}
}
+// Copy JME Headers to jni directory
+task copyJmeHeadersOpenAL(type: Copy) {
+ from file(jmeHeaders)
+ into file(openalsoftBuildJniDir + File.separator + "headers")
+}
+
// Copy jME Android native files to jni directory
-task copyJmeOpenALSoft(type: Copy, dependsOn:copyOpenALSoft) {
+task copyJmeOpenALSoft(type: Copy, dependsOn: [copyOpenALSoft, copyJmeHeadersOpenAL]) {
def sourceDir = file(openalsoftJmeAndroidPath)
def outputDir = file(openalsoftBuildJniDir)
// println "copyJmeOpenALSoft sourceDir: " + sourceDir
@@ -73,22 +81,7 @@ task copyJmeOpenALSoft(type: Copy, dependsOn:copyOpenALSoft) {
into outputDir
}
-task generateOpenAlSoftHeaders(type:Exec, dependsOn: copyJmeOpenALSoft) {
- def files0 = fileTree("src/main/java/").filter { it.isFile() && it.getName().endsWith(".java") }.files
- def files1 = fileTree("src/common/java/").filter { it.isFile() && it.getName().endsWith(".java") }.files
- def files2 = fileTree("../jme3-core/src/main/java/").filter { it.isFile() && it.getName().endsWith(".java") }.files
- def files3 = fileTree("../jme3-core/src/plugins/java/").filter { it.isFile() && it.getName().endsWith(".java") }.files
- def files4 = fileTree("../jme3-core/src/tools/java/").filter { it.isFile() && it.getName().endsWith(".java") }.files
- def files5 = fileTree("../jme3-terrain/src/main/java/").filter { it.isFile() && it.getName().endsWith(".java") }.files
- def filesList = "\"" + files0.join("\"\n\"") + "\"\n\"" + files1.join("\"\n\"") + "\"\n\"" + files2.join("\"\n\"") + "\"\n\"" + files3.join("\"\n\"") + "\"\n\"" + files4.join("\"\n\"") + "\"\n\"" + files5.join("\"\n\"") + "\""
- new File("$projectDir/java_classes.jtxt").text = filesList.replaceAll(java.util.regex.Pattern.quote("\\"), java.util.regex.Matcher.quoteReplacement("/"))
- executable org.gradle.internal.jvm.Jvm.current().getExecutable('javac')
- args '-h', openalsoftJmeAndroidPath
- args "@$projectDir/java_classes.jtxt"
- args '-d', openalsoftClassesBuildDir
-}
-
-task buildOpenAlSoftNativeLib(type: Exec, dependsOn: generateOpenAlSoftHeaders) {
+task buildOpenAlSoftNativeLib(type: Exec, dependsOn: copyJmeOpenALSoft) {
// println "openalsoft build dir: " + openalsoftBuildDir
// println "ndkCommandPath: " + project.ndkCommandPath
workingDir openalsoftBuildDir
diff --git a/jme3-android-native/src/native/jme_decode/com_jme3_audio_plugins_NativeVorbisFile.c b/jme3-android-native/src/native/jme_decode/com_jme3_audio_plugins_NativeVorbisFile.c
index 0b04cea1c7..2e62dee6b8 100644
--- a/jme3-android-native/src/native/jme_decode/com_jme3_audio_plugins_NativeVorbisFile.c
+++ b/jme3-android-native/src/native/jme_decode/com_jme3_audio_plugins_NativeVorbisFile.c
@@ -4,7 +4,7 @@
#include "Tremor/ivorbisfile.h"
-#include "com_jme3_audio_plugins_NativeVorbisFile.h"
+#include "../headers/com_jme3_audio_plugins_NativeVorbisFile.h"
#ifndef NDEBUG
#include
@@ -345,4 +345,4 @@ JNIEXPORT void JNICALL Java_com_jme3_audio_plugins_NativeVorbisFile_close
free(wrapper);
free(ovf);
(*env)->SetObjectField(env, nvf, nvf_field_ovf, NULL);
-}
\ No newline at end of file
+}
diff --git a/jme3-android-native/src/native/jme_decode/com_jme3_texture_plugins_AndroidNativeImageLoader.c b/jme3-android-native/src/native/jme_decode/com_jme3_texture_plugins_AndroidNativeImageLoader.c
index b03dd8e7dc..6d8084e6c0 100644
--- a/jme3-android-native/src/native/jme_decode/com_jme3_texture_plugins_AndroidNativeImageLoader.c
+++ b/jme3-android-native/src/native/jme_decode/com_jme3_texture_plugins_AndroidNativeImageLoader.c
@@ -1,4 +1,4 @@
-#include "com_jme3_texture_plugins_AndroidNativeImageLoader.h"
+#include "../headers/com_jme3_texture_plugins_AndroidNativeImageLoader.h"
#include
#ifndef NDEBUG
diff --git a/jme3-android-native/src/native/jme_openalsoft/com_jme3_audio_android_AndroidAL.c b/jme3-android-native/src/native/jme_openalsoft/com_jme3_audio_android_AndroidAL.c
index 0b6fb61b77..10ba99755b 100644
--- a/jme3-android-native/src/native/jme_openalsoft/com_jme3_audio_android_AndroidAL.c
+++ b/jme3-android-native/src/native/jme_openalsoft/com_jme3_audio_android_AndroidAL.c
@@ -1,4 +1,4 @@
-#include "com_jme3_audio_android_AndroidAL.h"
+#include "../headers/com_jme3_audio_android_AndroidAL.h"
#include "AL/al.h"
#include "AL/alext.h"
diff --git a/jme3-android-native/src/native/jme_openalsoft/com_jme3_audio_android_AndroidAL.h b/jme3-android-native/src/native/jme_openalsoft/com_jme3_audio_android_AndroidAL.h
deleted file mode 100644
index 1fa80bbf4e..0000000000
--- a/jme3-android-native/src/native/jme_openalsoft/com_jme3_audio_android_AndroidAL.h
+++ /dev/null
@@ -1,173 +0,0 @@
-/* DO NOT EDIT THIS FILE - it is machine generated */
-#include
-/* Header for class com_jme3_audio_android_AndroidAL */
-
-#ifndef _Included_com_jme3_audio_android_AndroidAL
-#define _Included_com_jme3_audio_android_AndroidAL
-#ifdef __cplusplus
-extern "C" {
-#endif
-/*
- * Class: com_jme3_audio_android_AndroidAL
- * Method: alGetString
- * Signature: (I)Ljava/lang/String;
- */
-JNIEXPORT jstring JNICALL Java_com_jme3_audio_android_AndroidAL_alGetString
- (JNIEnv *, jobject, jint);
-
-/*
- * Class: com_jme3_audio_android_AndroidAL
- * Method: alGenSources
- * Signature: ()I
- */
-JNIEXPORT jint JNICALL Java_com_jme3_audio_android_AndroidAL_alGenSources
- (JNIEnv *, jobject);
-
-/*
- * Class: com_jme3_audio_android_AndroidAL
- * Method: alGetError
- * Signature: ()I
- */
-JNIEXPORT jint JNICALL Java_com_jme3_audio_android_AndroidAL_alGetError
- (JNIEnv *, jobject);
-
-/*
- * Class: com_jme3_audio_android_AndroidAL
- * Method: alDeleteSources
- * Signature: (ILjava/nio/IntBuffer;)V
- */
-JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alDeleteSources
- (JNIEnv *, jobject, jint, jobject);
-
-/*
- * Class: com_jme3_audio_android_AndroidAL
- * Method: alGenBuffers
- * Signature: (ILjava/nio/IntBuffer;)V
- */
-JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alGenBuffers
- (JNIEnv *, jobject, jint, jobject);
-
-/*
- * Class: com_jme3_audio_android_AndroidAL
- * Method: alDeleteBuffers
- * Signature: (ILjava/nio/IntBuffer;)V
- */
-JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alDeleteBuffers
- (JNIEnv *, jobject, jint, jobject);
-
-/*
- * Class: com_jme3_audio_android_AndroidAL
- * Method: alSourceStop
- * Signature: (I)V
- */
-JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alSourceStop
- (JNIEnv *, jobject, jint);
-
-/*
- * Class: com_jme3_audio_android_AndroidAL
- * Method: alSourcei
- * Signature: (III)V
- */
-JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alSourcei
- (JNIEnv *, jobject, jint, jint, jint);
-
-/*
- * Class: com_jme3_audio_android_AndroidAL
- * Method: alBufferData
- * Signature: (IILjava/nio/ByteBuffer;II)V
- */
-JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alBufferData
- (JNIEnv *, jobject, jint, jint, jobject, jint, jint);
-
-/*
- * Class: com_jme3_audio_android_AndroidAL
- * Method: alSourcePlay
- * Signature: (I)V
- */
-JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alSourcePlay
- (JNIEnv *, jobject, jint);
-
-/*
- * Class: com_jme3_audio_android_AndroidAL
- * Method: alSourcePause
- * Signature: (I)V
- */
-JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alSourcePause
- (JNIEnv *, jobject, jint);
-
-/*
- * Class: com_jme3_audio_android_AndroidAL
- * Method: alSourcef
- * Signature: (IIF)V
- */
-JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alSourcef
- (JNIEnv *, jobject, jint, jint, jfloat);
-
-/*
- * Class: com_jme3_audio_android_AndroidAL
- * Method: alSource3f
- * Signature: (IIFFF)V
- */
-JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alSource3f
- (JNIEnv *, jobject, jint, jint, jfloat, jfloat, jfloat);
-
-/*
- * Class: com_jme3_audio_android_AndroidAL
- * Method: alGetSourcei
- * Signature: (II)I
- */
-JNIEXPORT jint JNICALL Java_com_jme3_audio_android_AndroidAL_alGetSourcei
- (JNIEnv *, jobject, jint, jint);
-
-/*
- * Class: com_jme3_audio_android_AndroidAL
- * Method: alSourceUnqueueBuffers
- * Signature: (IILjava/nio/IntBuffer;)V
- */
-JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alSourceUnqueueBuffers
- (JNIEnv *, jobject, jint, jint, jobject);
-
-/*
- * Class: com_jme3_audio_android_AndroidAL
- * Method: alSourceQueueBuffers
- * Signature: (IILjava/nio/IntBuffer;)V
- */
-JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alSourceQueueBuffers
- (JNIEnv *, jobject, jint, jint, jobject);
-
-/*
- * Class: com_jme3_audio_android_AndroidAL
- * Method: alListener
- * Signature: (ILjava/nio/FloatBuffer;)V
- */
-JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alListener
- (JNIEnv *, jobject, jint, jobject);
-
-/*
- * Class: com_jme3_audio_android_AndroidAL
- * Method: alListenerf
- * Signature: (IF)V
- */
-JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alListenerf
- (JNIEnv *, jobject, jint, jfloat);
-
-/*
- * Class: com_jme3_audio_android_AndroidAL
- * Method: alListener3f
- * Signature: (IFFF)V
- */
-JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alListener3f
- (JNIEnv *, jobject, jint, jfloat, jfloat, jfloat);
-
-/*
- * Class: com_jme3_audio_android_AndroidAL
- * Method: alSource3i
- * Signature: (IIIII)V
- */
-JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidAL_alSource3i
- (JNIEnv *, jobject, jint, jint, jint, jint, jint);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
diff --git a/jme3-android-native/src/native/jme_openalsoft/com_jme3_audio_android_AndroidALC.c b/jme3-android-native/src/native/jme_openalsoft/com_jme3_audio_android_AndroidALC.c
index 4438910cc8..c919f951a5 100644
--- a/jme3-android-native/src/native/jme_openalsoft/com_jme3_audio_android_AndroidALC.c
+++ b/jme3-android-native/src/native/jme_openalsoft/com_jme3_audio_android_AndroidALC.c
@@ -1,5 +1,5 @@
#include "util.h"
-#include "com_jme3_audio_android_AndroidALC.h"
+#include "../headers/com_jme3_audio_android_AndroidALC.h"
#include "AL/alc.h"
#include "AL/alext.h"
@@ -171,4 +171,4 @@ JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidALC_alcDeviceResumeSOF
if (device == NULL) return;
alcDeviceResumeSOFT(device);
-}
\ No newline at end of file
+}
diff --git a/jme3-android-native/src/native/jme_openalsoft/com_jme3_audio_android_AndroidALC.h b/jme3-android-native/src/native/jme_openalsoft/com_jme3_audio_android_AndroidALC.h
deleted file mode 100644
index e50b7b5113..0000000000
--- a/jme3-android-native/src/native/jme_openalsoft/com_jme3_audio_android_AndroidALC.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/* DO NOT EDIT THIS FILE - it is machine generated */
-#include
-/* Header for class com_jme3_audio_android_AndroidALC */
-
-#ifndef _Included_com_jme3_audio_android_AndroidALC
-#define _Included_com_jme3_audio_android_AndroidALC
-#ifdef __cplusplus
-extern "C" {
-#endif
-/*
- * Class: com_jme3_audio_android_AndroidALC
- * Method: createALC
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidALC_createALC
- (JNIEnv *, jobject);
-
-/*
- * Class: com_jme3_audio_android_AndroidALC
- * Method: destroyALC
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidALC_destroyALC
- (JNIEnv *, jobject);
-
-/*
- * Class: com_jme3_audio_android_AndroidALC
- * Method: isCreated
- * Signature: ()Z
- */
-JNIEXPORT jboolean JNICALL Java_com_jme3_audio_android_AndroidALC_isCreated
- (JNIEnv *, jobject);
-
-/*
- * Class: com_jme3_audio_android_AndroidALC
- * Method: alcGetString
- * Signature: (I)Ljava/lang/String;
- */
-JNIEXPORT jstring JNICALL Java_com_jme3_audio_android_AndroidALC_alcGetString
- (JNIEnv *, jobject, jint);
-
-/*
- * Class: com_jme3_audio_android_AndroidALC
- * Method: alcIsExtensionPresent
- * Signature: (Ljava/lang/String;)Z
- */
-JNIEXPORT jboolean JNICALL Java_com_jme3_audio_android_AndroidALC_alcIsExtensionPresent
- (JNIEnv *, jobject, jstring);
-
-/*
- * Class: com_jme3_audio_android_AndroidALC
- * Method: alcGetInteger
- * Signature: (ILjava/nio/IntBuffer;I)V
- */
-JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidALC_alcGetInteger
- (JNIEnv *, jobject, jint, jobject, jint);
-
-/*
- * Class: com_jme3_audio_android_AndroidALC
- * Method: alcDevicePauseSOFT
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidALC_alcDevicePauseSOFT
- (JNIEnv *, jobject);
-
-/*
- * Class: com_jme3_audio_android_AndroidALC
- * Method: alcDeviceResumeSOFT
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidALC_alcDeviceResumeSOFT
- (JNIEnv *, jobject);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
diff --git a/jme3-android-native/src/native/jme_openalsoft/com_jme3_audio_android_AndroidEFX.c b/jme3-android-native/src/native/jme_openalsoft/com_jme3_audio_android_AndroidEFX.c
index ea50c2672f..6d3b623db2 100644
--- a/jme3-android-native/src/native/jme_openalsoft/com_jme3_audio_android_AndroidEFX.c
+++ b/jme3-android-native/src/native/jme_openalsoft/com_jme3_audio_android_AndroidEFX.c
@@ -1,5 +1,5 @@
#include "util.h"
-#include "com_jme3_audio_android_AndroidEFX.h"
+#include "../headers/com_jme3_audio_android_AndroidEFX.h"
#include "AL/alext.h"
JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidEFX_alGenAuxiliaryEffectSlots
@@ -72,4 +72,4 @@ JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidEFX_alEffectf
(JNIEnv* env, jobject obj, jint effect, jint param, jfloat value)
{
alEffectf((ALuint)effect, (ALenum)param, (ALfloat)value);
-}
\ No newline at end of file
+}
diff --git a/jme3-android-native/src/native/jme_openalsoft/com_jme3_audio_android_AndroidEFX.h b/jme3-android-native/src/native/jme_openalsoft/com_jme3_audio_android_AndroidEFX.h
deleted file mode 100644
index 4bdd94f075..0000000000
--- a/jme3-android-native/src/native/jme_openalsoft/com_jme3_audio_android_AndroidEFX.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/* DO NOT EDIT THIS FILE - it is machine generated */
-#include
-/* Header for class com_jme3_audio_android_AndroidEFX */
-
-#ifndef _Included_com_jme3_audio_android_AndroidEFX
-#define _Included_com_jme3_audio_android_AndroidEFX
-#ifdef __cplusplus
-extern "C" {
-#endif
-/*
- * Class: com_jme3_audio_android_AndroidEFX
- * Method: alGenAuxiliaryEffectSlots
- * Signature: (ILjava/nio/IntBuffer;)V
- */
-JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidEFX_alGenAuxiliaryEffectSlots
- (JNIEnv *, jobject, jint, jobject);
-
-/*
- * Class: com_jme3_audio_android_AndroidEFX
- * Method: alGenEffects
- * Signature: (ILjava/nio/IntBuffer;)V
- */
-JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidEFX_alGenEffects
- (JNIEnv *, jobject, jint, jobject);
-
-/*
- * Class: com_jme3_audio_android_AndroidEFX
- * Method: alEffecti
- * Signature: (III)V
- */
-JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidEFX_alEffecti
- (JNIEnv *, jobject, jint, jint, jint);
-
-/*
- * Class: com_jme3_audio_android_AndroidEFX
- * Method: alAuxiliaryEffectSloti
- * Signature: (III)V
- */
-JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidEFX_alAuxiliaryEffectSloti
- (JNIEnv *, jobject, jint, jint, jint);
-
-/*
- * Class: com_jme3_audio_android_AndroidEFX
- * Method: alDeleteEffects
- * Signature: (ILjava/nio/IntBuffer;)V
- */
-JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidEFX_alDeleteEffects
- (JNIEnv *, jobject, jint, jobject);
-
-/*
- * Class: com_jme3_audio_android_AndroidEFX
- * Method: alDeleteAuxiliaryEffectSlots
- * Signature: (ILjava/nio/IntBuffer;)V
- */
-JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidEFX_alDeleteAuxiliaryEffectSlots
- (JNIEnv *, jobject, jint, jobject);
-
-/*
- * Class: com_jme3_audio_android_AndroidEFX
- * Method: alGenFilters
- * Signature: (ILjava/nio/IntBuffer;)V
- */
-JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidEFX_alGenFilters
- (JNIEnv *, jobject, jint, jobject);
-
-/*
- * Class: com_jme3_audio_android_AndroidEFX
- * Method: alFilteri
- * Signature: (III)V
- */
-JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidEFX_alFilteri
- (JNIEnv *, jobject, jint, jint, jint);
-
-/*
- * Class: com_jme3_audio_android_AndroidEFX
- * Method: alFilterf
- * Signature: (IIF)V
- */
-JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidEFX_alFilterf
- (JNIEnv *, jobject, jint, jint, jfloat);
-
-/*
- * Class: com_jme3_audio_android_AndroidEFX
- * Method: alDeleteFilters
- * Signature: (ILjava/nio/IntBuffer;)V
- */
-JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidEFX_alDeleteFilters
- (JNIEnv *, jobject, jint, jobject);
-
-/*
- * Class: com_jme3_audio_android_AndroidEFX
- * Method: alEffectf
- * Signature: (IIF)V
- */
-JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidEFX_alEffectf
- (JNIEnv *, jobject, jint, jint, jfloat);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
diff --git a/jme3-android/build.gradle b/jme3-android/build.gradle
index 4caad528e7..98a2b37a0a 100644
--- a/jme3-android/build.gradle
+++ b/jme3-android/build.gradle
@@ -1,3 +1,5 @@
+apply plugin: 'java'
+
if (!hasProperty('mainClass')) {
ext.mainClass = ''
}
@@ -7,3 +9,8 @@ dependencies {
compile project(':jme3-plugins')
compileOnly 'android:android'
}
+
+compileJava {
+ // The Android-Native Project requires the jni headers to be generated, so we do that here
+ options.compilerArgs += ["-h", "${project.rootDir}/jme3-android-native/src/native/headers"]
+}
diff --git a/jme3-android/src/main/java/com/jme3/app/AndroidHarness.java b/jme3-android/src/main/java/com/jme3/app/AndroidHarness.java
index 5ca059e9a7..b6d0913d16 100644
--- a/jme3-android/src/main/java/com/jme3/app/AndroidHarness.java
+++ b/jme3-android/src/main/java/com/jme3/app/AndroidHarness.java
@@ -88,7 +88,7 @@ public class AndroidHarness extends Activity implements TouchListener, DialogInt
protected int eglStencilBits = 0;
/**
- * Set the desired frame rate. If frameRate > 0, the application
+ * Set the desired frame rate. If frameRate higher than 0, the application
* will be capped at the desired frame rate.
* (default = -1, no frame rate cap)
*/
diff --git a/jme3-android/src/main/java/com/jme3/app/AndroidHarnessFragment.java b/jme3-android/src/main/java/com/jme3/app/AndroidHarnessFragment.java
index 7b2bf180f2..ed8976955f 100644
--- a/jme3-android/src/main/java/com/jme3/app/AndroidHarnessFragment.java
+++ b/jme3-android/src/main/java/com/jme3/app/AndroidHarnessFragment.java
@@ -116,7 +116,7 @@ public class AndroidHarnessFragment extends Fragment implements
protected int eglStencilBits = 0;
/**
- * Set the desired frame rate. If frameRate > 0, the application
+ * Set the desired frame rate. If frameRate higher than 0, the application
* will be capped at the desired frame rate.
* (default = -1, no frame rate cap)
*/
@@ -129,7 +129,7 @@ public class AndroidHarnessFragment extends Fragment implements
* will have the resolution set to a maximum of maxResolutionDimension.
* The other direction will be set to a value that maintains the aspect
* ratio of the surfaceview.
- * Any value < 0 (default = -1) will result in the surfaceview having the
+ * Any value less than 0 (default = -1) will result in the surfaceview having the
* same resolution as the view layout (ie. no max resolution).
*/
protected int maxResolutionDimension = -1;
diff --git a/jme3-android/src/main/java/com/jme3/app/DefaultAndroidProfiler.java b/jme3-android/src/main/java/com/jme3/app/DefaultAndroidProfiler.java
index 1308b08ddc..4faa8aa898 100644
--- a/jme3-android/src/main/java/com/jme3/app/DefaultAndroidProfiler.java
+++ b/jme3-android/src/main/java/com/jme3/app/DefaultAndroidProfiler.java
@@ -63,7 +63,7 @@
*
*
This profiler uses the Android Trace class which is only supported
* on Android SDK rev 18 and higher (ver 4.3 and higher). If the
- * device is running a version < rev 18, the logging will
+ * device is running a version less than rev 18, the logging will
* be skipped.
*
*
In the MainActivity class, add the following:
diff --git a/jme3-android/src/main/java/com/jme3/input/android/AndroidJoyInput.java b/jme3-android/src/main/java/com/jme3/input/android/AndroidJoyInput.java
index 1e610d24e5..6eb2a949f9 100644
--- a/jme3-android/src/main/java/com/jme3/input/android/AndroidJoyInput.java
+++ b/jme3-android/src/main/java/com/jme3/input/android/AndroidJoyInput.java
@@ -71,10 +71,11 @@
* This is done to allow for battery conservation when sensor data or gamepads
* are not required by the application.
*
+ * {@code
* To use the joystick rumble feature, the following line needs to be
* added to the Android Manifest File
*
- *
+ * }
* @author iwgeric
*/
public class AndroidJoyInput implements JoyInput {
diff --git a/jme3-android/src/main/java/com/jme3/renderer/android/AndroidGL.java b/jme3-android/src/main/java/com/jme3/renderer/android/AndroidGL.java
index 44e931104a..ced4260ea5 100644
--- a/jme3-android/src/main/java/com/jme3/renderer/android/AndroidGL.java
+++ b/jme3-android/src/main/java/com/jme3/renderer/android/AndroidGL.java
@@ -34,6 +34,7 @@
import android.opengl.*;
import com.jme3.renderer.RendererException;
import com.jme3.renderer.opengl.*;
+import com.jme3.util.BufferUtils;
import java.nio.Buffer;
import java.nio.ByteBuffer;
@@ -41,7 +42,9 @@
import java.nio.IntBuffer;
import java.nio.ShortBuffer;
-public class AndroidGL implements GL, GLExt, GLFbo {
+public class AndroidGL implements GL, GL2, GLES_30, GLExt, GLFbo {
+
+ IntBuffer tmpBuff = BufferUtils.createIntBuffer(1);
public void resetStats() {
}
@@ -361,7 +364,7 @@ public void glStencilOpSeparate(int face, int sfail, int dpfail, int dppass) {
}
public void glTexImage2D(int target, int level, int internalFormat, int width, int height, int border, int format, int type, ByteBuffer data) {
- GLES20.glTexImage2D(target, level, format, width, height, 0, format, type, data);
+ GLES20.glTexImage2D(target, level, internalFormat, width, height, 0, format, type, data);
}
public void glTexParameterf(int target, int pname, float param) {
@@ -449,7 +452,7 @@ public void glViewport(int x, int y, int width, int height) {
}
public void glBlitFramebufferEXT(int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, int dstY1, int mask, int filter) {
- throw new UnsupportedOperationException("FBO blit not available on Android");
+ GLES30.glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
}
public void glBufferData(int target, IntBuffer data, int usage) {
@@ -461,31 +464,31 @@ public void glBufferSubData(int target, long offset, IntBuffer data) {
}
public void glDrawArraysInstancedARB(int mode, int first, int count, int primcount) {
- throw new UnsupportedOperationException("Instancing not available on Android");
+ GLES30.glDrawArraysInstanced(mode, first, count, primcount);
}
public void glDrawBuffers(IntBuffer bufs) {
- throw new UnsupportedOperationException("MRT not available on Android");
+ GLES30.glDrawBuffers(bufs.limit(), bufs);
}
public void glDrawElementsInstancedARB(int mode, int indices_count, int type, long indices_buffer_offset, int primcount) {
- throw new UnsupportedOperationException("Instancing not available on Android");
+ GLES30.glDrawElementsInstanced(mode, indices_count, type, (int)indices_buffer_offset, primcount);
}
public void glGetMultisample(int pname, int index, FloatBuffer val) {
- throw new UnsupportedOperationException("Multisample renderbuffers not available on Android");
+ GLES31.glGetMultisamplefv(pname, index, val);
}
public void glRenderbufferStorageMultisampleEXT(int target, int samples, int internalformat, int width, int height) {
- throw new UnsupportedOperationException("Multisample renderbuffers not available on Android");
+ GLES30.glRenderbufferStorageMultisample(target, samples, internalformat, width, height);
}
public void glTexImage2DMultisample(int target, int samples, int internalformat, int width, int height, boolean fixedsamplelocations) {
- throw new UnsupportedOperationException("Multisample textures not available on Android");
+ GLES31.glTexStorage2DMultisample(target, samples, internalformat, width, height, fixedsamplelocations);
}
public void glVertexAttribDivisorARB(int index, int divisor) {
- throw new UnsupportedOperationException("Instancing not available on Android");
+ GLES30.glVertexAttribDivisor(index, divisor);
}
public void glBindFramebufferEXT(int param1, int param2) {
@@ -564,6 +567,49 @@ public void glBlendEquationSeparate(int colorMode, int alphaMode) {
@Override
public void glFramebufferTextureLayerEXT(int target, int attachment, int texture, int level, int layer) {
- throw new UnsupportedOperationException("OpenGL ES 2 does not support texture arrays");
+ GLES30.glFramebufferTextureLayer(target, attachment, texture, level, layer);
+ }
+
+ public void glAlphaFunc(int func, float ref) {
+ }
+
+ public void glPointSize(float size) {
+ }
+
+ public void glPolygonMode(int face, int mode) {
+ }
+
+ // Wrapper to DrawBuffers as there's no DrawBuffer method in GLES
+ public void glDrawBuffer(int mode) {
+ tmpBuff.clear();
+ tmpBuff.put(0, mode);
+ tmpBuff.rewind();
+ glDrawBuffers(tmpBuff);
+ }
+
+ public void glReadBuffer(int mode) {
+ GLES30.glReadBuffer(mode);
}
+
+ public void glCompressedTexImage3D(int target, int level, int internalFormat, int width, int height, int depth,
+ int border, ByteBuffer data) {
+ GLES30.glCompressedTexImage3D(target, level, internalFormat, width, height, depth, border, getLimitBytes(data), data);
+ }
+
+ public void glCompressedTexSubImage3D(int target, int level, int xoffset, int yoffset, int zoffset, int width,
+ int height, int depth, int format, ByteBuffer data) {
+ GLES30.glCompressedTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, getLimitBytes(data), data);
+ }
+
+ public void glTexImage3D(int target, int level, int internalFormat, int width, int height, int depth, int border,
+ int format, int type, ByteBuffer data) {
+ GLES30.glTexImage3D(target, level, internalFormat, width, height, depth, border, format, type, data);
+ }
+
+ public void glTexSubImage3D(int target, int level, int xoffset, int yoffset, int zoffset, int width, int height,
+ int depth, int format, int type, ByteBuffer data) {
+ GLES30.glTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, data);
+ }
+
}
+
diff --git a/jme3-android/src/main/java/com/jme3/system/android/AndroidConfigChooser.java b/jme3-android/src/main/java/com/jme3/system/android/AndroidConfigChooser.java
index ba4c5a42e2..4bccf537aa 100644
--- a/jme3-android/src/main/java/com/jme3/system/android/AndroidConfigChooser.java
+++ b/jme3-android/src/main/java/com/jme3/system/android/AndroidConfigChooser.java
@@ -19,6 +19,7 @@ public class AndroidConfigChooser implements EGLConfigChooser {
private static final Logger logger = Logger.getLogger(AndroidConfigChooser.class.getName());
protected AppSettings settings;
private final static int EGL_OPENGL_ES2_BIT = 4;
+ private final static int EGL_OPENGL_ES3_BIT = 0x40;
public AndroidConfigChooser(AppSettings settings) {
this.settings = settings;
@@ -140,12 +141,29 @@ private EGLConfig[] getConfigs(EGL10 egl, EGLDisplay display) {
int[] num_config = new int[1];
int[] configSpec = new int[]{
- EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT,
EGL10.EGL_NONE};
+ boolean gles3=true;
- if (!egl.eglChooseConfig(display, configSpec, null, 0, num_config)) {
- RendererUtil.checkEGLError(egl);
- throw new AssertionError();
+ // Try openGL ES 3
+ try {
+ if (!egl.eglChooseConfig(display, configSpec, null, 0, num_config)) {
+ RendererUtil.checkEGLError(egl);
+ gles3=false;
+ }
+ } catch (com.jme3.renderer.RendererException re) {
+ // it's just the device not supporting GLES3. Fallback to GLES2
+ gles3=false;
+ }
+
+ if(!gles3)
+ {
+ // Get back to openGL ES 2
+ configSpec[1]=EGL_OPENGL_ES2_BIT;
+ if (!egl.eglChooseConfig(display, configSpec, null, 0, num_config)) {
+ RendererUtil.checkEGLError(egl);
+ throw new AssertionError();
+ }
}
int numConfigs = num_config[0];
diff --git a/jme3-android/src/main/java/com/jme3/system/android/OGLESContext.java b/jme3-android/src/main/java/com/jme3/system/android/OGLESContext.java
index db185b0026..7ea954eac4 100644
--- a/jme3-android/src/main/java/com/jme3/system/android/OGLESContext.java
+++ b/jme3-android/src/main/java/com/jme3/system/android/OGLESContext.java
@@ -53,12 +53,15 @@
import com.jme3.input.dummy.DummyMouseInput;
import com.jme3.renderer.android.AndroidGL;
import com.jme3.renderer.opengl.GL;
+import com.jme3.renderer.opengl.GLES_30;
import com.jme3.renderer.opengl.GLDebugES;
import com.jme3.renderer.opengl.GLExt;
import com.jme3.renderer.opengl.GLFbo;
import com.jme3.renderer.opengl.GLRenderer;
import com.jme3.renderer.opengl.GLTracer;
import com.jme3.system.*;
+import com.jme3.util.AndroidBufferAllocator;
+import com.jme3.util.BufferAllocatorFactory;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -81,6 +84,14 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer, SoftTex
protected long minFrameDuration = 0; // No FPS cap
protected long lastUpdateTime = 0;
+ static {
+ final String implementation = BufferAllocatorFactory.PROPERTY_BUFFER_ALLOCATOR_IMPLEMENTATION;
+
+ if (System.getProperty(implementation) == null) {
+ System.setProperty(implementation, AndroidBufferAllocator.class.getName());
+ }
+ }
+
public OGLESContext() {
}
@@ -99,13 +110,13 @@ public Type getType() {
* @return GLSurfaceView The newly created view
*/
public GLSurfaceView createView(Context context) {
+ ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+ ConfigurationInfo info = am.getDeviceConfigurationInfo();
// NOTE: We assume all ICS devices have OpenGL ES 2.0.
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
// below 4.0, check OpenGL ES 2.0 support.
- ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
- ConfigurationInfo info = am.getDeviceConfigurationInfo();
if (info.reqGlEsVersion < 0x20000) {
- throw new UnsupportedOperationException("OpenGL ES 2.0 is not supported on this device");
+ throw new UnsupportedOperationException("OpenGL ES 2.0 or better is not supported on this device");
}
} else if (Build.VERSION.SDK_INT < 9){
throw new UnsupportedOperationException("jME3 requires Android 2.3 or later");
@@ -126,7 +137,8 @@ public GLSurfaceView createView(Context context) {
// setEGLContextClientVersion must be set before calling setRenderer
// this means it cannot be set in AndroidConfigChooser (too late)
- view.setEGLContextClientVersion(2);
+ // use proper openGL ES version
+ view.setEGLContextClientVersion(info.reqGlEsVersion>>16);
view.setFocusableInTouchMode(true);
view.setFocusable(true);
@@ -201,7 +213,7 @@ public void uncaughtException(Thread thread, Throwable thrown) {
gl = new GLDebugES((GL) gl, (GLExt) gl, (GLFbo) gl);
}
if (settings.getBoolean("GraphicsTrace")) {
- gl = GLTracer.createGlesTracer(gl, GL.class, GLFbo.class, GLExt.class);
+ gl = GLTracer.createGlesTracer(gl, GL.class, GLES_30.class, GLFbo.class, GLExt.class);
}
renderer = new GLRenderer((GL)gl, (GLExt)gl, (GLFbo)gl);
renderer.initialize();
diff --git a/jme3-android/src/main/java/com/jme3/util/AndroidBufferAllocator.java b/jme3-android/src/main/java/com/jme3/util/AndroidBufferAllocator.java
new file mode 100644
index 0000000000..73e203da54
--- /dev/null
+++ b/jme3-android/src/main/java/com/jme3/util/AndroidBufferAllocator.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2009-2019 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.util;
+
+import java.lang.reflect.Field;
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Jesus Oliver
+ */
+public class AndroidBufferAllocator implements BufferAllocator {
+
+ // We make use of the ReflectionAllocator to remove the inner buffer
+ private static final ReflectionAllocator reflectionAllocator = new ReflectionAllocator();
+
+ private static final String[] wrapperClassNames = {
+ "java.nio.ByteBufferAsFloatBuffer",
+ "java.nio.ByteBufferAsIntBuffer",
+ "java.nio.ByteBufferAsDoubleBuffer",
+ "java.nio.ByteBufferAsShortBuffer",
+ "java.nio.ByteBufferAsLongBuffer",
+ "java.nio.ByteBufferAsCharBuffer",
+ };
+ private static final String[] possibleBufferFieldNames = {"bb", "byteBuffer"};
+
+ // Keep track of ByteBuffer field by the wrapper class
+ private static final Map fieldIndex = new HashMap<>();
+
+ static {
+ for (String className : wrapperClassNames) {
+ try {
+ Class clazz = Class.forName(className);
+
+ // loop for all possible field names in android
+ for (String fieldName : possibleBufferFieldNames) {
+ try {
+ Field field = clazz.getDeclaredField(fieldName);
+ field.setAccessible(true);
+ fieldIndex.put(clazz, field);
+ break;
+ } catch (NoSuchFieldException e) {
+ }
+ }
+ } catch (ClassNotFoundException ex) {
+ }
+ }
+ }
+
+ @Override
+ /**
+ * This function search the inner direct buffer of the android specific wrapped buffer classes
+ * and destroys it using the reflection allocator method.
+ *
+ * @param toBeDestroyed The direct buffer that will be "cleaned".
+ *
+ */
+ public void destroyDirectBuffer(Buffer toBeDestroyed) {
+ // If it is a wrapped buffer, get it's inner direct buffer field and destroy it
+ Field field = fieldIndex.get(toBeDestroyed.getClass());
+ if (field != null) {
+ try {
+ ByteBuffer innerBuffer = (ByteBuffer) field.get(toBeDestroyed);
+ if (innerBuffer != null) {
+ // Destroy it using the reflection method
+ reflectionAllocator.destroyDirectBuffer(innerBuffer);
+ }
+ } catch (IllegalAccessException ex) {
+ }
+
+ } else {
+ // It is not a wrapped buffer, use default reflection allocator to remove it instead.
+ reflectionAllocator.destroyDirectBuffer(toBeDestroyed);
+ }
+ }
+
+ @Override
+ public ByteBuffer allocate(int size) {
+ return ByteBuffer.allocateDirect(size);
+ }
+}
+
diff --git a/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinition.java b/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinition.java
index a1f3a73165..166b28c614 100644
--- a/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinition.java
+++ b/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinition.java
@@ -151,7 +151,7 @@ public Set getAlteredOmas() {
* @param targetTransform
* the target transform used by some of the constraints
* @param influence
- * the influence of the constraint (from range <0; 1>)
+ * the influence of the constraint from range [0; 1]
*/
public abstract void bake(Space ownerSpace, Space targetSpace, Transform targetTransform, float influence);
diff --git a/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/TextureHelper.java b/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/TextureHelper.java
index cd146b109a..5b7ccfc9bc 100644
--- a/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/TextureHelper.java
+++ b/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/TextureHelper.java
@@ -313,7 +313,7 @@ public AffineTransform createAffineTransform(Vector2f[] source, Vector2f[] dest,
* This method returns the proper pixel position on the image.
*
* @param pos
- * the relative position (value of range <0, 1> (both inclusive))
+ * the relative position (value of range [0, 1] (both inclusive))
* @param size
* the size of the line the pixel lies on (width, height or
* depth)
diff --git a/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/TexturePixel.java b/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/TexturePixel.java
index 365b34f5e9..def3462ed8 100644
--- a/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/TexturePixel.java
+++ b/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/TexturePixel.java
@@ -118,7 +118,7 @@ public void fromIntensity(short intensity) {
/**
* This method sets the alpha value (converts it to float number from range
- * <0, 1>).
+ * [0, 1]).
*
* @param alpha
* the alpha value
@@ -129,7 +129,7 @@ public void setAlpha(byte alpha) {
/**
* This method sets the alpha value (converts it to float number from range
- * <0, 1>).
+ * [0, 1]).
*
* @param alpha
* the alpha value
diff --git a/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/blending/TextureBlenderAWT.java b/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/blending/TextureBlenderAWT.java
index 1c6f2549d6..41e3e9475e 100644
--- a/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/blending/TextureBlenderAWT.java
+++ b/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/blending/TextureBlenderAWT.java
@@ -142,8 +142,15 @@ public Image blend(Image image, Image baseImage, BlenderContext blenderContext)
}
dataArray.add(newData);
}
-
- Image result = depth > 1 ? new Image(Format.RGBA8, width, height, depth, dataArray, ColorSpace.Linear) : new Image(Format.RGBA8, width, height, dataArray.get(0), ColorSpace.Linear);
+
+ ColorSpace colorSpace;
+ if (baseImage != null) {
+ colorSpace = baseImage.getColorSpace() != null ? baseImage.getColorSpace() : ColorSpace.Linear;
+ } else {
+ colorSpace = image.getColorSpace();
+ }
+
+ Image result = depth > 1 ? new Image(Format.RGBA8, width, height, depth, dataArray, colorSpace) : new Image(Format.RGBA8, width, height, dataArray.get(0), colorSpace);
if (image.getMipMapSizes() != null) {
result.setMipMapSizes(image.getMipMapSizes().clone());
}
diff --git a/jme3-bullet-native-android/build.gradle b/jme3-bullet-native-android/build.gradle
index 1058ef3225..fecb39b39f 100644
--- a/jme3-bullet-native-android/build.gradle
+++ b/jme3-bullet-native-android/build.gradle
@@ -1,4 +1,4 @@
-String jmeBulletNativeProjectPath = '../jme3-bullet-native'
+String jmeBulletNativeProjectPath = project(":jme3-bullet-native").projectDir
String localUnzipPath = jmeBulletNativeProjectPath
String localZipFile = jmeBulletNativeProjectPath + File.separator + bulletZipFile
@@ -14,7 +14,8 @@ String jniPath = ndkWorkingPath + '/jni'
String ndkOutputPath = ndkWorkingPath + '/libs'
//Pre-compiled libs directory
-String bulletPreCompiledLibsDir = 'libs'
+def rootPath = rootProject.projectDir.absolutePath
+String bulletPreCompiledLibsDir = rootPath + File.separator + 'build' + File.separator + 'native' + File.separator + 'android' + File.separator + 'bullet'
if (!hasProperty('mainClass')) {
ext.mainClass = ''
@@ -24,7 +25,7 @@ dependencies {
compile project(':jme3-bullet')
}
-// Java source sets for IDE acces and source jar bundling / mavenization
+// Java source sets for IDE access and source jar bundling / mavenization
sourceSets {
main {
java {
@@ -42,70 +43,41 @@ task downloadBullet(type: MyDownload) {
// Unzip bullet if not available
task unzipBullet(type: Copy) {
- def zipFile = file(localZipFile)
- def outputDir = file(localUnzipPath)
-// println "unzipBullet zipFile = " + zipFile.absolutePath
-// println "unzipBullet outputDir = " + outputDir.absolutePath
-
- from zipTree(zipFile)
- into outputDir
+ from zipTree(localZipFile)
+ into file(localUnzipPath)
}
unzipBullet.dependsOn {
- def zipFile = file(localZipFile)
-// println "zipFile path: " + zipFile.absolutePath
-// println "zipFile exists: " + zipFile.exists()
-
- if (!zipFile.exists()) {
+ if (!file(localZipFile).exists()) {
downloadBullet
}
}
// Copy Bullet files to jni directory
task copyBullet(type: Copy) {
- def sourceDir = file(bulletSrcPath)
- def outputDir = new File(jniPath)
-// println "copyBullet sourceDir = " + sourceDir
-// println "copyBullet outputDir = " + outputDir
-
- from sourceDir
- into outputDir
+ from file(bulletSrcPath)
+ into file(jniPath)
}
copyBullet.dependsOn {
- def bulletUnzipDir = file(localZipFolder)
-// println "bulletUnzipDir: " + bulletUnzipDir.absolutePath
-// println "bulletUnzipDir exists: " + bulletUnzipDir.exists()
-// println "bulletUnzipDir isDirectory: " + bulletUnzipDir.isDirectory()
- if (!bulletUnzipDir.isDirectory()) {
+ if (!file(localZipFolder).isDirectory()) {
unzipBullet
}
}
// Copy jME cpp native files to jni directory
task copyJmeCpp(type: Copy) {
- def sourceDir = new File(jmeCppPath)
- def outputDir = new File(jniPath)
-// println "copyJmeCpp sourceDir = " + sourceDir
-// println "copyJmeCpp outputDir = " + outputDir
-
- from sourceDir
- into outputDir
+ from file(jmeCppPath)
+ into file(jniPath)
}
// Copy jME android native files to jni directory
task copyJmeAndroid(type: Copy) {
- def sourceDir = new File(jmeAndroidPath)
- def outputDir = new File(jniPath)
-// println "copyJmeAndroid sourceDir = " + sourceDir
-// println "copyJmeAndroid outputDir = " + outputDir
-
- from sourceDir
- into outputDir
+ from file(jmeAndroidPath)
+ into file(jniPath)
}
-//dependsOn ':jme3-bullet:generateNativeHeaders'
-task buildBulletNativeLib(type: Exec, dependsOn: [copyJmeAndroid, ':jme3-bullet:generateNativeHeaders', copyJmeCpp, copyBullet]) {
+task buildBulletNativeLib(type: Exec, dependsOn: [copyJmeAndroid, ':jme3-bullet:compileJava', copyJmeCpp, copyBullet]) {
// args 'TARGET_PLATFORM=android-9'
// println "buildBulletNativeLib ndkWorkingPath: " + ndkWorkingPath
// println "buildBulletNativeLib rootProject.ndkCommandPath: " + rootProject.ndkCommandPath
@@ -114,26 +86,20 @@ task buildBulletNativeLib(type: Exec, dependsOn: [copyJmeAndroid, ':jme3-bullet:
args "-j" + Runtime.runtime.availableProcessors()
}
-//task updatePreCompiledBulletLibs(type: Copy, dependsOn: generateNativeHeaders) {
-task updatePreCompiledBulletLibs(type: Copy, dependsOn: buildBulletNativeLib) {
- def sourceDir = new File(ndkOutputPath)
- def outputDir = new File(bulletPreCompiledLibsDir)
-// println "updatePreCompiledBulletLibs sourceDir: " + sourceDir
-// println "updatePreCompiledBulletLibs outputDir: " + outputDir
+/* The following two tasks: We store a prebuilt version in the repository, so nobody has to build
+ * natives in order to build the engine. When building these natives however, the prebuilt libraries
+ * can be updated (which is what the CI does). That's what the following two tasks do
+ */
- from sourceDir
- into outputDir
+task updatePreCompiledBulletLibs(type: Copy, dependsOn: buildBulletNativeLib) {
+ from file(ndkOutputPath)
+ into file(bulletPreCompiledLibsDir)
}
// Copy pre-compiled libs to build directory (when not building new libs)
task copyPreCompiledBulletLibs(type: Copy) {
- def sourceDir = new File(bulletPreCompiledLibsDir)
- def outputDir = new File(ndkOutputPath)
-// println "copyPreCompiledBulletLibs sourceDir: " + sourceDir
-// println "copyPreCompiledBulletLibs outputDir: " + outputDir
-
- from sourceDir
- into outputDir
+ from file(bulletPreCompiledLibsDir)
+ into file(ndkOutputPath)
}
// ndkExists is a boolean from the build.gradle in the root project
@@ -149,7 +115,7 @@ if (ndkExists && buildNativeProjects == "true") {
jar.into("lib") { from ndkOutputPath }
-// Helper class to wrap ant dowload task
+// Helper class to wrap ant download task
class MyDownload extends DefaultTask {
@Input
String sourceUrl
diff --git a/jme3-bullet-native-android/libs/arm64-v8a/libbulletjme.so b/jme3-bullet-native-android/libs/arm64-v8a/libbulletjme.so
deleted file mode 100755
index e64b52ba1b..0000000000
Binary files a/jme3-bullet-native-android/libs/arm64-v8a/libbulletjme.so and /dev/null differ
diff --git a/jme3-bullet-native-android/libs/armeabi-v7a/libbulletjme.so b/jme3-bullet-native-android/libs/armeabi-v7a/libbulletjme.so
deleted file mode 100755
index 7e2aad17b7..0000000000
Binary files a/jme3-bullet-native-android/libs/armeabi-v7a/libbulletjme.so and /dev/null differ
diff --git a/jme3-bullet-native-android/libs/armeabi/libbulletjme.so b/jme3-bullet-native-android/libs/armeabi/libbulletjme.so
deleted file mode 100755
index f54710e4a7..0000000000
Binary files a/jme3-bullet-native-android/libs/armeabi/libbulletjme.so and /dev/null differ
diff --git a/jme3-bullet-native-android/libs/mips/libbulletjme.so b/jme3-bullet-native-android/libs/mips/libbulletjme.so
deleted file mode 100755
index adc7fa1aa7..0000000000
Binary files a/jme3-bullet-native-android/libs/mips/libbulletjme.so and /dev/null differ
diff --git a/jme3-bullet-native-android/libs/mips64/libbulletjme.so b/jme3-bullet-native-android/libs/mips64/libbulletjme.so
deleted file mode 100755
index 094ae8478d..0000000000
Binary files a/jme3-bullet-native-android/libs/mips64/libbulletjme.so and /dev/null differ
diff --git a/jme3-bullet-native-android/libs/x86/libbulletjme.so b/jme3-bullet-native-android/libs/x86/libbulletjme.so
deleted file mode 100755
index 1089c838e7..0000000000
Binary files a/jme3-bullet-native-android/libs/x86/libbulletjme.so and /dev/null differ
diff --git a/jme3-bullet-native-android/libs/x86_64/libbulletjme.so b/jme3-bullet-native-android/libs/x86_64/libbulletjme.so
deleted file mode 100755
index 2f26225794..0000000000
Binary files a/jme3-bullet-native-android/libs/x86_64/libbulletjme.so and /dev/null differ
diff --git a/jme3-bullet-native-android/src/native/android/Android.mk b/jme3-bullet-native-android/src/native/android/Android.mk
index 1a1e64b89c..d04478e285 100644
--- a/jme3-bullet-native-android/src/native/android/Android.mk
+++ b/jme3-bullet-native-android/src/native/android/Android.mk
@@ -71,6 +71,7 @@ FILE_LIST := $(wildcard $(LOCAL_PATH)/*.cpp)
FILE_LIST += $(wildcard $(LOCAL_PATH)/**/*.cpp)
FILE_LIST += $(wildcard $(LOCAL_PATH)/**/**/*.cpp)
FILE_LIST := $(filter-out $(wildcard $(LOCAL_PATH)/Bullet3OpenCL/**/*.cpp), $(FILE_LIST))
+FILE_LIST := $(filter-out $(wildcard $(LOCAL_PATH)/*All.cpp), $(FILE_LIST))
LOCAL_SRC_FILES := $(FILE_LIST:$(LOCAL_PATH)/%=%)
include $(BUILD_SHARED_LIBRARY)
diff --git a/jme3-bullet-native-android/src/native/android/Application.mk b/jme3-bullet-native-android/src/native/android/Application.mk
index 44c5c842e5..6467a5a7f9 100644
--- a/jme3-bullet-native-android/src/native/android/Application.mk
+++ b/jme3-bullet-native-android/src/native/android/Application.mk
@@ -1,7 +1,7 @@
APP_OPTIM := release
APP_ABI := all
-APP_STL := stlport_static
-# gnustl_static or stlport_static
+# Used to be stlport_static, but that has been removed.
+APP_STL := c++_static
APP_MODULES := bulletjme
APP_CFLAGS += -funroll-loops -Ofast
diff --git a/jme3-bullet-native/build.gradle b/jme3-bullet-native/build.gradle
index 558940173f..745630a3b8 100644
--- a/jme3-bullet-native/build.gradle
+++ b/jme3-bullet-native/build.gradle
@@ -2,6 +2,8 @@ apply plugin: 'cpp'
import java.nio.file.Paths
+def rootPath = rootProject.projectDir.absolutePath
+
String bulletSrcPath = bulletFolder + '/src'
if (!hasProperty('mainClass')) {
@@ -29,12 +31,33 @@ task cleanZipFile(type: Delete) {
model {
components {
bulletjme(NativeLibrarySpec) {
- targetPlatform 'Windows64'
- targetPlatform 'Windows32'
- targetPlatform 'Mac64'
- targetPlatform 'Mac32'
- targetPlatform 'Linux64'
- targetPlatform 'Linux32'
+
+
+ String[] targets=[
+ "Windows64",
+ "Windows32",
+ "Mac64",
+ "Linux64",
+ "Linux32",
+ "LinuxArm",
+ "LinuxArmHF",
+ "LinuxArm64"
+ ];
+
+ String[] filter=gradle.rootProject.ext.usePrebuildNatives==true?null:buildForPlatforms.split(",");
+ if(filter==null)println("No filter set. build for all");
+ for(String target:targets){
+ if(filter==null){
+ targetPlatform(target);
+ }else{
+ for(String f:filter){
+ if(f.equals(target)){
+ targetPlatform(target);
+ break;
+ }
+ }
+ }
+ }
sources {
cpp {
@@ -47,6 +70,7 @@ model {
exclude 'Bullet3OpenCL/**'
exclude 'Bullet3Serialize/**'
include '**/*.cpp'
+ exclude '**/*All.cpp'
}
exportedHeaders {
srcDir 'src/native/cpp'
@@ -63,9 +87,41 @@ model {
}
}
+
+ toolChains {
+ visualCpp(VisualCpp)
+ gcc(Gcc)
+ clang(Clang)
+ gccArm(Gcc) {
+ // Fun Fact: Gradle uses gcc as linker frontend, so we don't specify ld directly here
+ target("LinuxArm"){
+ path "/usr/bin"
+ cCompiler.executable = "arm-linux-gnueabi-gcc-8"
+ cppCompiler.executable = "arm-linux-gnueabi-g++-8"
+ linker.executable = "arm-linux-gnueabi-gcc-8"
+ assembler.executable = "arm-linux-gnueabi-as"
+ }
+
+ target("LinuxArmHF"){
+ path "/usr/bin"
+ cCompiler.executable = "arm-linux-gnueabihf-gcc-8"
+ cppCompiler.executable = "arm-linux-gnueabihf-g++-8"
+ linker.executable = "arm-linux-gnueabihf-gcc-8"
+ assembler.executable = "arm-linux-gnueabihf-as"
+ }
+
+ target("LinuxArm64"){
+ path "/usr/bin"
+ cCompiler.executable = "aarch64-linux-gnu-gcc-8"
+ cppCompiler.executable = "aarch64-linux-gnu-g++-8"
+ linker.executable = "aarch64-linux-gnu-gcc-8"
+ assembler.executable = "aarch64-linux-gnu-as"
+ }
+ }
+ }
+
binaries {
withType(SharedLibraryBinarySpec) {
- def projectPath = project.projectDir.absolutePath
def javaHome = org.gradle.internal.jvm.Jvm.current().javaHome
def os = targetPlatform.operatingSystem.name
def arch = targetPlatform.architecture.name
@@ -75,88 +131,57 @@ model {
arch = arch.replaceAll('-', '_')
// For all binaries that can't be built on the current system
- if (buildNativeProjects != "true") {
- buildable = false
- }
+ if (buildNativeProjects != "true") buildable = false
- if (!buildable) {
- if (sharedLibraryFile.exists()) {
- // Add binary to jar file if the binary exists in the build folder already,
- // e.g. when the build of jme3-bullet-native has been run on a virtual box
- // and the project hasn't been cleaned yet.
- jar.into("native/${os}/${arch}") {
- from sharedLibraryFile
- }
- } else {
- // Get from libs folder if no fresh build is available in the build folder and add to jar file
- def precompiledFile = Paths.get(projectPath, 'libs', 'native', os, arch, fileName).toFile()
- if (precompiledFile.exists()) {
- jar.into("native/${os}/${arch}") {
- from precompiledFile
- }
- }
+ if (buildable) {
+ cppCompiler.define('BT_NO_PROFILE')
+ if (toolChain in VisualCpp) {
+ cppCompiler.args "/I$javaHome\\include"
+ } else{
+ cppCompiler.args '-I', "$javaHome/include"
}
- return
- }
- cppCompiler.define('BT_NO_PROFILE')
- if (toolChain in VisualCpp) {
- cppCompiler.args "/I$javaHome\\include"
- } else{
- cppCompiler.args '-I', "$javaHome/include"
- }
-
- if (os == "osx") {
- cppCompiler.args '-I', "$javaHome/include/darwin"
- cppCompiler.args "-Ofast"
- cppCompiler.args "-U_FORTIFY_SOURCE"
- } else if (os == "linux") {
- cppCompiler.args "-fvisibility=hidden"
- cppCompiler.args '-I', "$javaHome/include/linux"
- cppCompiler.args "-fPIC"
- cppCompiler.args "-Ofast"
- cppCompiler.args "-U_FORTIFY_SOURCE"
- cppCompiler.args "-fpermissive"
- linker.args "-fvisibility=hidden"
- } else if (os == "windows") {
- if (toolChain in Gcc) {
- if (toolChain.name.startsWith('mingw')) {
- cppCompiler.args '-I', "$projectDir/src/native/cpp/fake_win32"
- } else {
- cppCompiler.args '-I', "$javaHome/include/win32"
- }
- cppCompiler.args "-fpermissive"
- cppCompiler.args "-static"
- cppCompiler.args "-Ofast"
+ if (os == "osx") {
+ cppCompiler.args '-I', "$javaHome/include/darwin"
+ cppCompiler.args "-O3"
+ cppCompiler.args "-U_FORTIFY_SOURCE"
+ } else if (os == "linux") {
+ cppCompiler.args "-fvisibility=hidden"
+ cppCompiler.args '-I', "$javaHome/include/linux"
+ cppCompiler.args "-fPIC"
+ cppCompiler.args "-O3"
cppCompiler.args "-U_FORTIFY_SOURCE"
- linker.args "-static"
- linker.args "-Wl,--exclude-all-symbols"
+ cppCompiler.args "-fpermissive"
+ linker.args "-fvisibility=hidden"
+ } else if (os == "windows") {
+ if (toolChain in Gcc) {
+ if (toolChain.name.startsWith('mingw')) cppCompiler.args '-I', "$projectDir/src/native/cpp/fake_win32"
+ else cppCompiler.args '-I', "$javaHome/include/win32"
+ cppCompiler.args "-fpermissive"
+ cppCompiler.args "-static"
+ cppCompiler.args "-O3"
+ cppCompiler.args "-U_FORTIFY_SOURCE"
+ linker.args "-static"
+ linker.args "-Wl,--exclude-all-symbols"
+ } else if (toolChain in VisualCpp) {
+ cppCompiler.args "/I$javaHome\\include\\win32"
+ }
+ cppCompiler.define('WIN32')
}
- else if (toolChain in VisualCpp) {
- cppCompiler.args "/I$javaHome\\include\\win32"
+ tasks.all {
+ dependsOn unzipBulletIfNeeded
+ dependsOn ':jme3-bullet:compileJava'
}
- cppCompiler.define('WIN32')
- }
- tasks.all {
- dependsOn unzipBulletIfNeeded
- dependsOn ':jme3-bullet:generateNativeHeaders'
- }
+ task "copyBinaryToLibs${targetPlatform.name}"(type: Copy, dependsOn: tasks) {
+ from sharedLibraryFile
+ into "${rootPath}/build/native/bullet/native/${os}/${arch}"
+ }
- // Add output to jar file
- jar.into("native/${os}/${arch}") {
- from sharedLibraryFile
- }
+ // Add depend on copy
+ jar.dependsOn("copyBinaryToLibs${targetPlatform.name}")
- // Add depend on build
- jar.dependsOn tasks
- // Add output to libs folder
- task "copyBinaryToLibs${targetPlatform.name}"(type: Copy, dependsOn: tasks) {
- from sharedLibraryFile
- into "libs/native/${os}/${arch}"
}
- // Add depend on copy
- jar.dependsOn("copyBinaryToLibs${targetPlatform.name}")
}
withType(StaticLibraryBinarySpec) {
buildable = false
@@ -172,10 +197,6 @@ model {
architecture "x86_64"
operatingSystem "windows"
}
- Mac32 {
- architecture "x86"
- operatingSystem "osx"
- }
Mac64 {
architecture "x86_64"
operatingSystem "osx"
@@ -188,6 +209,18 @@ model {
architecture "x86_64"
operatingSystem "linux"
}
+ LinuxArm {
+ architecture "arm"
+ operatingSystem "linux"
+ }
+ LinuxArmHF {
+ architecture "armhf"
+ operatingSystem "linux"
+ }
+ LinuxArm64 {
+ architecture "aarch64"
+ operatingSystem "linux"
+ }
}
}
@@ -197,6 +230,9 @@ sourceSets {
java {
srcDir 'src/native/cpp'
}
+ resources {
+ srcDir file(Paths.get(rootPath, 'build', 'native', 'bullet'))
+ }
}
}
diff --git a/jme3-bullet-native/libs/native/linux/x86/libbulletjme.so b/jme3-bullet-native/libs/native/linux/x86/libbulletjme.so
deleted file mode 100755
index d0ea174f71..0000000000
Binary files a/jme3-bullet-native/libs/native/linux/x86/libbulletjme.so and /dev/null differ
diff --git a/jme3-bullet-native/libs/native/linux/x86_64/libbulletjme.so b/jme3-bullet-native/libs/native/linux/x86_64/libbulletjme.so
deleted file mode 100755
index 8cad657b2a..0000000000
Binary files a/jme3-bullet-native/libs/native/linux/x86_64/libbulletjme.so and /dev/null differ
diff --git a/jme3-bullet-native/libs/native/osx/x86/libbulletjme.dylib b/jme3-bullet-native/libs/native/osx/x86/libbulletjme.dylib
deleted file mode 100755
index d85332e863..0000000000
Binary files a/jme3-bullet-native/libs/native/osx/x86/libbulletjme.dylib and /dev/null differ
diff --git a/jme3-bullet-native/libs/native/osx/x86_64/libbulletjme.dylib b/jme3-bullet-native/libs/native/osx/x86_64/libbulletjme.dylib
deleted file mode 100755
index 62733e513d..0000000000
Binary files a/jme3-bullet-native/libs/native/osx/x86_64/libbulletjme.dylib and /dev/null differ
diff --git a/jme3-bullet-native/libs/native/windows/x86/bulletjme.dll b/jme3-bullet-native/libs/native/windows/x86/bulletjme.dll
deleted file mode 100755
index f826da28f7..0000000000
Binary files a/jme3-bullet-native/libs/native/windows/x86/bulletjme.dll and /dev/null differ
diff --git a/jme3-bullet-native/libs/native/windows/x86_64/bulletjme.dll b/jme3-bullet-native/libs/native/windows/x86_64/bulletjme.dll
deleted file mode 100755
index 9468e84681..0000000000
Binary files a/jme3-bullet-native/libs/native/windows/x86_64/bulletjme.dll and /dev/null differ
diff --git a/jme3-bullet-native/src/native/cpp/com_jme3_bullet_collision_PhysicsCollisionObject.cpp b/jme3-bullet-native/src/native/cpp/com_jme3_bullet_collision_PhysicsCollisionObject.cpp
index 0c7f0161ae..15d27849ce 100644
--- a/jme3-bullet-native/src/native/cpp/com_jme3_bullet_collision_PhysicsCollisionObject.cpp
+++ b/jme3-bullet-native/src/native/cpp/com_jme3_bullet_collision_PhysicsCollisionObject.cpp
@@ -178,6 +178,24 @@ extern "C" {
collisionObject->setCollisionFlags(desiredFlags);
}
+ /*
+ * Class: com_jme3_bullet_collision_PhysicsCollisionObject
+ * Method: getDeactivationTime
+ * Signature: (J)F
+ */
+ JNIEXPORT jfloat JNICALL Java_com_jme3_bullet_collision_PhysicsCollisionObject_getDeactivationTime
+ (JNIEnv *env, jobject object, jlong pcoId) {
+ btCollisionObject *pCollisionObject
+ = reinterpret_cast (pcoId);
+ if (pCollisionObject == NULL) {
+ jclass newExc = env->FindClass("java/lang/NullPointerException");
+ env->ThrowNew(newExc, "The native object does not exist.");
+ return 0;
+ }
+
+ jfloat result = pCollisionObject->getDeactivationTime();
+ return result;
+ }
#ifdef __cplusplus
}
diff --git a/jme3-bullet-native/src/native/cpp/com_jme3_bullet_collision_shapes_CollisionShape.cpp b/jme3-bullet-native/src/native/cpp/com_jme3_bullet_collision_shapes_CollisionShape.cpp
index dc48be257a..bfdaa20de6 100644
--- a/jme3-bullet-native/src/native/cpp/com_jme3_bullet_collision_shapes_CollisionShape.cpp
+++ b/jme3-bullet-native/src/native/cpp/com_jme3_bullet_collision_shapes_CollisionShape.cpp
@@ -105,6 +105,25 @@ extern "C" {
}
delete(shape);
}
+
+ /*
+ * Class: com_jme3_bullet_collision_shapes_CollisionShape
+ * Method: isNonMoving
+ * Signature: (J)Z
+ */
+ JNIEXPORT jboolean JNICALL Java_com_jme3_bullet_collision_shapes_CollisionShape_isNonMoving
+ (JNIEnv *env, jobject object, jlong shapeId) {
+ btCollisionShape *pShape
+ = reinterpret_cast (shapeId);
+ if (pShape == NULL) {
+ jclass newExc = env->FindClass("java/lang/NullPointerException");
+ env->ThrowNew(newExc, "The native object does not exist.");
+ return false;
+ }
+
+ return pShape->isNonMoving();
+ }
+
#ifdef __cplusplus
}
#endif
diff --git a/jme3-bullet-native/src/native/cpp/com_jme3_bullet_collision_shapes_GImpactCollisionShape.cpp b/jme3-bullet-native/src/native/cpp/com_jme3_bullet_collision_shapes_GImpactCollisionShape.cpp
index f416e46b4a..71a3d3742b 100644
--- a/jme3-bullet-native/src/native/cpp/com_jme3_bullet_collision_shapes_GImpactCollisionShape.cpp
+++ b/jme3-bullet-native/src/native/cpp/com_jme3_bullet_collision_shapes_GImpactCollisionShape.cpp
@@ -55,6 +55,18 @@ extern "C" {
return reinterpret_cast(shape);
}
+ /*
+ * Class: com_jme3_bullet_collision_shapes_GImpactCollisionShape
+ * Method: recalcAabb
+ * Signature: (J)V
+ */
+ JNIEXPORT void JNICALL Java_com_jme3_bullet_collision_shapes_GImpactCollisionShape_recalcAabb
+ (JNIEnv *env, jobject object, jlong shapeId) {
+ btGImpactMeshShape *pShape
+ = reinterpret_cast (shapeId);
+ pShape->updateBound();
+ }
+
/*
* Class: com_jme3_bullet_collision_shapes_GImpactCollisionShape
* Method: finalizeNative
@@ -65,7 +77,7 @@ extern "C" {
btTriangleIndexVertexArray* array = reinterpret_cast (meshId);
delete(array);
}
-
+
#ifdef __cplusplus
}
#endif
diff --git a/jme3-bullet-native/src/native/cpp/com_jme3_bullet_joints_SixDofJoint.cpp b/jme3-bullet-native/src/native/cpp/com_jme3_bullet_joints_SixDofJoint.cpp
index ea55820e0f..24a26c0cfa 100644
--- a/jme3-bullet-native/src/native/cpp/com_jme3_bullet_joints_SixDofJoint.cpp
+++ b/jme3-bullet-native/src/native/cpp/com_jme3_bullet_joints_SixDofJoint.cpp
@@ -165,6 +165,30 @@ extern "C" {
btGeneric6DofConstraint* joint = new btGeneric6DofConstraint(*bodyA, *bodyB, transA, transB, useLinearReferenceFrameA);
return reinterpret_cast(joint);
}
+
+ /*
+ * Class: com_jme3_bullet_joints_SixDofJoint
+ * Method: getAngles
+ * Signature: (JLcom/jme3/math/Vector3f;)V
+ */
+ JNIEXPORT void JNICALL Java_com_jme3_bullet_joints_SixDofJoint_getAngles
+ (JNIEnv *env, jobject object, jlong jointId, jobject storeVector) {
+ btGeneric6DofConstraint *pJoint
+ = reinterpret_cast (jointId);
+ if (pJoint == NULL) {
+ jclass newExc = env->FindClass("java/lang/NullPointerException");
+ env->ThrowNew(newExc, "The native object does not exist.");
+ return;
+ }
+
+ pJoint->calculateTransforms();
+ btScalar x = pJoint->getAngle(0);
+ btScalar y = pJoint->getAngle(1);
+ btScalar z = pJoint->getAngle(2);
+ const btVector3& angles = btVector3(x, y, z);
+ jmeBulletUtil::convert(env, &angles, storeVector);
+ }
+
#ifdef __cplusplus
}
#endif
diff --git a/jme3-bullet-native/src/native/cpp/com_jme3_bullet_joints_motors_TranslationalLimitMotor.cpp b/jme3-bullet-native/src/native/cpp/com_jme3_bullet_joints_motors_TranslationalLimitMotor.cpp
index 39db519e70..14e66933f6 100644
--- a/jme3-bullet-native/src/native/cpp/com_jme3_bullet_joints_motors_TranslationalLimitMotor.cpp
+++ b/jme3-bullet-native/src/native/cpp/com_jme3_bullet_joints_motors_TranslationalLimitMotor.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009-2012 jMonkeyEngine
+ * Copyright (c) 2009-2019 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -232,6 +232,43 @@ extern "C" {
motor->m_restitution = value;
}
+ /*
+ * Class: com_jme3_bullet_joints_motors_TranslationalLimitMotor
+ * Method: setEnabled
+ * Signature: (JIZ)V
+ */
+ JNIEXPORT void JNICALL Java_com_jme3_bullet_joints_motors_TranslationalLimitMotor_setEnabled
+ (JNIEnv *env, jobject object, jlong motorId, jint axisIndex, jboolean newSetting) {
+ btTranslationalLimitMotor *pMotor
+ = reinterpret_cast (motorId);
+ if (pMotor == NULL) {
+ jclass newExc = env->FindClass("java/lang/NullPointerException");
+ env->ThrowNew(newExc, "The native object does not exist.");
+ return;
+ }
+
+ pMotor->m_enableMotor[axisIndex] = (bool)newSetting;
+ }
+
+ /*
+ * Class: com_jme3_bullet_joints_motors_TranslationalLimitMotor
+ * Method: isEnabled
+ * Signature: (JI)Z
+ */
+ JNIEXPORT jboolean JNICALL Java_com_jme3_bullet_joints_motors_TranslationalLimitMotor_isEnabled
+ (JNIEnv *env, jobject object, jlong motorId, jint axisIndex) {
+ btTranslationalLimitMotor *pMotor
+ = reinterpret_cast (motorId);
+ if (pMotor == NULL) {
+ jclass newExc = env->FindClass("java/lang/NullPointerException");
+ env->ThrowNew(newExc, "The native object does not exist.");
+ return 0;
+ }
+
+ bool result = pMotor->m_enableMotor[axisIndex];
+ return (jboolean) result;
+ }
+
#ifdef __cplusplus
}
#endif
diff --git a/jme3-bullet-native/src/native/cpp/com_jme3_bullet_objects_PhysicsRigidBody.cpp b/jme3-bullet-native/src/native/cpp/com_jme3_bullet_objects_PhysicsRigidBody.cpp
index 1d726038fd..3c05e124fb 100644
--- a/jme3-bullet-native/src/native/cpp/com_jme3_bullet_objects_PhysicsRigidBody.cpp
+++ b/jme3-bullet-native/src/native/cpp/com_jme3_bullet_objects_PhysicsRigidBody.cpp
@@ -52,9 +52,7 @@ extern "C" {
btMotionState* motionState = reinterpret_cast(motionstatId);
btCollisionShape* shape = reinterpret_cast(shapeId);
btVector3 localInertia = btVector3();
- if(mass > 0){
- shape->calculateLocalInertia(mass, localInertia);
- }
+ shape->calculateLocalInertia(mass, localInertia);
btRigidBody* body = new btRigidBody(mass, motionState, shape, localInertia);
body->setUserPointer(NULL);
return reinterpret_cast(body);
diff --git a/jme3-bullet/build.gradle b/jme3-bullet/build.gradle
index 404e6cb002..64185b3442 100644
--- a/jme3-bullet/build.gradle
+++ b/jme3-bullet/build.gradle
@@ -1,8 +1,11 @@
+apply plugin: 'java'
+
if (!hasProperty('mainClass')) {
ext.mainClass = ''
}
String classBuildDir = "${buildDir}" + File.separator + 'classes'
+def nativeIncludes = new File(project(":jme3-bullet-native").projectDir, "src/native/cpp")
sourceSets {
main {
@@ -18,22 +21,7 @@ dependencies {
compile project(':jme3-terrain')
}
-task generateNativeHeaders(type: Exec, dependsOn: classes) {
- def files0 = fileTree("src/main/java/").filter { it.isFile() && it.getName().endsWith(".java") }.files
- def files1 = fileTree("src/common/java/").filter { it.isFile() && it.getName().endsWith(".java") }.files
- def files2 = fileTree("../jme3-core/src/main/java/").filter { it.isFile() && it.getName().endsWith(".java") }.files
- def files3 = fileTree("../jme3-core/src/plugins/java/").filter { it.isFile() && it.getName().endsWith(".java") }.files
- def files4 = fileTree("../jme3-core/src/tools/java/").filter { it.isFile() && it.getName().endsWith(".java") }.files
- def files5 = fileTree("../jme3-terrain/src/main/java/").filter { it.isFile() && it.getName().endsWith(".java") }.files
- def classpath = sourceSets.main.runtimeClasspath.asPath
- def nativeIncludes = new File(project(":jme3-bullet-native").projectDir, "src/native/cpp")
- def filesList = "\"" + files0.join("\"\n\"") + "\"\n\"" + files1.join("\"\n\"") + "\"\n\"" + files2.join("\"\n\"") + "\"\n\"" + files3.join("\"\n\"") + "\"\n\"" + files4.join("\"\n\"") + "\"\n\"" + files5.join("\"\n\"") + "\""
- new File("$projectDir/java_classes.jtxt").text = filesList.replaceAll(java.util.regex.Pattern.quote("\\"), java.util.regex.Matcher.quoteReplacement("/"))
- executable org.gradle.internal.jvm.Jvm.current().getExecutable('javac')
- args "-h", nativeIncludes
- args "@$projectDir/java_classes.jtxt"
- args '-d', classBuildDir
- args "-encoding", "UTF-8"
+compileJava {
+ // The Android-Native Project requires the jni headers to be generated, so we do that here
+ options.compilerArgs += ["-h", nativeIncludes]
}
-
-assemble.dependsOn(generateNativeHeaders)
\ No newline at end of file
diff --git a/jme3-bullet/src/common/java/com/jme3/bullet/BulletAppState.java b/jme3-bullet/src/common/java/com/jme3/bullet/BulletAppState.java
index 9fb5b85f1c..2dc46906ce 100644
--- a/jme3-bullet/src/common/java/com/jme3/bullet/BulletAppState.java
+++ b/jme3-bullet/src/common/java/com/jme3/bullet/BulletAppState.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009-2018 jMonkeyEngine
+ * Copyright (c) 2009-2019 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -32,7 +32,7 @@
package com.jme3.bullet;
import com.jme3.app.Application;
-import com.jme3.app.state.AppState;
+import com.jme3.app.state.AbstractAppState;
import com.jme3.app.state.AppStateManager;
import com.jme3.bullet.PhysicsSpace.BroadphaseType;
import com.jme3.bullet.debug.BulletDebugAppState;
@@ -49,13 +49,15 @@
*
* @author normenhansen
*/
-public class BulletAppState implements AppState, PhysicsTickListener {
+public class BulletAppState
+ extends AbstractAppState
+ implements PhysicsTickListener {
/**
* true if-and-only-if the physics simulation is running (started but not
* yet stopped)
*/
- protected boolean initialized = false;
+ protected volatile boolean isRunning = false;
protected Application app;
/**
* manager that manages this state, set during attach
@@ -232,7 +234,7 @@ public PhysicsSpace getPhysicsSpace() {
* sooner, invoke this method.
*/
public void startPhysics() {
- if (initialized) {
+ if (isRunning) {
return;
}
@@ -252,14 +254,14 @@ public void startPhysics() {
throw new IllegalStateException(threadingType.toString());
}
- initialized = true;
+ isRunning = true;
}
/**
* Stop physics after this state is detached.
*/
public void stopPhysics() {
- if(!initialized){
+ if (!isRunning) {
return;
}
if (executor != null) {
@@ -268,7 +270,7 @@ public void stopPhysics() {
}
pSpace.removeTickListener(this);
pSpace.destroy();
- initialized = false;
+ isRunning = false;
}
/**
@@ -278,40 +280,14 @@ public void stopPhysics() {
* @param stateManager the manager for this state (not null)
* @param app the application which owns this state (not null)
*/
+ @Override
public void initialize(AppStateManager stateManager, Application app) {
+ super.initialize(stateManager, app);
this.app = app;
this.stateManager = stateManager;
startPhysics();
}
- /**
- * Test whether the physics simulation is running (started but not yet
- * stopped).
- *
- * @return true if running, otherwise false
- */
- public boolean isInitialized() {
- return initialized;
- }
-
- /**
- * Enable or disable this state.
- *
- * @param enabled true → enable, false → disable
- */
- public void setEnabled(boolean enabled) {
- this.active = enabled;
- }
-
- /**
- * Test whether this state is enabled.
- *
- * @return true if enabled, otherwise false
- */
- public boolean isEnabled() {
- return active;
- }
-
/**
* Alter whether debug visualization is enabled.
*
@@ -337,8 +313,10 @@ public boolean isDebugEnabled() {
*
* @param stateManager (not null)
*/
+ @Override
public void stateAttached(AppStateManager stateManager) {
- if (!initialized) {
+ super.stateAttached(stateManager);
+ if (!isRunning) {
startPhysics();
}
if (threadingType == ThreadingType.PARALLEL) {
@@ -350,15 +328,6 @@ public void stateAttached(AppStateManager stateManager) {
}
}
- /**
- * Transition this state from running to terminating. Should be invoked only
- * by a subclass or by the AppStateManager.
- *
- * @param stateManager (not null)
- */
- public void stateDetached(AppStateManager stateManager) {
- }
-
/**
* Update this state prior to rendering. Should be invoked only by a
* subclass or by the AppStateManager. Invoked once per frame, provided the
@@ -366,7 +335,9 @@ public void stateDetached(AppStateManager stateManager) {
*
* @param tpf the time interval between frames (in seconds, ≥0)
*/
+ @Override
public void update(float tpf) {
+ super.update(tpf);
if (debugEnabled && debugAppState == null && pSpace != null) {
debugAppState = new BulletDebugAppState(pSpace);
stateManager.attach(debugAppState);
@@ -388,7 +359,9 @@ public void update(float tpf) {
*
* @param rm the render manager (not null)
*/
+ @Override
public void render(RenderManager rm) {
+ super.render(rm);
if (!active) {
return;
}
@@ -405,7 +378,9 @@ public void render(RenderManager rm) {
* invoked only by a subclass or by the AppStateManager. Invoked once per
* frame, provided the state is attached and enabled.
*/
+ @Override
public void postRender() {
+ super.postRender();
if (physicsFuture != null) {
try {
physicsFuture.get();
@@ -424,12 +399,14 @@ public void postRender() {
* {@link #initialize(com.jme3.app.state.AppStateManager, com.jme3.app.Application)}
* is invoked.
*/
+ @Override
public void cleanup() {
if (debugAppState != null) {
stateManager.detach(debugAppState);
debugAppState = null;
}
stopPhysics();
+ super.cleanup();
}
/**
diff --git a/jme3-bullet/src/main/java/com/jme3/bullet/collision/PhysicsCollisionObject.java b/jme3-bullet/src/main/java/com/jme3/bullet/collision/PhysicsCollisionObject.java
index ea8ced87c8..df4265be5c 100644
--- a/jme3-bullet/src/main/java/com/jme3/bullet/collision/PhysicsCollisionObject.java
+++ b/jme3-bullet/src/main/java/com/jme3/bullet/collision/PhysicsCollisionObject.java
@@ -158,6 +158,18 @@ public CollisionShape getCollisionShape() {
return collisionShape;
}
+ /**
+ * Read the deactivation time.
+ *
+ * @return the time (in seconds)
+ */
+ public float getDeactivationTime() {
+ float time = getDeactivationTime(objectId);
+ return time;
+ }
+
+ native private float getDeactivationTime(long objectId);
+
/**
* Read the collision group for this physics object.
*
diff --git a/jme3-bullet/src/main/java/com/jme3/bullet/collision/shapes/CollisionShape.java b/jme3-bullet/src/main/java/com/jme3/bullet/collision/shapes/CollisionShape.java
index acdd6ed04d..94d39973d9 100644
--- a/jme3-bullet/src/main/java/com/jme3/bullet/collision/shapes/CollisionShape.java
+++ b/jme3-bullet/src/main/java/com/jme3/bullet/collision/shapes/CollisionShape.java
@@ -87,7 +87,7 @@ public CollisionShape() {
//// objectId.calculateLocalInertia(mass, vector);
//// }
// }
-//
+//
// private native void calculateLocalInertia(long objectId, long shapeId, float mass);
/**
@@ -129,6 +129,19 @@ public Vector3f getScale() {
return scale;
}
+ /**
+ * Test whether this shape can be applied to a dynamic rigid body. The only
+ * non-moving shapes are the heightfield, mesh, and plane shapes.
+ *
+ * @return true if non-moving, false otherwise
+ */
+ public boolean isNonMoving() {
+ boolean result = isNonMoving(objectId);
+ return result;
+ }
+
+ native private boolean isNonMoving(long objectId);
+
/**
* Read the collision margin for this shape.
*
@@ -137,7 +150,7 @@ public Vector3f getScale() {
public float getMargin() {
return getMargin(objectId);
}
-
+
private native float getMargin(long objectId);
/**
@@ -177,9 +190,9 @@ public void setMargin(float margin) {
setMargin(objectId, margin);
this.margin = margin;
}
-
+
private native void setLocalScaling(long obectId, Vector3f scale);
-
+
private native void setMargin(long objectId, float margin);
/**
diff --git a/jme3-bullet/src/main/java/com/jme3/bullet/collision/shapes/GImpactCollisionShape.java b/jme3-bullet/src/main/java/com/jme3/bullet/collision/shapes/GImpactCollisionShape.java
index 0f9cfc4256..2e5dc9704e 100644
--- a/jme3-bullet/src/main/java/com/jme3/bullet/collision/shapes/GImpactCollisionShape.java
+++ b/jme3-bullet/src/main/java/com/jme3/bullet/collision/shapes/GImpactCollisionShape.java
@@ -36,6 +36,7 @@
import com.jme3.export.JmeExporter;
import com.jme3.export.JmeImporter;
import com.jme3.export.OutputCapsule;
+import com.jme3.math.Vector3f;
import com.jme3.scene.Mesh;
import com.jme3.scene.VertexBuffer.Type;
import com.jme3.scene.mesh.IndexBuffer;
@@ -153,6 +154,23 @@ public void read(JmeImporter im) throws IOException {
vertexBase = ByteBuffer.wrap(capsule.readByteArray("vertexBase", new byte[0]));
createShape();
}
+
+ /**
+ * Alter the scaling factors of this shape.
+ *
+ * Note that if the shape is shared (between collision objects and/or
+ * compound shapes) changes can have unintended consequences.
+ *
+ * @param scale the desired scaling factor for each local axis (not null, no
+ * negative component, unaffected, default=(1,1,1))
+ */
+ @Override
+ public void setScale(Vector3f scale) {
+ super.setScale(scale);
+ recalcAabb(objectId);
+ }
+
+ native private void recalcAabb(long shapeId);
/**
* Instantiate the configured shape in Bullet.
diff --git a/jme3-bullet/src/main/java/com/jme3/bullet/collision/shapes/HeightfieldCollisionShape.java b/jme3-bullet/src/main/java/com/jme3/bullet/collision/shapes/HeightfieldCollisionShape.java
index f4fcaef6d6..0a4140bdbb 100644
--- a/jme3-bullet/src/main/java/com/jme3/bullet/collision/shapes/HeightfieldCollisionShape.java
+++ b/jme3-bullet/src/main/java/com/jme3/bullet/collision/shapes/HeightfieldCollisionShape.java
@@ -147,7 +147,7 @@ protected void createCollisionHeightfield(float[] heightmap, Vector3f worldScale
this.maxHeight = max;
this.upAxis = 1;
- this.flipQuadEdges = false;
+ flipQuadEdges = true;
heightStickWidth = (int) FastMath.sqrt(heightfieldData.length);
heightStickLength = heightStickWidth;
diff --git a/jme3-bullet/src/main/java/com/jme3/bullet/joints/SixDofJoint.java b/jme3-bullet/src/main/java/com/jme3/bullet/joints/SixDofJoint.java
index 660319a18e..27e4c48b93 100644
--- a/jme3-bullet/src/main/java/com/jme3/bullet/joints/SixDofJoint.java
+++ b/jme3-bullet/src/main/java/com/jme3/bullet/joints/SixDofJoint.java
@@ -166,6 +166,24 @@ private void gatherMotors() {
translationalMotor = new TranslationalLimitMotor(getTranslationalLimitMotor(objectId));
}
+ native private void getAngles(long jointId, Vector3f storeVector);
+
+ /**
+ * Copy the joint's rotation angles.
+ *
+ * @param storeResult storage for the result (modified if not null)
+ * @return the rotation angle for each local axis (in radians, either
+ * storeResult or a new vector, not null)
+ */
+ public Vector3f getAngles(Vector3f storeResult) {
+ Vector3f result = (storeResult == null) ? new Vector3f() : storeResult;
+
+ long constraintId = getObjectId();
+ getAngles(constraintId, result);
+
+ return result;
+ }
+
private native long getRotationalLimitMotor(long objectId, int index);
private native long getTranslationalLimitMotor(long objectId);
@@ -281,6 +299,11 @@ public void read(JmeImporter im) throws IOException {
getTranslationalLimitMotor().setLowerLimit((Vector3f) capsule.readSavable("transMotor_LowerLimit", Vector3f.ZERO));
getTranslationalLimitMotor().setRestitution(capsule.readFloat("transMotor_Restitution", 0.5f));
getTranslationalLimitMotor().setUpperLimit((Vector3f) capsule.readSavable("transMotor_UpperLimit", Vector3f.ZERO));
+
+ for (int axisIndex = 0; axisIndex < 3; ++axisIndex) {
+ translationalMotor.setEnabled(axisIndex, capsule.readBoolean(
+ "transMotor_Enable" + axisIndex, false));
+ }
}
/**
@@ -318,5 +341,10 @@ public void write(JmeExporter ex) throws IOException {
capsule.write(getTranslationalLimitMotor().getLowerLimit(), "transMotor_LowerLimit", Vector3f.ZERO);
capsule.write(getTranslationalLimitMotor().getRestitution(), "transMotor_Restitution", 0.5f);
capsule.write(getTranslationalLimitMotor().getUpperLimit(), "transMotor_UpperLimit", Vector3f.ZERO);
+
+ for (int axisIndex = 0; axisIndex < 3; ++axisIndex) {
+ capsule.write(translationalMotor.isEnabled(axisIndex),
+ "transMotor_Enable" + axisIndex, false);
+ }
}
}
diff --git a/jme3-bullet/src/main/java/com/jme3/bullet/joints/motors/TranslationalLimitMotor.java b/jme3-bullet/src/main/java/com/jme3/bullet/joints/motors/TranslationalLimitMotor.java
index 97993edd3a..4fbf0cb896 100644
--- a/jme3-bullet/src/main/java/com/jme3/bullet/joints/motors/TranslationalLimitMotor.java
+++ b/jme3-bullet/src/main/java/com/jme3/bullet/joints/motors/TranslationalLimitMotor.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009-2018 jMonkeyEngine
+ * Copyright (c) 2009-2019 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -204,4 +204,30 @@ public void setRestitution(float restitution) {
}
private native void setRestitution(long motorId, float restitution);
+
+ /**
+ * Enable or disable the indexed axis.
+ *
+ * @param axisIndex which axis: 0→X, 1→Y, 2→Z
+ * @param enableMotor true→enable, false→disable (default=false)
+ */
+ public void setEnabled(int axisIndex, boolean enableMotor) {
+ setEnabled(motorId, axisIndex, enableMotor);
+ }
+
+ native private void setEnabled(long motorId, int axisIndex,
+ boolean enableMotor);
+
+ /**
+ * Test whether the indexed axis is enabled.
+ *
+ * @param axisIndex which axis: 0→X, 1→Y, 2→Z
+ * @return true if enabled, otherwise false
+ */
+ public boolean isEnabled(int axisIndex) {
+ boolean result = isEnabled(motorId, axisIndex);
+ return result;
+ }
+
+ native private boolean isEnabled(long motorId, int axisIndex);
}
diff --git a/jme3-core/src/main/java/com/jme3/anim/AnimComposer.java b/jme3-core/src/main/java/com/jme3/anim/AnimComposer.java
index d997ab39d1..740c4e034e 100644
--- a/jme3-core/src/main/java/com/jme3/anim/AnimComposer.java
+++ b/jme3-core/src/main/java/com/jme3/anim/AnimComposer.java
@@ -32,6 +32,10 @@ public AnimComposer() {
layers.put(DEFAULT_LAYER, new Layer(this));
}
+ public boolean hasAnimClip(String name) {
+ return animClipMap.containsKey(name);
+ }
+
/**
* Retrieve an animation from the list of animations.
*
@@ -104,6 +108,36 @@ public void removeCurrentAction(String layerName) {
l.time = 0;
l.currentAction = null;
}
+
+ /**
+ * Returns current time of the specified layer.
+ */
+ public double getTime(String layerName) {
+ Layer l = layers.get(layerName);
+ if (l == null) {
+ throw new IllegalArgumentException("Unknown layer " + layerName);
+ }
+ return l.time;
+ }
+
+ /**
+ * Sets current time on the specified layer.
+ */
+ public void setTime(String layerName, double time) {
+ Layer l = layers.get(layerName);
+ if (l == null) {
+ throw new IllegalArgumentException("Unknown layer " + layerName);
+ }
+ if (l.currentAction == null) {
+ throw new RuntimeException("There is no action running in layer " + layerName);
+ }
+ double length = l.currentAction.getLength();
+ if (time >= 0) {
+ l.time = time % length;
+ } else {
+ l.time = time % length + length;
+ }
+ }
/**
*
diff --git a/jme3-core/src/main/java/com/jme3/anim/Joint.java b/jme3-core/src/main/java/com/jme3/anim/Joint.java
index 0c7153d296..1c1699f64e 100644
--- a/jme3-core/src/main/java/com/jme3/anim/Joint.java
+++ b/jme3-core/src/main/java/com/jme3/anim/Joint.java
@@ -268,6 +268,9 @@ Node getAttachmentsNode(int jointIndex, SafeArrayList targets) {
return attachedNode;
}
+ public Transform getInitialTransform() {
+ return initialTransform;
+ }
public Transform getLocalTransform() {
return localTransform;
diff --git a/jme3-core/src/main/java/com/jme3/anim/TransformTrack.java b/jme3-core/src/main/java/com/jme3/anim/TransformTrack.java
index 29354fead0..63eba06cfc 100644
--- a/jme3-core/src/main/java/com/jme3/anim/TransformTrack.java
+++ b/jme3-core/src/main/java/com/jme3/anim/TransformTrack.java
@@ -233,11 +233,13 @@ public void getDataAtTime(double t, Transform transform) {
int endFrame = 1;
float blend = 0;
if (time >= times[lastFrame]) {
+ // extrapolate beyond the final frame of the animation
startFrame = lastFrame;
- time = time - times[startFrame] + times[startFrame - 1];
- blend = (time - times[startFrame - 1])
- / (times[startFrame] - times[startFrame - 1]);
+ float inferredInterval = times[lastFrame] - times[lastFrame - 1];
+ if (inferredInterval > 0f) {
+ blend = (time - times[startFrame]) / inferredInterval;
+ }
} else {
// use lastFrame so we never overflow the array
@@ -297,7 +299,7 @@ public void read(JmeImporter im) throws IOException {
}
@Override
- public Object jmeClone() {
+ public TransformTrack jmeClone() {
try {
TransformTrack clone = (TransformTrack) super.clone();
return clone;
diff --git a/jme3-core/src/main/java/com/jme3/anim/tween/action/BlendableAction.java b/jme3-core/src/main/java/com/jme3/anim/tween/action/BlendableAction.java
index 4b3b6f9660..4ebf3ede2b 100644
--- a/jme3-core/src/main/java/com/jme3/anim/tween/action/BlendableAction.java
+++ b/jme3-core/src/main/java/com/jme3/anim/tween/action/BlendableAction.java
@@ -74,6 +74,7 @@ public double getTransitionLength() {
public void setTransitionLength(double transitionLength) {
this.transitionLength = transitionLength;
+ this.transition.setLength(transitionLength);
}
protected float getTransitionWeight() {
diff --git a/jme3-core/src/main/java/com/jme3/app/state/AbstractAppState.java b/jme3-core/src/main/java/com/jme3/app/state/AbstractAppState.java
index c2e3642da6..96b7e6b6c0 100644
--- a/jme3-core/src/main/java/com/jme3/app/state/AbstractAppState.java
+++ b/jme3-core/src/main/java/com/jme3/app/state/AbstractAppState.java
@@ -40,7 +40,7 @@
* @author Kirill Vainer
* @see com.jme3.app.state.BaseAppState
*/
-public class AbstractAppState implements AppState {
+public abstract class AbstractAppState implements AppState {
/**
* initialized is set to true when the method
@@ -50,38 +50,70 @@ public class AbstractAppState implements AppState {
*/
protected boolean initialized = false;
private boolean enabled = true;
+ private String id;
+
+ protected AbstractAppState() {
+ }
+
+ protected AbstractAppState( String id ) {
+ this.id = id;
+ }
+ @Override
public void initialize(AppStateManager stateManager, Application app) {
initialized = true;
}
+ @Override
public boolean isInitialized() {
return initialized;
}
+ /**
+ * Sets the unique ID of this app state. Note: that setting
+ * this while an app state is attached to the state manager will
+ * have no effect on ID-based lookups.
+ */
+ protected void setId( String id ) {
+ this.id = id;
+ }
+
+ @Override
+ public String getId() {
+ return id;
+ }
+
+ @Override
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
+ @Override
public boolean isEnabled() {
return enabled;
}
+ @Override
public void stateAttached(AppStateManager stateManager) {
}
+ @Override
public void stateDetached(AppStateManager stateManager) {
}
+ @Override
public void update(float tpf) {
}
+ @Override
public void render(RenderManager rm) {
}
+ @Override
public void postRender(){
}
+ @Override
public void cleanup() {
initialized = false;
}
diff --git a/jme3-core/src/main/java/com/jme3/app/state/AppState.java b/jme3-core/src/main/java/com/jme3/app/state/AppState.java
index 72988c0efd..33a6d28d5d 100644
--- a/jme3-core/src/main/java/com/jme3/app/state/AppState.java
+++ b/jme3-core/src/main/java/com/jme3/app/state/AppState.java
@@ -90,6 +90,12 @@ public interface AppState {
*/
public boolean isInitialized();
+ /**
+ * Returns the unique ID for this AppState or null if it has no
+ * unique ID.
+ */
+ public String getId();
+
/**
* Enable or disable the functionality of the AppState.
* The effect of this call depends on implementation. An
diff --git a/jme3-core/src/main/java/com/jme3/app/state/AppStateManager.java b/jme3-core/src/main/java/com/jme3/app/state/AppStateManager.java
index b15b555989..96a7295d35 100644
--- a/jme3-core/src/main/java/com/jme3/app/state/AppStateManager.java
+++ b/jme3-core/src/main/java/com/jme3/app/state/AppStateManager.java
@@ -37,6 +37,8 @@
import com.jme3.util.SafeArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ConcurrentHashMap;
/**
* The AppStateManager holds a list of {@link AppState}s which
@@ -82,6 +84,12 @@ public class AppStateManager {
* cleanup.
*/
private final SafeArrayList terminating = new SafeArrayList(AppState.class);
+
+ /**
+ * Thread-safe index of every state that is currently attached and has
+ * an ID.
+ */
+ private final ConcurrentMap stateIndex = new ConcurrentHashMap<>();
// All of the above lists need to be thread safe but access will be
// synchronized separately.... but always on the states list. This
@@ -122,7 +130,8 @@ protected AppState[] getStates(){
/**
* Attach a state to the AppStateManager, the same state cannot be attached
- * twice.
+ * twice. Throws an IllegalArgumentException if the state has an ID and that
+ * ID has already been associated with another AppState.
*
* @param state The state to attach
* @return True if the state was successfully attached, false if the state
@@ -130,11 +139,16 @@ protected AppState[] getStates(){
*/
public boolean attach(AppState state){
synchronized (states){
+ if( state.getId() != null && stateIndex.putIfAbsent(state.getId(), state) != null ) {
+ throw new IllegalArgumentException("ID:" + state.getId()
+ + " is already being used by another state:"
+ + stateIndex.get(state.getId()));
+ }
if (!states.contains(state) && !initializing.contains(state)){
state.stateAttached(this);
initializing.add(state);
return true;
- }else{
+ } else {
return false;
}
}
@@ -175,6 +189,12 @@ public void attachAll(Iterable states){
*/
public boolean detach(AppState state){
synchronized (states){
+
+ // Remove it from the index if it exists.
+ // Note: we remove it directly from the values() in case
+ // the state has changed its ID since registered.
+ stateIndex.values().remove(state);
+
if (states.contains(state)){
state.stateDetached(this);
states.remove(state);
@@ -249,6 +269,35 @@ public T getState(Class stateClass, boolean failOnMiss){
return null;
}
+ /**
+ * Returns the state associated with the specified ID at the time it was
+ * attached or null if not state was attached with that ID.
+ */
+ public T getState( String id, Class stateClass ) {
+ return stateClass.cast(stateIndex.get(id));
+ }
+
+ /**
+ * Returns true if there is currently a state associated with the specified
+ * ID.
+ */
+ public boolean hasState( String id ) {
+ return stateIndex.containsKey(id);
+ }
+
+ /**
+ * Returns the state associated with the specified ID at the time it
+ * was attached or throws an IllegalArgumentException if the ID was
+ * not found.
+ */
+ public T stateForId( String id, Class stateClass ) {
+ T result = getState(id, stateClass);
+ if( result == null ) {
+ throw new IllegalArgumentException("State not found for:" + id);
+ }
+ return stateClass.cast(result);
+ }
+
protected void initializePending(){
AppState[] array = getInitializing();
if (array.length == 0)
diff --git a/jme3-core/src/main/java/com/jme3/app/state/BaseAppState.java b/jme3-core/src/main/java/com/jme3/app/state/BaseAppState.java
index cee045355e..a745215613 100644
--- a/jme3-core/src/main/java/com/jme3/app/state/BaseAppState.java
+++ b/jme3-core/src/main/java/com/jme3/app/state/BaseAppState.java
@@ -78,6 +78,14 @@ public abstract class BaseAppState implements AppState {
private Application app;
private boolean initialized;
private boolean enabled = true;
+ private String id;
+
+ protected BaseAppState() {
+ }
+
+ protected BaseAppState( String id ) {
+ this.id = id;
+ }
/**
* Called during initialization once the app state is
@@ -133,6 +141,20 @@ public final boolean isInitialized() {
return initialized;
}
+ /**
+ * Sets the unique ID of this app state. Note: that setting
+ * this while an app state is attached to the state manager will
+ * have no effect on ID-based lookups.
+ */
+ protected void setId( String id ) {
+ this.id = id;
+ }
+
+ @Override
+ public String getId() {
+ return id;
+ }
+
public final Application getApplication() {
return app;
}
diff --git a/jme3-core/src/main/java/com/jme3/app/state/RootNodeAppState.java b/jme3-core/src/main/java/com/jme3/app/state/RootNodeAppState.java
index 8daa9dc3a7..f7406ba55a 100644
--- a/jme3-core/src/main/java/com/jme3/app/state/RootNodeAppState.java
+++ b/jme3-core/src/main/java/com/jme3/app/state/RootNodeAppState.java
@@ -85,6 +85,18 @@ public RootNodeAppState(ViewPort viewPort, Node rootNode) {
this.rootNode = rootNode;
}
+ /**
+ * Creates the AppState with the given unique ID, ViewPort, and root Node, attaches
+ * the root Node to the ViewPort and updates it.
+ * @param viewPort An existing ViewPort
+ * @param rootNode An existing root Node
+ */
+ public RootNodeAppState( String id, ViewPort viewPort, Node rootNode ) {
+ super(id);
+ this.viewPort = viewPort;
+ this.rootNode = rootNode;
+ }
+
@Override
public void initialize(AppStateManager stateManager, Application app) {
if (rootNode == null) {
@@ -101,6 +113,12 @@ public void initialize(AppStateManager stateManager, Application app) {
public void update(float tpf) {
super.update(tpf);
rootNode.updateLogicalState(tpf);
+
+ // FIXME: I'm 99% sure that updateGeometricState() should be
+ // called in render() so that it is done as late as possible.
+ // In complicated app state setups, cross-state chatter could
+ // cause nodes (or their children) to be updated after this
+ // app state's update has been called. -pspeed:2019-09-15
rootNode.updateGeometricState();
}
diff --git a/jme3-core/src/main/java/com/jme3/asset/DesktopAssetManager.java b/jme3-core/src/main/java/com/jme3/asset/DesktopAssetManager.java
index bf6b41b7ab..0c92e19e91 100644
--- a/jme3-core/src/main/java/com/jme3/asset/DesktopAssetManager.java
+++ b/jme3-core/src/main/java/com/jme3/asset/DesktopAssetManager.java
@@ -41,6 +41,7 @@
import com.jme3.scene.Spatial;
import com.jme3.shader.Glsl100ShaderGenerator;
import com.jme3.shader.Glsl150ShaderGenerator;
+import com.jme3.shader.Glsl300ShaderGenerator;
import com.jme3.shader.ShaderGenerator;
import com.jme3.system.JmeSystem;
import com.jme3.texture.Texture;
@@ -434,7 +435,9 @@ public FilterPostProcessor loadFilter(String name){
@Override
public ShaderGenerator getShaderGenerator(EnumSet caps) {
if (shaderGenerator == null) {
- if(caps.contains(Caps.GLSL150)){
+ if(caps.contains(Caps.OpenGLES30) && caps.contains(Caps.GLSL300)){
+ shaderGenerator = new Glsl300ShaderGenerator(this);
+ }else if(caps.contains(Caps.GLSL150)) {
shaderGenerator = new Glsl150ShaderGenerator(this);
}else{
shaderGenerator = new Glsl100ShaderGenerator(this);
diff --git a/jme3-core/src/main/java/com/jme3/audio/AudioNode.java b/jme3-core/src/main/java/com/jme3/audio/AudioNode.java
index becc7fa19e..fead019aea 100644
--- a/jme3-core/src/main/java/com/jme3/audio/AudioNode.java
+++ b/jme3-core/src/main/java/com/jme3/audio/AudioNode.java
@@ -158,6 +158,7 @@ public AudioNode(AssetManager assetManager, String name, DataType type) {
*
* @deprecated Use {@link AudioNode#AudioNode(com.jme3.asset.AssetManager, java.lang.String, com.jme3.audio.AudioData.DataType)} instead
*/
+ @Deprecated
public AudioNode(AssetManager assetManager, String name, boolean stream, boolean streamCache) {
this.audioKey = new AudioKey(name, stream, streamCache);
this.data = (AudioData) assetManager.loadAsset(audioKey);
@@ -173,6 +174,7 @@ public AudioNode(AssetManager assetManager, String name, boolean stream, boolean
*
* @deprecated Use {@link AudioNode#AudioNode(com.jme3.asset.AssetManager, java.lang.String, com.jme3.audio.AudioData.DataType)} instead
*/
+ @Deprecated
public AudioNode(AssetManager assetManager, String name, boolean stream) {
this(assetManager, name, stream, true); // Always streamCached
}
@@ -186,6 +188,7 @@ public AudioNode(AssetManager assetManager, String name, boolean stream) {
*
* @deprecated AudioRenderer parameter is ignored.
*/
+ @Deprecated
public AudioNode(AudioRenderer audioRenderer, AssetManager assetManager, String name) {
this(assetManager, name, DataType.Buffer);
}
@@ -197,6 +200,7 @@ public AudioNode(AudioRenderer audioRenderer, AssetManager assetManager, String
* @param name The filename of the audio file
* @deprecated Use {@link AudioNode#AudioNode(com.jme3.asset.AssetManager, java.lang.String, com.jme3.audio.AudioData.DataType) } instead
*/
+ @Deprecated
public AudioNode(AssetManager assetManager, String name) {
this(assetManager, name, DataType.Buffer);
}
@@ -722,7 +726,7 @@ public void updateLogicalState(float tpf) {
@Override
public void updateGeometricState() {
super.updateGeometricState();
- if (channel < 0 || this.getParent() == null) return;
+ if (channel < 0) return;
Vector3f currentWorldTranslation = worldTransform.getTranslation();
if (!previousWorldTranslation.equals(currentWorldTranslation)) {
getRenderer().updateSourceParam(this, AudioParam.Position);
diff --git a/jme3-core/src/main/java/com/jme3/bounding/BoundingBox.java b/jme3-core/src/main/java/com/jme3/bounding/BoundingBox.java
index c087950a38..6e422dea42 100644
--- a/jme3-core/src/main/java/com/jme3/bounding/BoundingBox.java
+++ b/jme3-core/src/main/java/com/jme3/bounding/BoundingBox.java
@@ -79,9 +79,9 @@ public BoundingBox() {
* Instantiate a BoundingBox with given center and extents.
*
* @param c the coordinates of the center of the box (not null, not altered)
- * @param x the X-extent of the box (>=0, may be +Infinity)
- * @param y the Y-extent of the box (>=0, may be +Infinity)
- * @param z the Z-extent of the box (>=0, may be +Infinity)
+ * @param x the X-extent of the box (0 or greater, may be +Infinity)
+ * @param y the Y-extent of the box (0 or greater, may be +Infinity)
+ * @param z the Z-extent of the box (0 or greater, may be +Infinity)
*/
public BoundingBox(Vector3f c, float x, float y, float z) {
this.center.set(c);
diff --git a/jme3-core/src/main/java/com/jme3/bounding/BoundingSphere.java b/jme3-core/src/main/java/com/jme3/bounding/BoundingSphere.java
index 3137f2cbf7..7936c72244 100644
--- a/jme3-core/src/main/java/com/jme3/bounding/BoundingSphere.java
+++ b/jme3-core/src/main/java/com/jme3/bounding/BoundingSphere.java
@@ -173,11 +173,11 @@ public void computeFromTris(Triangle[] tris, int start, int end) {
/**
* Calculates a minimum bounding sphere for the set of points. The algorithm
- * was originally found in C++ at
- *
- *
+ * was originally found in C++ at
+ *
+ * http://flipcode.com/archives/Smallest_Enclosing_Spheres.shtml
+ * and translated to java by Cep21
+ *
* @param points
* The points to calculate the minimum bounds from.
*/
diff --git a/jme3-core/src/main/java/com/jme3/cinematic/Cinematic.java b/jme3-core/src/main/java/com/jme3/cinematic/Cinematic.java
index d9e9d5b11f..3bcbc17a74 100644
--- a/jme3-core/src/main/java/com/jme3/cinematic/Cinematic.java
+++ b/jme3-core/src/main/java/com/jme3/cinematic/Cinematic.java
@@ -99,6 +99,7 @@ public class Cinematic extends AbstractCinematicEvent implements AppState {
private boolean initialized = false;
private Map> eventsData;
private float nextEnqueue = 0;
+ private String id;
/**
* Used for serialization creates a cinematic, don't use this constructor
@@ -291,6 +292,20 @@ public boolean isInitialized() {
return initialized;
}
+ /**
+ * Sets the unique ID of this app state. Note: that setting
+ * this while an app state is attached to the state manager will
+ * have no effect on ID-based lookups.
+ */
+ protected void setId( String id ) {
+ this.id = id;
+ }
+
+ @Override
+ public String getId() {
+ return id;
+ }
+
/**
* passing true has the same effect as play() you should use play(),
* pause(), stop() to handle the cinematic playing state.
diff --git a/jme3-core/src/main/java/com/jme3/cinematic/events/CameraEvent.java b/jme3-core/src/main/java/com/jme3/cinematic/events/CameraEvent.java
index 91b9ee5e18..8d2b708942 100644
--- a/jme3-core/src/main/java/com/jme3/cinematic/events/CameraEvent.java
+++ b/jme3-core/src/main/java/com/jme3/cinematic/events/CameraEvent.java
@@ -41,7 +41,7 @@
/**
*
- * @author Rickard
+ * @author Rickard (neph1 @ github)
*/
public class CameraEvent extends AbstractCinematicEvent{
diff --git a/jme3-core/src/main/java/com/jme3/effect/ParticleEmitter.java b/jme3-core/src/main/java/com/jme3/effect/ParticleEmitter.java
index 020803c876..19268b8175 100644
--- a/jme3-core/src/main/java/com/jme3/effect/ParticleEmitter.java
+++ b/jme3-core/src/main/java/com/jme3/effect/ParticleEmitter.java
@@ -783,7 +783,7 @@ public float getParticlesPerSec() {
*/
public void setParticlesPerSec(float particlesPerSec) {
this.particlesPerSec = particlesPerSec;
- timeDifference = 0;
+ timeDifference = Math.min(timeDifference,1f / particlesPerSec); //prevent large accumulated timeDifference from causing a huge number of particles to be emitted
}
/**
diff --git a/jme3-core/src/main/java/com/jme3/export/SavableClassUtil.java b/jme3-core/src/main/java/com/jme3/export/SavableClassUtil.java
index d41e6bb925..2e206a416b 100644
--- a/jme3-core/src/main/java/com/jme3/export/SavableClassUtil.java
+++ b/jme3-core/src/main/java/com/jme3/export/SavableClassUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009-2012 jMonkeyEngine
+ * Copyright (c) 2009-2019 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -36,7 +36,9 @@
import com.jme3.material.MatParamTexture;
import java.io.IOException;
+import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -161,16 +163,19 @@ public static int getSavedSavableVersion(Object savable, Class extends Savable
* @return the Savable instance of the class.
* @throws InstantiationException thrown if the class does not have an empty constructor.
* @throws IllegalAccessException thrown if the class is not accessable.
+ * @throws java.lang.reflect.InvocationTargetException
* @throws ClassNotFoundException thrown if the class name is not in the classpath.
- * @throws IOException when loading ctor parameters fails
*/
- public static Savable fromName(String className) throws InstantiationException,
- IllegalAccessException, ClassNotFoundException, IOException {
-
+ public static Savable fromName(String className)
+ throws ClassNotFoundException, IllegalAccessException,
+ InstantiationException, InvocationTargetException {
className = remapClass(className);
+
+ Constructor noArgConstructor = findNoArgConstructor(className);
+ noArgConstructor.setAccessible(true);
try {
- return (Savable) Class.forName(className).newInstance();
- } catch (InstantiationException e) {
+ return (Savable) noArgConstructor.newInstance();
+ } catch (InvocationTargetException | InstantiationException e) {
Logger.getLogger(SavableClassUtil.class.getName()).log(
Level.SEVERE, "Could not access constructor of class ''{0}" + "''! \n"
+ "Some types need to have the BinaryImporter set up in a special way. Please doublecheck the setup.", className);
@@ -184,6 +189,7 @@ public static Savable fromName(String className) throws InstantiationException,
}
public static Savable fromName(String className, List loaders) throws InstantiationException,
+ InvocationTargetException, NoSuchMethodException,
IllegalAccessException, ClassNotFoundException, IOException {
if (loaders == null) {
return fromName(className);
@@ -208,4 +214,25 @@ public static Savable fromName(String className, List loaders) thro
return fromName(className);
}
+
+ /**
+ * Use reflection to gain access to the no-arg constructor of the named
+ * class.
+ *
+ * @return the pre-existing constructor (not null)
+ */
+ private static Constructor findNoArgConstructor(String className)
+ throws ClassNotFoundException, InstantiationException {
+ Class clazz = Class.forName(className);
+ Constructor result;
+ try {
+ result = clazz.getDeclaredConstructor();
+ } catch (NoSuchMethodException e) {
+ throw new InstantiationException(
+ "Loading requires a no-arg constructor, but class "
+ + className + " lacks one.");
+ }
+
+ return result;
+ }
}
diff --git a/jme3-core/src/main/java/com/jme3/input/AbstractJoystick.java b/jme3-core/src/main/java/com/jme3/input/AbstractJoystick.java
index 5ced607ffe..ee0d4b9e86 100644
--- a/jme3-core/src/main/java/com/jme3/input/AbstractJoystick.java
+++ b/jme3-core/src/main/java/com/jme3/input/AbstractJoystick.java
@@ -98,6 +98,7 @@ public void rumble(float amount){
* @deprecated Use JoystickButton.assignButton() instead.
*/
@Override
+ @Deprecated
public void assignButton(String mappingName, int buttonId){
if (buttonId < 0 || buttonId >= getButtonCount())
throw new IllegalArgumentException();
@@ -116,6 +117,7 @@ public void assignButton(String mappingName, int buttonId){
* @deprecated Use JoystickAxis.assignAxis() instead.
*/
@Override
+ @Deprecated
public void assignAxis(String positiveMapping, String negativeMapping, int axisId){
// For backwards compatibility
diff --git a/jme3-core/src/main/java/com/jme3/input/InputManager.java b/jme3-core/src/main/java/com/jme3/input/InputManager.java
index eb15f1c8b6..a8f56c3b9a 100644
--- a/jme3-core/src/main/java/com/jme3/input/InputManager.java
+++ b/jme3-core/src/main/java/com/jme3/input/InputManager.java
@@ -776,6 +776,7 @@ public void setSimulateMouse(boolean value) {
* Returns state of simulation of mouse events. Used for touchscreen input only.
*
*/
+ @Deprecated
public boolean getSimulateMouse() {
if (touch != null) {
return touch.isSimulateMouse();
diff --git a/jme3-core/src/main/java/com/jme3/input/Joystick.java b/jme3-core/src/main/java/com/jme3/input/Joystick.java
index 8c55c906ed..e172224c2f 100644
--- a/jme3-core/src/main/java/com/jme3/input/Joystick.java
+++ b/jme3-core/src/main/java/com/jme3/input/Joystick.java
@@ -57,6 +57,7 @@ public interface Joystick {
* @see Joystick#getButtonCount()
* @deprecated Use JoystickButton.assignButton() instead.
*/
+ @Deprecated
public void assignButton(String mappingName, int buttonId);
/**
@@ -69,6 +70,7 @@ public interface Joystick {
* @see Joystick#getAxisCount()
* @deprecated Use JoystickAxis.assignAxis() instead.
*/
+ @Deprecated
public void assignAxis(String positiveMapping, String negativeMapping, int axisId);
/**
diff --git a/jme3-core/src/main/java/com/jme3/light/LightProbe.java b/jme3-core/src/main/java/com/jme3/light/LightProbe.java
index c2e011c6c1..a53c4ddbd7 100644
--- a/jme3-core/src/main/java/com/jme3/light/LightProbe.java
+++ b/jme3-core/src/main/java/com/jme3/light/LightProbe.java
@@ -120,7 +120,7 @@ public void setPrefilteredMap(TextureCubeMap prefileteredEnvMap) {
// 1 | ay by cy | py | probe position
// 2 | az bz cz | pz | )
// --|----------|
- // 3 | sx sy sz sp | -> 1/probe radius + nbMipMaps
+ // 3 | sx sy sz sp | 1/probe radius + nbMipMaps
// --scale--
*
* (ax, ay, az) is the pitch rotation axis
diff --git a/jme3-core/src/main/java/com/jme3/material/Material.java b/jme3-core/src/main/java/com/jme3/material/Material.java
index ea0ac70b91..15bd3c17df 100644
--- a/jme3-core/src/main/java/com/jme3/material/Material.java
+++ b/jme3-core/src/main/java/com/jme3/material/Material.java
@@ -537,9 +537,11 @@ public void setTextureParam(String name, VarType type, Texture value) {
MatParamTexture val = getTextureParam(name);
if (val == null) {
checkTextureParamColorSpace(name, value);
- paramValues.put(name, new MatParamTexture(type, name, value, null));
+ paramValues.put(name, new MatParamTexture(type, name, value, value.getImage() != null ? value.getImage().getColorSpace() : null));
} else {
+ checkTextureParamColorSpace(name, value);
val.setTextureValue(value);
+ val.setColorSpace(value.getImage() != null ? value.getImage().getColorSpace() : null);
}
if (technique != null) {
diff --git a/jme3-core/src/main/java/com/jme3/material/RenderState.java b/jme3-core/src/main/java/com/jme3/material/RenderState.java
index fea4d26e21..5413c3880c 100644
--- a/jme3-core/src/main/java/com/jme3/material/RenderState.java
+++ b/jme3-core/src/main/java/com/jme3/material/RenderState.java
@@ -272,27 +272,27 @@ public enum BlendMode {
/**
* Additive blending. For use with glows and particle emitters.
*
- * Result = Source Color + Destination Color -> (GL_ONE, GL_ONE)
+ * Result = Source Color + Destination Color -> (GL_ONE, GL_ONE)
*/
Additive,
/**
* Premultiplied alpha blending, for use with premult alpha textures.
*
- * Result = Source Color + (Dest Color * (1 - Source Alpha) ) -> (GL_ONE, GL_ONE_MINUS_SRC_ALPHA)
+ * Result = Source Color + (Dest Color * (1 - Source Alpha) ) -> (GL_ONE, GL_ONE_MINUS_SRC_ALPHA)
*/
PremultAlpha,
/**
* Additive blending that is multiplied with source alpha.
* For use with glows and particle emitters.
*
- * Result = (Source Alpha * Source Color) + Dest Color -> (GL_SRC_ALPHA, GL_ONE)
+ * Result = (Source Alpha * Source Color) + Dest Color -> (GL_SRC_ALPHA, GL_ONE)
*/
AlphaAdditive,
/**
* Color blending, blends in color from dest color
* using source color.
*
- * Result = Source Color + (1 - Source Color) * Dest Color -> (GL_ONE, GL_ONE_MINUS_SRC_COLOR)
+ * Result = Source Color + (1 - Source Color) * Dest Color -> (GL_ONE, GL_ONE_MINUS_SRC_COLOR)
*/
Color,
/**
@@ -300,7 +300,7 @@ public enum BlendMode {
* using source alpha.
*
* Result = Source Alpha * Source Color +
- * (1 - Source Alpha) * Dest Color -> (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
+ * (1 - Source Alpha) * Dest Color -> (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
*/
Alpha,
/**
@@ -309,28 +309,28 @@ public enum BlendMode {
* The resulting alpha is the sum between the source alpha and the destination alpha.
*
* Result.rgb = Source Alpha * Source Color +
- * (1 - Source Alpha) * Dest Color -> (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
- * Result.a = 1 * Source Alpha + 1 * Dest Alpha -> (GL_ONE, GL_ONE)
+ * (1 - Source Alpha) * Dest Color -> (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
+ * Result.a = 1 * Source Alpha + 1 * Dest Alpha -> (GL_ONE, GL_ONE)
*
*/
AlphaSumA,
/**
* Multiplies the source and dest colors.
*
- * Result = Source Color * Dest Color -> (GL_DST_COLOR, GL_ZERO)
+ * Result = Source Color * Dest Color -> (GL_DST_COLOR, GL_ZERO)
*/
Modulate,
/**
* Multiplies the source and dest colors then doubles the result.
*
- * Result = 2 * Source Color * Dest Color -> (GL_DST_COLOR, GL_SRC_COLOR)
+ * Result = 2 * Source Color * Dest Color -> (GL_DST_COLOR, GL_SRC_COLOR)
*/
ModulateX2,
/**
* Opposite effect of Modulate/Multiply. Invert both colors, multiply and
* then invert the result.
*
- * Result = 1 - (1 - Source Color) * (1 - Dest Color) -> (GL_ONE, GL_ONE_MINUS_SRC_COLOR)
+ * Result = 1 - (1 - Source Color) * (1 - Dest Color) -> (GL_ONE, GL_ONE_MINUS_SRC_COLOR)
*/
Screen,
/**
@@ -338,7 +338,7 @@ public enum BlendMode {
* operation. This is directly equivalent to Photoshop's "Exclusion" blend.
*
* Result = (Source Color * (1 - Dest Color)) + (Dest Color * (1 - Source Color))
- * -> (GL_ONE_MINUS_DST_COLOR, GL_ONE_MINUS_SRC_COLOR)
+ * -> (GL_ONE_MINUS_DST_COLOR, GL_ONE_MINUS_SRC_COLOR)
*/
Exclusion,
/**
@@ -1242,6 +1242,7 @@ public boolean isPointSprite() {
* material parameter.
* @return false
*/
+ @Deprecated
public boolean isAlphaTest() {
return false;
}
diff --git a/jme3-core/src/main/java/com/jme3/material/Technique.java b/jme3-core/src/main/java/com/jme3/material/Technique.java
index 5b02d77e73..a2fb1a0371 100644
--- a/jme3-core/src/main/java/com/jme3/material/Technique.java
+++ b/jme3-core/src/main/java/com/jme3/material/Technique.java
@@ -169,7 +169,7 @@ void render(RenderManager renderManager, Shader shader, Geometry geometry, Light
/**
* Get the {@link DefineList} for dynamic defines.
*
- * Dynamic defines are used to implement material parameter -> define
+ * Dynamic defines are used to implement material parameter -- define
* bindings as well as {@link TechniqueDefLogic} specific functionality.
*
* @return all dynamic defines.
diff --git a/jme3-core/src/main/java/com/jme3/math/FastMath.java b/jme3-core/src/main/java/com/jme3/math/FastMath.java
index 1bbf37fca0..49c993a091 100644
--- a/jme3-core/src/main/java/com/jme3/math/FastMath.java
+++ b/jme3-core/src/main/java/com/jme3/math/FastMath.java
@@ -91,7 +91,7 @@ public static boolean isPowerOfTwo(int number) {
* 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.
+ * Returns 1 for all numbers less than or equal to 1.
*
* @param number The number to obtain the POT for.
* @return The next power of two.
@@ -942,7 +942,8 @@ public static boolean approximateEquals(float a, float b) {
* Converts a single precision (32 bit) floating point value
* into half precision (16 bit).
*
- *
Source:
+ * ftp://www.fox-toolkit.org/pub/fasthalffloatconversion.pdf
*
* @param half The half floating point value as a short.
* @return floating point value of the half.
@@ -992,4 +993,16 @@ public static short convertFloatToHalf(float flt) {
| ((((f & 0x7f800000) - 0x38000000) >> 13) & 0x7c00)
| ((f >> 13) & 0x03ff));
}
+
+ /**
+ * Converts a range of min/max to a 0-1 range.
+ * @param value the value between min-max (inclusive).
+ * @param min the minimum of the range.
+ * @param max the maximum of the range.
+ * @return A value between 0-1 if the given value is between min/max.
+ */
+ public static float unInterpolateLinear(float value, float min, float max) {
+ return (value - min) / (max - min);
+ }
+
}
diff --git a/jme3-core/src/main/java/com/jme3/math/Ray.java b/jme3-core/src/main/java/com/jme3/math/Ray.java
index 8b2ab216b7..81e54d99ff 100644
--- a/jme3-core/src/main/java/com/jme3/math/Ray.java
+++ b/jme3-core/src/main/java/com/jme3/math/Ray.java
@@ -43,8 +43,9 @@
/**
* Ray defines a line segment which has an origin and a direction.
* That is, a point and an infinite ray is cast from this point. The ray is
- * defined by the following equation: R(t) = origin + t*direction for t >= 0.
- *
+ * defined by the following equation: {@literal
+ * R(t) = origin + t*direction for t >= 0.
+ * }
* @author Mark Powell
* @author Joshua Slack
*/
diff --git a/jme3-core/src/main/java/com/jme3/renderer/Caps.java b/jme3-core/src/main/java/com/jme3/renderer/Caps.java
index b930863a6f..7bda5f4ae8 100644
--- a/jme3-core/src/main/java/com/jme3/renderer/Caps.java
+++ b/jme3-core/src/main/java/com/jme3/renderer/Caps.java
@@ -238,7 +238,7 @@ public enum Caps {
TextureBuffer,
/**
- * Supports floating point & half textures (Format.RGB16F)
+ * Supports floating point and half textures (Format.RGB16F)
*/
FloatTexture,
@@ -403,7 +403,46 @@ public enum Caps {
/**
* Supporting working with ShaderStorageBufferObjects.
*/
- ShaderStorageBufferObject;
+ ShaderStorageBufferObject,
+
+ /**
+ * Supports OpenGL ES 3.0
+ */
+ OpenGLES30,
+
+ /**
+ * Supports GLSL 3.0
+ */
+ GLSL300,
+
+ /**
+ * Supports OpenGL ES 3.1
+ */
+ OpenGLES31,
+
+ /**
+ * Supports GLSL 3.1
+ */
+ GLSL310,
+
+ /**
+ * Supports OpenGL ES 3.2
+ */
+ OpenGLES32,
+
+ /**
+ * Supports GLSL 3.2
+ */
+ GLSL320,
+
+ /**
+ * Explicit support of depth 24 textures
+ */
+ Depth24,
+
+
+ UnpackRowLength
+ ;
/**
* Returns true if given the renderer capabilities, the texture
diff --git a/jme3-core/src/main/java/com/jme3/renderer/Renderer.java b/jme3-core/src/main/java/com/jme3/renderer/Renderer.java
index 095cc76de9..ee11088789 100644
--- a/jme3-core/src/main/java/com/jme3/renderer/Renderer.java
+++ b/jme3-core/src/main/java/com/jme3/renderer/Renderer.java
@@ -443,5 +443,18 @@ public interface Renderer {
* @return true if the results of the task with the given task id are available.
*/
public boolean isTaskResultAvailable(int taskId);
+
+
+ /**
+ * Gets the alpha to coverage state.
+ *
+ */
+ public boolean getAlphaToCoverage();
+
+ /**
+ * Get the default anisotropic filter level for textures.
+ *
+ */
+ public int getDefaultAnisotropicFilter();
}
diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GL.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GL.java
index b2a57736f9..9f7c5ac309 100644
--- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GL.java
+++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GL.java
@@ -194,6 +194,7 @@ public interface GL {
public static final int GL_VERSION = 0x1F02;
public static final int GL_VERTEX_SHADER = 0x8B31;
public static final int GL_ZERO = 0x0;
+ public static final int GL_UNPACK_ROW_LENGTH = 0x0CF2;
public void resetStats();
@@ -991,7 +992,7 @@ public void glCompressedTexSubImage2D(int target, int level, int xoffset, int yo
*
* Defines the scissor rectangle for all viewports. The scissor test is enabled or disabled for all viewports using {@link #glEnable Enable} or {@link #glDisable Disable}
* with the symbolic constant {@link #GL_SCISSOR_TEST SCISSOR_TEST}. When disabled, it is as if the scissor test always passes. When enabled, if
- * left <= xw < left + width and bottom <= yw < bottom + height for the scissor rectangle, then the scissor
+ * left <= xw < left + width and bottom <= yw < bottom + height for the scissor rectangle, then the scissor
* test passes. Otherwise, the test fails and the fragment is discarded.
*
* @param x the left scissor rectangle coordinate.
diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebugES.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebugES.java
index 8746d57edc..19546f20f2 100644
--- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebugES.java
+++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebugES.java
@@ -5,7 +5,7 @@
import java.nio.IntBuffer;
import java.nio.ShortBuffer;
-public class GLDebugES extends GLDebug implements GL, GLFbo, GLExt {
+public class GLDebugES extends GLDebug implements GL, GL2, GLES_30, GLFbo, GLExt {
private final GLFbo glfbo;
private final GLExt glext;
@@ -609,4 +609,54 @@ public void glFramebufferTextureLayerEXT(int param1, int param2, int param3, int
glfbo.glFramebufferTextureLayerEXT(param1, param2, param3, param4, param5);
checkError();
}
+
+ public void glAlphaFunc(int func, float ref) {
+ ((GL2)gl).glAlphaFunc(func, ref);
+ checkError();
+ }
+
+ public void glPointSize(float size) {
+ ((GL2)gl).glPointSize(size);
+ checkError();
+ }
+
+ public void glPolygonMode(int face, int mode) {
+ ((GL2)gl).glPolygonMode(face, mode);
+ checkError();
+ }
+
+ public void glDrawBuffer(int mode) {
+ ((GL2)gl).glDrawBuffer(mode);
+ checkError();
+ }
+
+ public void glReadBuffer(int mode) {
+ ((GL2)gl).glReadBuffer(mode);
+ checkError();
+ }
+
+ public void glCompressedTexImage3D(int target, int level, int internalFormat, int width, int height, int depth,
+ int border, ByteBuffer data) {
+ ((GL2)gl).glCompressedTexImage3D(target, level, internalFormat, width, height, depth, border, data);
+ checkError();
+ }
+
+ public void glCompressedTexSubImage3D(int target, int level, int xoffset, int yoffset, int zoffset, int width,
+ int height, int depth, int format, ByteBuffer data) {
+ ((GL2)gl).glCompressedTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, data);
+ checkError();
+ }
+
+ public void glTexImage3D(int target, int level, int internalFormat, int width, int height, int depth, int border,
+ int format, int type, ByteBuffer data) {
+ ((GL2)gl).glTexImage3D(target, level, internalFormat, width, height, depth, border, format, type, data);
+ checkError();
+ }
+
+ public void glTexSubImage3D(int target, int level, int xoffset, int yoffset, int zoffset, int width, int height,
+ int depth, int format, int type, ByteBuffer data) {
+ ((GL2)gl).glTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, data);
+ checkError();
+ }
+
}
diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLES_30.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLES_30.java
new file mode 100644
index 0000000000..017dae8163
--- /dev/null
+++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLES_30.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2009-2019 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.renderer.opengl;
+
+import java.nio.ByteBuffer;
+
+/**
+ * GL functions and constants only available on vanilla OpenGL ES 3.0.
+ *
+ * @author Jesus Oliver
+ */
+public interface GLES_30 extends GL {
+
+ public static final int GL_RGB10_A2 = 0x8059;
+ public static final int GL_UNSIGNED_INT_2_10_10_10_REV = 0x8368;
+
+}
diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLImageFormats.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLImageFormats.java
index 52c9a5b3d3..6daee5aff8 100644
--- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLImageFormats.java
+++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLImageFormats.java
@@ -166,7 +166,7 @@ public static GLImageFormat[][] getFormatsForCaps(EnumSet caps) {
format(formatToGL, Format.Luminance8, GLExt.GL_RGBA8, GL.GL_LUMINANCE, GL.GL_UNSIGNED_BYTE);
format(formatToGL, Format.Luminance8Alpha8, GLExt.GL_RGBA8, GL.GL_LUMINANCE_ALPHA, GL.GL_UNSIGNED_BYTE);
}
- format(formatToGL, Format.RGB8, GLExt.GL_RGBA8, GL.GL_RGB, GL.GL_UNSIGNED_BYTE);
+ format(formatToGL, Format.RGB8, GL2.GL_RGB8, GL.GL_RGB, GL.GL_UNSIGNED_BYTE);
format(formatToGL, Format.RGBA8, GLExt.GL_RGBA8, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE);
formatSwiz(formatToGL, Format.BGR8, GL2.GL_RGB8, GL2.GL_RGB, GL.GL_UNSIGNED_BYTE);
@@ -217,8 +217,28 @@ public static GLImageFormat[][] getFormatsForCaps(EnumSet caps) {
format(formatToGL, Format.RGB16F_to_RGB9E5, GLExt.GL_RGB9_E5_EXT, GL.GL_RGB, halfFloatFormat);
}
}
+
+ // Supported in GLES30 core
+ if (caps.contains(Caps.OpenGLES30)) {
+ format(formatToGL, Format.RGB10A2, GLES_30.GL_RGB10_A2, GL.GL_RGBA, GLES_30.GL_UNSIGNED_INT_2_10_10_10_REV);
+ format(formatToGL, Format.Alpha8, GL2.GL_ALPHA8, GL.GL_ALPHA, GL.GL_UNSIGNED_BYTE);
+ format(formatToGL, Format.Luminance8, GL.GL_LUMINANCE, GL.GL_LUMINANCE, GL.GL_UNSIGNED_BYTE);
+ format(formatToGL, Format.Luminance8Alpha8, GL.GL_LUMINANCE_ALPHA, GL.GL_LUMINANCE_ALPHA, GL.GL_UNSIGNED_BYTE);
+
+ formatSrgb(formatToGL, Format.RGB8, GLExt.GL_SRGB8_EXT, GL.GL_RGB, GL.GL_UNSIGNED_BYTE);
+ formatSrgb(formatToGL, Format.RGBA8, GLExt.GL_SRGB8_ALPHA8_EXT, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE);
+
+ //Depending on the device could be better to use the previously defined extension based float textures instead of gles3.0 texture formats
+// if (!caps.contains(Caps.FloatTexture)) {
+ format(formatToGL, Format.RGB16F, GLExt.GL_RGB16F_ARB, GL.GL_RGB, GLExt.GL_HALF_FLOAT_ARB);
+ format(formatToGL, Format.RGB32F, GLExt.GL_RGB32F_ARB, GL.GL_RGB, GL.GL_FLOAT);
+ format(formatToGL, Format.RGBA16F, GLExt.GL_RGBA16F_ARB, GL.GL_RGBA, GLExt.GL_HALF_FLOAT_ARB);
+ format(formatToGL, Format.RGBA32F, GLExt.GL_RGBA32F_ARB, GL.GL_RGBA, GL.GL_FLOAT);
+// }
+ format(formatToGL, Format.RGB111110F, GLExt.GL_R11F_G11F_B10F_EXT, GL.GL_RGB, GLExt.GL_UNSIGNED_INT_10F_11F_11F_REV_EXT);
+ }
- // Need to check if Caps.DepthTexture is supported prior to using for textures
+ // Need to check if Caps.DepthTexture is supported prior to using for textures
// But for renderbuffers its OK.
format(formatToGL, Format.Depth16, GL.GL_DEPTH_COMPONENT16, GL.GL_DEPTH_COMPONENT, GL.GL_UNSIGNED_SHORT);
@@ -228,7 +248,7 @@ public static GLImageFormat[][] getFormatsForCaps(EnumSet caps) {
} else {
format(formatToGL, Format.Depth, GL.GL_DEPTH_COMPONENT, GL.GL_DEPTH_COMPONENT, GL.GL_UNSIGNED_BYTE);
}
- if (caps.contains(Caps.OpenGL20)) {
+ if (caps.contains(Caps.OpenGL20) || caps.contains(Caps.Depth24)) {
format(formatToGL, Format.Depth24, GL2.GL_DEPTH_COMPONENT24, GL.GL_DEPTH_COMPONENT, GL.GL_UNSIGNED_INT);
}
if (caps.contains(Caps.FloatDepthBuffer)) {
diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java
index 6f222eb02d..d20c78b309 100644
--- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java
+++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java
@@ -52,6 +52,7 @@
import com.jme3.texture.FrameBuffer.RenderBuffer;
import com.jme3.texture.Image;
import com.jme3.texture.Texture;
+import com.jme3.texture.Texture2D;
import com.jme3.texture.Texture.ShadowCompareMode;
import com.jme3.texture.Texture.WrapAxis;
import com.jme3.texture.image.LastTextureState;
@@ -71,6 +72,7 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+
public final class GLRenderer implements Renderer {
private static final Logger logger = Logger.getLogger(GLRenderer.class.getName());
@@ -166,9 +168,28 @@ private boolean hasExtension(String extensionName) {
}
private void loadCapabilitiesES() {
+ int oglVer = extractVersion(gl.glGetString(GL.GL_VERSION));
caps.add(Caps.GLSL100);
caps.add(Caps.OpenGLES20);
+ caps.add(Caps.Multisample);
+
+ if (oglVer >= 300) {
+ caps.add(Caps.OpenGLES30);
+ caps.add(Caps.GLSL300);
+ // Instancing is core in GLES300
+ caps.add(Caps.MeshInstancing);
+ }
+ if (oglVer >= 310) {
+ caps.add(Caps.OpenGLES31);
+ caps.add(Caps.GLSL310);
+ }
+ if (oglVer >= 320) {
+ caps.add(Caps.OpenGLES32);
+ caps.add(Caps.GLSL320);
+ caps.add(Caps.GeometryShader);
+ caps.add(Caps.TesselationShader);
+ }
// Important: Do not add OpenGL20 - that's the desktop capability!
}
@@ -293,6 +314,7 @@ private void loadCapabilitiesCommon() {
if (hasExtension("GL_ARB_draw_instanced") &&
hasExtension("GL_ARB_instanced_arrays")) {
+ // TODO: If there were a way to call the EXT extension for GLES2, should check also (hasExtension("GL_EXT_draw_instanced") && hasExtension("GL_EXT_instanced_arrays"))
caps.add(Caps.MeshInstancing);
}
@@ -330,8 +352,10 @@ private void loadCapabilitiesCommon() {
if (hasExtension("GL_OES_depth_texture") || gl2 != null) {
caps.add(Caps.DepthTexture);
+ }
- // TODO: GL_OES_depth24
+ if (hasExtension("GL_OES_depth24")) {
+ caps.add(Caps.Depth24);
}
if (hasExtension("GL_OES_rgb8_rgba8") ||
@@ -340,7 +364,7 @@ private void loadCapabilitiesCommon() {
caps.add(Caps.Rgba8);
}
- if (caps.contains(Caps.OpenGL30) || hasExtension("GL_OES_packed_depth_stencil")) {
+ if (caps.contains(Caps.OpenGL30) || caps.contains(Caps.OpenGLES30) || hasExtension("GL_OES_packed_depth_stencil")) {
caps.add(Caps.PackedDepthStencilBuffer);
}
@@ -350,7 +374,7 @@ private void loadCapabilitiesCommon() {
caps.add(Caps.FloatColorBuffer);
}
- if (hasExtension("GL_ARB_depth_buffer_float")) {
+ if (caps.contains(Caps.OpenGLES30) || hasExtension("GL_ARB_depth_buffer_float")) {
caps.add(Caps.FloatDepthBuffer);
}
@@ -397,7 +421,7 @@ private void loadCapabilitiesCommon() {
caps.add(Caps.PartialNonPowerOfTwoTextures);
}
- if (hasExtension("GL_EXT_texture_array") || caps.contains(Caps.OpenGL30)) {
+ if (hasExtension("GL_EXT_texture_array") || caps.contains(Caps.OpenGL30) || caps.contains(Caps.OpenGLES30)) {
caps.add(Caps.TextureArray);
}
@@ -414,16 +438,16 @@ private void loadCapabilitiesCommon() {
limits.put(Limits.RenderBufferSize, getInteger(GLFbo.GL_MAX_RENDERBUFFER_SIZE_EXT));
limits.put(Limits.FrameBufferAttachments, getInteger(GLFbo.GL_MAX_COLOR_ATTACHMENTS_EXT));
- if (hasExtension("GL_EXT_framebuffer_blit") || caps.contains(Caps.OpenGL30)) {
+ if (hasExtension("GL_EXT_framebuffer_blit") || caps.contains(Caps.OpenGL30) || caps.contains(Caps.OpenGLES30)) {
caps.add(Caps.FrameBufferBlit);
}
- if (hasExtension("GL_EXT_framebuffer_multisample")) {
+ if (hasExtension("GL_EXT_framebuffer_multisample") || caps.contains(Caps.OpenGLES30)) {
caps.add(Caps.FrameBufferMultisample);
limits.put(Limits.FrameBufferSamples, getInteger(GLExt.GL_MAX_SAMPLES_EXT));
}
- if (hasExtension("GL_ARB_texture_multisample")) {
+ if (hasExtension("GL_ARB_texture_multisample") || caps.contains(Caps.OpenGLES31)) { // GLES31 does not fully support it
caps.add(Caps.TextureMultisample);
limits.put(Limits.ColorTextureSamples, getInteger(GLExt.GL_MAX_COLOR_TEXTURE_SAMPLES));
limits.put(Limits.DepthTextureSamples, getInteger(GLExt.GL_MAX_DEPTH_TEXTURE_SAMPLES));
@@ -432,8 +456,8 @@ private void loadCapabilitiesCommon() {
limits.put(Limits.FrameBufferSamples, limits.get(Limits.ColorTextureSamples));
}
}
-
- if (hasExtension("GL_ARB_draw_buffers") || caps.contains(Caps.OpenGL30)) {
+
+ if (hasExtension("GL_ARB_draw_buffers") || caps.contains(Caps.OpenGL30) || caps.contains(Caps.OpenGLES30)) {
limits.put(Limits.FrameBufferMrtAttachments, getInteger(GLExt.GL_MAX_DRAW_BUFFERS_ARB));
if (limits.get(Limits.FrameBufferMrtAttachments) > 1) {
caps.add(Caps.FrameBufferMRT);
@@ -443,7 +467,7 @@ private void loadCapabilitiesCommon() {
}
}
- if (hasExtension("GL_ARB_multisample")) {
+ if (hasExtension("GL_ARB_multisample") /*|| caps.contains(Caps.OpenGLES20)*/) {
boolean available = getInteger(GLExt.GL_SAMPLE_BUFFERS_ARB) != 0;
int samples = getInteger(GLExt.GL_SAMPLES_ARB);
logger.log(Level.FINER, "Samples: {0}", samples);
@@ -498,6 +522,18 @@ private void loadCapabilitiesCommon() {
limits.put(Limits.UniformBufferObjectMaxVertexBlocks, getInteger(GL3.GL_MAX_VERTEX_UNIFORM_BLOCKS));
}
+ if (hasExtension("GL_OES_geometry_shader") || hasExtension("GL_EXT_geometry_shader")) {
+ caps.add(Caps.GeometryShader);
+ }
+
+ if (hasExtension("GL_OES_tessellation_shader") || hasExtension("GL_EXT_tessellation_shader")) {
+ caps.add(Caps.TesselationShader);
+ }
+
+ if(caps.contains(Caps.OpenGL20)){
+ caps.add(Caps.UnpackRowLength);
+ }
+
// Print context information
logger.log(Level.INFO, "OpenGL Renderer Information\n" +
" * Vendor: {0}\n" +
@@ -539,7 +575,7 @@ private void loadCapabilitiesCommon() {
}
private void loadCapabilities() {
- if (gl2 != null) {
+ if (gl2 != null && !(gl instanceof GLES_30)) {
loadCapabilitiesGL2();
} else {
loadCapabilitiesES();
@@ -1327,10 +1363,11 @@ public void updateShaderSourceData(ShaderSource source) {
throw new RendererException("Cannot recompile shader source");
}
+ boolean gles3 = caps.contains(Caps.OpenGLES30);
boolean gles2 = caps.contains(Caps.OpenGLES20);
String language = source.getLanguage();
- if (gles2 && !language.equals("GLSL100")) {
+ if (!gles3 && gles2 && !language.equals("GLSL100")) { //avoid this check for gles3
throw new RendererException("This shader cannot run in OpenGL ES 2. "
+ "Only GLSL 1.00 shaders are supported.");
}
@@ -1339,24 +1376,25 @@ public void updateShaderSourceData(ShaderSource source) {
// Upload shader source.
// Merge the defines and source code.
stringBuf.setLength(0);
+ int version = Integer.parseInt(language.substring(4));
if (language.startsWith("GLSL")) {
- int version = Integer.parseInt(language.substring(4));
if (version > 100) {
stringBuf.append("#version ");
stringBuf.append(language.substring(4));
if (version >= 150) {
- stringBuf.append(" core");
+ if(gles3) {
+ stringBuf.append(" es");
+ }
+ else {
+ stringBuf.append(" core");
+ }
}
stringBuf.append("\n");
} else {
- if (gles2) {
+ if (gles2 || gles3) {
// request GLSL ES (1.00) when compiling under GLES2.
stringBuf.append("#version 100\n");
- if (source.getType() == ShaderType.Fragment) {
- // GLES2 requires precision qualifier.
- insertPrecision = true;
- }
} else {
// version 100 does not exist in desktop GLSL.
// put version 110 in that case to enable strict checking
@@ -1364,6 +1402,15 @@ public void updateShaderSourceData(ShaderSource source) {
stringBuf.append("#version 110\n");
}
}
+
+ if (gles2 || gles3) {
+ //Inserting precision only to fragment shaders creates some link failures because of different precision between shaders
+ //But adding the precision to all shaders generates rendering glitches in some devices if not set to highp
+ if (source.getType() == ShaderType.Fragment) {
+ // GLES requires precision qualifier.
+ insertPrecision = true;
+ }
+ }
}
if (linearizeSrgbImages) {
@@ -1375,11 +1422,22 @@ public void updateShaderSourceData(ShaderSource source) {
stringBuf.append(source.getSource());
if(insertPrecision){
+ // default precision could be defined in GLSLCompat.glsllib so final users can use custom defined precision instead
// precision token is not a preprocessor dirrective therefore it must be placed after #extension tokens to avoid
// Error P0001: Extension directive must occur before any non-preprocessor tokens
int idx = stringBuf.lastIndexOf("#extension");
idx = stringBuf.indexOf("\n", idx);
- stringBuf.insert(idx + 1, "precision mediump float;\n");
+
+ if(version>=310) {
+ stringBuf.insert(idx + 1, "precision highp sampler2DMS;\n");
+ }
+ if(version>=300) {
+ stringBuf.insert(idx + 1, "precision highp sampler2DArray;\n");
+ stringBuf.insert(idx + 1, "precision highp sampler2DShadow;\n");
+ stringBuf.insert(idx + 1, "precision highp sampler3D;\n");
+ stringBuf.insert(idx + 1, "precision highp sampler2D;\n");
+ }
+ stringBuf.insert(idx + 1, "precision highp float;\n");
}
intBuf1.clear();
@@ -1612,6 +1670,7 @@ public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst, boolean copyDepth)
if (copyDepth) {
mask |= GL.GL_DEPTH_BUFFER_BIT;
}
+
glfbo.glBlitFramebufferEXT(srcX0, srcY0, srcX1, srcY1,
dstX0, dstY0, dstX1, dstY1, mask,
GL.GL_NEAREST);
@@ -1842,7 +1901,7 @@ public void setMainFrameBufferOverride(FrameBuffer fb) {
}
public void setReadDrawBuffers(FrameBuffer fb) {
- if (gl2 == null) {
+ if (gl2 == null || gl instanceof GLES_30) {
return;
}
@@ -1982,6 +2041,7 @@ private void readFrameBufferWithGLFormat(FrameBuffer fb, ByteBuffer byteBuf, int
context.boundReadBuf = rb.getSlot();
}
}
+
} else {
setFrameBuffer(null);
}
@@ -2048,7 +2108,7 @@ private int convertTextureType(Texture.Type type, int samples, int face) {
return GLExt.GL_TEXTURE_2D_ARRAY_EXT;
}
case ThreeDimensional:
- if (!caps.contains(Caps.OpenGL20)) {
+ if (!caps.contains(Caps.OpenGL20) && !caps.contains(Caps.OpenGLES30)) {
throw new RendererException("3D textures are not supported" +
" by the video hardware.");
}
@@ -2172,9 +2232,9 @@ private void setupTextureParams(int unit, Texture tex) {
switch (tex.getType()) {
case ThreeDimensional:
case CubeMap: // cubemaps use 3D coords
- if (gl2 != null && curState.rWrap != tex.getWrap(WrapAxis.R)) {
+ if (gl2 != null && (caps.contains(Caps.OpenGL20) || caps.contains(Caps.OpenGLES30)) && curState.rWrap != tex.getWrap(WrapAxis.R)) {
bindTextureAndUnit(target, image, unit);
- gl2.glTexParameteri(target, GL2.GL_TEXTURE_WRAP_R, convertWrapMode(tex.getWrap(WrapAxis.R)));
+ gl.glTexParameteri(target, GL2.GL_TEXTURE_WRAP_R, convertWrapMode(tex.getWrap(WrapAxis.R)));
curState.rWrap = tex.getWrap(WrapAxis.R);
}
//There is no break statement on purpose here
@@ -2196,17 +2256,17 @@ private void setupTextureParams(int unit, Texture tex) {
}
ShadowCompareMode texCompareMode = tex.getShadowCompareMode();
- if (gl2 != null && curState.shadowCompareMode != texCompareMode) {
+ if ( (gl2 != null || caps.contains(Caps.OpenGLES30)) && curState.shadowCompareMode != texCompareMode) {
bindTextureAndUnit(target, image, unit);
if (texCompareMode != ShadowCompareMode.Off) {
- gl2.glTexParameteri(target, GL2.GL_TEXTURE_COMPARE_MODE, GL2.GL_COMPARE_REF_TO_TEXTURE);
+ gl.glTexParameteri(target, GL2.GL_TEXTURE_COMPARE_MODE, GL2.GL_COMPARE_REF_TO_TEXTURE);
if (texCompareMode == ShadowCompareMode.GreaterOrEqual) {
- gl2.glTexParameteri(target, GL2.GL_TEXTURE_COMPARE_FUNC, GL.GL_GEQUAL);
+ gl.glTexParameteri(target, GL2.GL_TEXTURE_COMPARE_FUNC, GL.GL_GEQUAL);
} else {
- gl2.glTexParameteri(target, GL2.GL_TEXTURE_COMPARE_FUNC, GL.GL_LEQUAL);
+ gl.glTexParameteri(target, GL2.GL_TEXTURE_COMPARE_FUNC, GL.GL_LEQUAL);
}
} else {
- gl2.glTexParameteri(target, GL2.GL_TEXTURE_COMPARE_MODE, GL.GL_NONE);
+ gl.glTexParameteri(target, GL2.GL_TEXTURE_COMPARE_MODE, GL.GL_NONE);
}
curState.shadowCompareMode = texCompareMode;
}
@@ -2340,7 +2400,6 @@ public void updateTexImageData(Image img, Texture.Type type, int unit, boolean s
bindTextureAndUnit(target, img, unit);
int imageSamples = img.getMultiSamples();
-
if (imageSamples <= 1) {
if (!img.hasMipmaps() && img.isGeneratedMipmapsRequired()) {
// Image does not have mipmaps, but they are required.
@@ -2353,7 +2412,7 @@ public void updateTexImageData(Image img, Texture.Type type, int unit, boolean s
// For OpenGL3 and up.
// We'll generate mipmaps via glGenerateMipmapEXT (see below)
}
- } else if (caps.contains(Caps.OpenGL20)) {
+ } else if (caps.contains(Caps.OpenGL20) || caps.contains(Caps.OpenGLES30)) {
if (img.hasMipmaps()) {
// Image already has mipmaps, set the max level based on the
// number of mipmaps we have.
@@ -2483,12 +2542,34 @@ public void setTexture(int unit, Texture tex) {
setupTextureParams(unit, tex);
}
+
+ /**
+ * @deprecated Use modifyTexture(Texture2D dest, Image src, int destX, int destY, int srcX, int srcY, int areaW, int areaH)
+ */
+ @Deprecated
public void modifyTexture(Texture tex, Image pixels, int x, int y) {
setTexture(0, tex);
int target = convertTextureType(tex.getType(), pixels.getMultiSamples(), -1);
- texUtil.uploadSubTexture(pixels, target, 0, x, y, linearizeSrgbImages);
+ texUtil.uploadSubTexture(target,pixels, 0, x, y,0,0,pixels.getWidth(),pixels.getHeight(), linearizeSrgbImages);
+ }
+
+ /**
+ * Copy a part of an image to a texture 2d.
+ * @param dest The destination image, where the source will be copied
+ * @param src The source image that contains the data to copy
+ * @param destX First pixel of the destination image from where the src image will be drawn (x component)
+ * @param destY First pixel of the destination image from where the src image will be drawn (y component)
+ * @param srcX First pixel to copy (x component)
+ * @param srcY First pixel to copy (y component)
+ * @param areaW Width of the area to copy
+ * @param areaH Height of the area to copy
+ */
+ public void modifyTexture(Texture2D dest, Image src, int destX, int destY, int srcX, int srcY, int areaW, int areaH) {
+ setTexture(0, dest);
+ int target = convertTextureType(dest.getType(), src.getMultiSamples(), -1);
+ texUtil.uploadSubTexture(target, src, 0, destX, destY, srcX, srcY, areaW, areaH, linearizeSrgbImages);
}
-
+
public void deleteImage(Image image) {
int texId = image.getId();
if (texId != -1) {
@@ -3136,4 +3217,18 @@ public long getProfilingTime(int taskId) {
public boolean isTaskResultAvailable(int taskId) {
return gl.glGetQueryObjectiv(taskId, GL.GL_QUERY_RESULT_AVAILABLE) == 1;
}
+
+ @Override
+ public boolean getAlphaToCoverage() {
+ if (caps.contains(Caps.Multisample)) {
+ return gl.glIsEnabled(GLExt.GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);
+
+ }
+ return false;
+ }
+
+ @Override
+ public int getDefaultAnisotropicFilter() {
+ return this.defaultAnisotropicFilter;
+ }
}
diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/TextureUtil.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/TextureUtil.java
index db5331e110..7086eb0455 100644
--- a/jme3-core/src/main/java/com/jme3/renderer/opengl/TextureUtil.java
+++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/TextureUtil.java
@@ -54,6 +54,7 @@ final class TextureUtil {
private final GL2 gl2;
private final GLExt glext;
private GLImageFormat[][] formats;
+ private boolean supportUnpackRowLength;
public TextureUtil(GL gl, GL2 gl2, GLExt glext) {
this.gl = gl;
@@ -62,6 +63,7 @@ public TextureUtil(GL gl, GL2 gl2, GLExt glext) {
}
public void initialize(EnumSet caps) {
+ supportUnpackRowLength = caps.contains(Caps.UnpackRowLength);
this.formats = GLImageFormats.getFormatsForCaps(caps);
if (logger.isLoggable(Level.FINE)) {
StringBuilder sb = new StringBuilder();
@@ -142,13 +144,13 @@ private void uploadTextureLevel(GLImageFormat format, int target, int level, int
if (target == GL2.GL_TEXTURE_3D) {
// For 3D textures, we upload the entire mipmap level.
gl2.glCompressedTexImage3D(target,
- level,
- format.internalFormat,
- width,
- height,
- depth,
- 0,
- data);
+ level,
+ format.internalFormat,
+ width,
+ height,
+ depth,
+ 0,
+ data);
} else if (target == GLExt.GL_TEXTURE_2D_ARRAY_EXT) {
// For texture arrays, only upload 1 slice at a time.
// zoffset specifies slice index, and depth is 1 to indicate
@@ -298,6 +300,10 @@ public void uploadTexture(Image image,
}
}
+ /**
+ * @deprecated Use uploadSubTexture(int target, Image src, int index,int targetX, int targetY,int srcX,int srcY, int areaWidth,int areaHeight, boolean linearizeSrgb)
+ */
+ @Deprecated
public void uploadSubTexture(Image image, int target, int index, int x, int y, boolean linearizeSrgb) {
if (target != GL.GL_TEXTURE_2D || image.getDepth() > 1) {
throw new UnsupportedOperationException("Updating non-2D texture is not supported");
@@ -338,4 +344,63 @@ public void uploadSubTexture(Image image, int target, int index, int x, int y, b
gl.glTexSubImage2D(target, 0, x, y, image.getWidth(), image.getHeight(),
oglFormat.format, oglFormat.dataType, data);
}
+
+ public void uploadSubTexture(int target, Image src, int index, int targetX, int targetY, int areaX, int areaY, int areaWidth, int areaHeight, boolean linearizeSrgb) {
+ if (target != GL.GL_TEXTURE_2D || src.getDepth() > 1) {
+ throw new UnsupportedOperationException("Updating non-2D texture is not supported");
+ }
+
+ if (src.getMipMapSizes() != null) {
+ throw new UnsupportedOperationException("Updating mip-mappped images is not supported");
+ }
+
+ if (src.getMultiSamples() > 1) {
+ throw new UnsupportedOperationException("Updating multisampled images is not supported");
+ }
+
+ Image.Format jmeFormat = src.getFormat();
+
+ if (jmeFormat.isCompressed()) {
+ throw new UnsupportedOperationException("Updating compressed images is not supported");
+ } else if (jmeFormat.isDepthFormat()) {
+ throw new UnsupportedOperationException("Updating depth images is not supported");
+ }
+
+ boolean getSrgbFormat = src.getColorSpace() == ColorSpace.sRGB && linearizeSrgb;
+ GLImageFormat oglFormat = getImageFormatWithError(jmeFormat, getSrgbFormat);
+
+ ByteBuffer data = src.getData(index);
+
+ if (data == null) {
+ throw new IndexOutOfBoundsException("The image index " + index + " is not valid for the given image");
+ }
+
+ int Bpp = src.getFormat().getBitsPerPixel() / 8;
+
+ int srcWidth = src.getWidth();
+ int cpos = data.position();
+ int skip = areaX;
+ skip += areaY * srcWidth;
+ skip *= Bpp;
+
+ data.position(skip);
+
+ boolean needsStride = srcWidth != areaWidth;
+
+ if (needsStride && (!supportUnpackRowLength)) { // doesn't support stride, copy row by row (slower).
+ for (int i = 0; i < areaHeight; i++) {
+ data.position(skip + (srcWidth * Bpp * i));
+ gl.glTexSubImage2D(target, 0, targetX, targetY + i, areaWidth, 1, oglFormat.format, oglFormat.dataType, data);
+ }
+ } else {
+ if (needsStride)
+ gl2.glPixelStorei(GL.GL_UNPACK_ROW_LENGTH, srcWidth);
+ gl.glTexSubImage2D(target, 0, targetX, targetY, areaWidth, areaHeight, oglFormat.format, oglFormat.dataType, data);
+ if (needsStride)
+ gl2.glPixelStorei(GL.GL_UNPACK_ROW_LENGTH, 0);
+ }
+ data.position(cpos);
+
+ }
+
}
diff --git a/jme3-core/src/main/java/com/jme3/scene/Geometry.java b/jme3-core/src/main/java/com/jme3/scene/Geometry.java
index 005d0e8c75..adc1d51a55 100644
--- a/jme3-core/src/main/java/com/jme3/scene/Geometry.java
+++ b/jme3-core/src/main/java/com/jme3/scene/Geometry.java
@@ -601,6 +601,22 @@ public void setMorphState(float[] state) {
this.dirtyMorph = true;
}
+ /**
+ * Set the state of the morph with the given name.
+ *
+ * If the name of the morph is not found, no state will be set.
+ *
+ * @param morphTarget The name of the morph to set the state of
+ * @param state The state to set the morph to
+ */
+ public void setMorphState(String morphTarget, float state) {
+ int index = mesh.getMorphIndex(morphTarget);
+ if (index >= 0) {
+ morphState[index] = state;
+ this.dirtyMorph = true;
+ }
+ }
+
/**
* returns true if the morph state has changed on the last frame.
* @return true if changed, otherwise false
@@ -629,6 +645,20 @@ public float[] getMorphState() {
}
return morphState;
}
+
+ /**
+ * Get the state of a morph
+ * @param morphTarget the name of the morph to get the state of
+ * @return the state of the morph, or -1 if the morph is not found
+ */
+ public float getMorphState(String morphTarget) {
+ int index = mesh.getMorphIndex(morphTarget);
+ if (index < 0) {
+ return -1;
+ } else {
+ return morphState[index];
+ }
+ }
/**
* Return the number of morph targets that can be handled on the GPU simultaneously for this geometry.
diff --git a/jme3-core/src/main/java/com/jme3/scene/Mesh.java b/jme3-core/src/main/java/com/jme3/scene/Mesh.java
index caffca063d..1e3195e003 100644
--- a/jme3-core/src/main/java/com/jme3/scene/Mesh.java
+++ b/jme3-core/src/main/java/com/jme3/scene/Mesh.java
@@ -1529,10 +1529,46 @@ public void addMorphTarget(MorphTarget target) {
public MorphTarget[] getMorphTargets() {
return morphTargets.getArray();
}
+
+ /**
+ * Get the name of all morphs in order.
+ * Morphs without names will be null
+ * @return an array
+ */
+ public String[] getMorphTargetNames() {
+
+ MorphTarget[] nbMorphTargets = getMorphTargets();
+ if (nbMorphTargets.length == 0) {
+ return new String[0];
+ }
+ String[] targets = new String[nbMorphTargets.length];
+
+ for (int index = 0; index < nbMorphTargets.length; index++) {
+ targets[index] = nbMorphTargets[index].getName();
+ }
+ return targets;
+ }
public boolean hasMorphTargets() {
return morphTargets != null && !morphTargets.isEmpty();
}
+
+ /**
+ * Get the index of the morph that has the given name.
+ * @param morphName The name of the morph to search for
+ * @return The index of the morph, or -1 if not found.
+ */
+ public int getMorphIndex(String morphName) {
+ int index = -1;
+ MorphTarget[] nbMorphTargets = getMorphTargets();
+ for (int i = 0; i < nbMorphTargets.length; i++) {
+ if (nbMorphTargets[i].getName().equals(morphName)) {
+ index = i;
+ break;
+ }
+ }
+ return index;
+ }
@Override
public void write(JmeExporter ex) throws IOException {
diff --git a/jme3-core/src/main/java/com/jme3/scene/SceneGraphVisitorAdapter.java b/jme3-core/src/main/java/com/jme3/scene/SceneGraphVisitorAdapter.java
index 8fa419e750..7cde0d266b 100644
--- a/jme3-core/src/main/java/com/jme3/scene/SceneGraphVisitorAdapter.java
+++ b/jme3-core/src/main/java/com/jme3/scene/SceneGraphVisitorAdapter.java
@@ -51,9 +51,9 @@ public void visit(Geometry geom) {}
/**
* Called when a {@link Node} is visited.
*
- * @param geom The visited node
+ * @param node The visited node
*/
- public void visit(Node geom) {}
+ public void visit(Node node) {}
@Override
public final void visit(Spatial spatial) {
diff --git a/jme3-core/src/main/java/com/jme3/scene/mesh/IndexBuffer.java b/jme3-core/src/main/java/com/jme3/scene/mesh/IndexBuffer.java
index 3fc4b318e7..dd94761f77 100644
--- a/jme3-core/src/main/java/com/jme3/scene/mesh/IndexBuffer.java
+++ b/jme3-core/src/main/java/com/jme3/scene/mesh/IndexBuffer.java
@@ -31,12 +31,14 @@
*/
package com.jme3.scene.mesh;
-import com.jme3.util.BufferUtils;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;
+import com.jme3.scene.VertexBuffer.Format;
+import com.jme3.util.BufferUtils;
+
/**
* IndexBuffer is an abstraction for integer index buffers,
* it is used to retrieve indices without knowing in which format they
@@ -59,21 +61,22 @@ public static IndexBuffer wrapIndexBuffer(Buffer buf) {
}
/**
- * Creates an index buffer that can contain the given amount
- * of vertices.
- * Returns {@link IndexShortBuffer}
+ * Creates an index buffer that can contain the given amount of vertices.
+ *
+ * Returns either {@link IndexByteBuffer}, {@link IndexShortBuffer} or
+ * {@link IndexIntBuffer}
*
* @param vertexCount The amount of vertices to contain
- * @param indexCount The amount of indices
- * to contain.
- * @return A new index buffer
+ * @param indexCount The amount of indices to contain
+ * @return A new, apropriately sized index buffer
*/
public static IndexBuffer createIndexBuffer(int vertexCount, int indexCount){
- if (vertexCount > 65535){
- return new IndexIntBuffer(BufferUtils.createIntBuffer(indexCount));
- }else{
+ if (vertexCount < 128)
+ return new IndexByteBuffer(BufferUtils.createByteBuffer (indexCount));
+ else if (vertexCount < 65536)
return new IndexShortBuffer(BufferUtils.createShortBuffer(indexCount));
- }
+ else
+ return new IndexIntBuffer(BufferUtils.createIntBuffer(indexCount));
}
/**
@@ -107,12 +110,31 @@ public int remaining() {
public abstract int get(int i);
/**
- * Puts the vertex index at the index buffer's index.
+ * Absolute put method.
+ *
+ *
Puts the vertex index at the index buffer's index.
* Implementations may throw an {@link UnsupportedOperationException}
* if modifying the IndexBuffer is not supported (e.g. virtual index
- * buffers).
+ * buffers).
+ *
+ * @param i The buffer index
+ * @param value The vertex index
+ * @return This buffer
*/
- public abstract void put(int i, int value);
+ public abstract IndexBuffer put(int i, int value);
+
+ /**
+ * Relative put method.
+ *
+ *
Puts the vertex index at the current position, then increments the
+ * position. Implementations may throw an
+ * {@link UnsupportedOperationException} if modifying the IndexBuffer is not
+ * supported (e.g. virtual index buffers).
+ *
+ * @param value The vertex index
+ * @return This buffer
+ */
+ public abstract IndexBuffer put(int value);
/**
* Returns the size of the index buffer.
@@ -129,4 +151,17 @@ public int remaining() {
* @return the underlying {@link Buffer}.
*/
public abstract Buffer getBuffer();
+
+ /**
+ * Returns the format of the data stored in this buffer.
+ *
+ *
This method can be used to set an {@link IndexBuffer} to a
+ * {@link com.jme3.scene.Mesh Mesh}:
+ * @return
+ */
+ public abstract Format getFormat();
}
diff --git a/jme3-core/src/main/java/com/jme3/scene/mesh/IndexByteBuffer.java b/jme3-core/src/main/java/com/jme3/scene/mesh/IndexByteBuffer.java
index ab7461c2a9..d27901673f 100644
--- a/jme3-core/src/main/java/com/jme3/scene/mesh/IndexByteBuffer.java
+++ b/jme3-core/src/main/java/com/jme3/scene/mesh/IndexByteBuffer.java
@@ -34,6 +34,8 @@
import java.nio.Buffer;
import java.nio.ByteBuffer;
+import com.jme3.scene.VertexBuffer.Format;
+
/**
* IndexBuffer implementation for {@link ByteBuffer}s.
*
@@ -59,8 +61,15 @@ public int get(int i) {
}
@Override
- public void put(int i, int value) {
+ public IndexByteBuffer put(int i, int value) {
buf.put(i, (byte) value);
+ return this;
+ }
+
+ @Override
+ public IndexByteBuffer put(int value) {
+ buf.put((byte) value);
+ return this;
}
@Override
@@ -72,5 +81,10 @@ public int size() {
public Buffer getBuffer() {
return buf;
}
+
+ @Override
+ public Format getFormat () {
+ return Format.UnsignedByte;
+ }
}
diff --git a/jme3-core/src/main/java/com/jme3/scene/mesh/IndexIntBuffer.java b/jme3-core/src/main/java/com/jme3/scene/mesh/IndexIntBuffer.java
index ca109ba660..d5f2b86a91 100644
--- a/jme3-core/src/main/java/com/jme3/scene/mesh/IndexIntBuffer.java
+++ b/jme3-core/src/main/java/com/jme3/scene/mesh/IndexIntBuffer.java
@@ -34,6 +34,8 @@
import java.nio.Buffer;
import java.nio.IntBuffer;
+import com.jme3.scene.VertexBuffer.Format;
+
/**
* IndexBuffer implementation for {@link IntBuffer}s.
*
@@ -58,8 +60,15 @@ public int get(int i) {
}
@Override
- public void put(int i, int value) {
+ public IndexIntBuffer put(int i, int value) {
buf.put(i, value);
+ return this;
+ }
+
+ @Override
+ public IndexIntBuffer put(int value) {
+ buf.put(value);
+ return this;
}
@Override
@@ -71,4 +80,9 @@ public int size() {
public Buffer getBuffer() {
return buf;
}
+
+ @Override
+ public Format getFormat () {
+ return Format.UnsignedInt;
+ }
}
diff --git a/jme3-core/src/main/java/com/jme3/scene/mesh/IndexShortBuffer.java b/jme3-core/src/main/java/com/jme3/scene/mesh/IndexShortBuffer.java
index e87b5533fb..3dfd560dea 100644
--- a/jme3-core/src/main/java/com/jme3/scene/mesh/IndexShortBuffer.java
+++ b/jme3-core/src/main/java/com/jme3/scene/mesh/IndexShortBuffer.java
@@ -34,6 +34,8 @@
import java.nio.Buffer;
import java.nio.ShortBuffer;
+import com.jme3.scene.VertexBuffer.Format;
+
/**
* IndexBuffer implementation for {@link ShortBuffer}s.
*
@@ -58,8 +60,15 @@ public int get(int i) {
}
@Override
- public void put(int i, int value) {
+ public IndexShortBuffer put(int i, int value) {
buf.put(i, (short) value);
+ return this;
+ }
+
+ @Override
+ public IndexShortBuffer put(int value) {
+ buf.put((short) value);
+ return this;
}
@Override
@@ -71,4 +80,9 @@ public int size() {
public Buffer getBuffer() {
return buf;
}
+
+ @Override
+ public Format getFormat () {
+ return Format.UnsignedShort;
+ }
}
diff --git a/jme3-core/src/main/java/com/jme3/scene/mesh/MorphTarget.java b/jme3-core/src/main/java/com/jme3/scene/mesh/MorphTarget.java
index 083d04fb7f..fc80e21139 100644
--- a/jme3-core/src/main/java/com/jme3/scene/mesh/MorphTarget.java
+++ b/jme3-core/src/main/java/com/jme3/scene/mesh/MorphTarget.java
@@ -11,6 +11,23 @@
public class MorphTarget implements Savable {
private EnumMap buffers = new EnumMap<>(VertexBuffer.Type.class);
+ private String name = null;
+
+ public MorphTarget() {
+
+ }
+
+ public MorphTarget(String name) {
+ this.name = name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
public void setBuffer(VertexBuffer.Type type, FloatBuffer buffer) {
buffers.put(type, buffer);
@@ -35,6 +52,7 @@ public void write(JmeExporter ex) throws IOException {
Buffer roData = entry.getValue().asReadOnlyBuffer();
oc.write((FloatBuffer) roData, entry.getKey().name(),null);
}
+ oc.write(name, "morphName", null);
}
@Override
@@ -46,6 +64,6 @@ public void read(JmeImporter im) throws IOException {
setBuffer(type, b);
}
}
-
+ name = ic.readString("morphName", null);
}
}
diff --git a/jme3-core/src/main/java/com/jme3/scene/mesh/VirtualIndexBuffer.java b/jme3-core/src/main/java/com/jme3/scene/mesh/VirtualIndexBuffer.java
index 64aa438eb6..dd57abee43 100644
--- a/jme3-core/src/main/java/com/jme3/scene/mesh/VirtualIndexBuffer.java
+++ b/jme3-core/src/main/java/com/jme3/scene/mesh/VirtualIndexBuffer.java
@@ -32,6 +32,8 @@
package com.jme3.scene.mesh;
import com.jme3.scene.Mesh.Mode;
+import com.jme3.scene.VertexBuffer.Format;
+
import java.nio.Buffer;
/**
@@ -138,7 +140,7 @@ public int get(int i) {
}
@Override
- public void put(int i, int value) {
+ public IndexBuffer put(int i, int value) {
throw new UnsupportedOperationException("Does not represent index buffer");
}
@@ -152,4 +154,15 @@ public Buffer getBuffer() {
return null;
}
+ @Override
+ public IndexBuffer put (int value) {
+ throw new UnsupportedOperationException("Does not represent index buffer");
+ }
+
+ @Override
+ public Format getFormat () {
+ // return largest size
+ return Format.UnsignedInt;
+ }
+
}
diff --git a/jme3-core/src/main/java/com/jme3/scene/mesh/WrappedIndexBuffer.java b/jme3-core/src/main/java/com/jme3/scene/mesh/WrappedIndexBuffer.java
index a960d2e360..5a91050f2d 100644
--- a/jme3-core/src/main/java/com/jme3/scene/mesh/WrappedIndexBuffer.java
+++ b/jme3-core/src/main/java/com/jme3/scene/mesh/WrappedIndexBuffer.java
@@ -107,11 +107,7 @@ public static void convertToList(Mesh mesh){
default:
break;
}
- if (outBuf instanceof IndexIntBuffer){
- mesh.setBuffer(Type.Index, 3, (IntBuffer)outBuf.getBuffer());
- }else{
- mesh.setBuffer(Type.Index, 3, (ShortBuffer)outBuf.getBuffer());
- }
+ mesh.setBuffer(Type.Index, 3, outBuf.getFormat(), outBuf.getBuffer());
}
}
diff --git a/jme3-core/src/main/java/com/jme3/scene/shape/Line.java b/jme3-core/src/main/java/com/jme3/scene/shape/Line.java
index e2ac6d85c3..93e667d7c5 100644
--- a/jme3-core/src/main/java/com/jme3/scene/shape/Line.java
+++ b/jme3-core/src/main/java/com/jme3/scene/shape/Line.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009-2012 jMonkeyEngine
+ * Copyright (c) 2009-2019 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -51,8 +51,11 @@ public class Line extends Mesh {
private Vector3f start;
private Vector3f end;
-
- public Line() {
+
+ /**
+ * No-argument constructor needed by SavableClassUtil.
+ */
+ public Line() { // TODO protected
}
public Line(Vector3f start, Vector3f end) {
@@ -79,9 +82,16 @@ protected void updateGeometry(Vector3f start, Vector3f end) {
}
/**
- * Update the start and end points of the line.
+ * Alter the start and end.
+ *
+ * @param start the desired mesh location of the start (not null,
+ * unaffected)
+ * @param end the desired mesh location of the end (not null, unaffected)
*/
public void updatePoints(Vector3f start, Vector3f end) {
+ this.start.set(start);
+ this.end.set(end);
+
VertexBuffer posBuf = getBuffer(Type.Position);
FloatBuffer fb = (FloatBuffer) posBuf.getData();
diff --git a/jme3-core/src/main/java/com/jme3/scene/shape/PQTorus.java b/jme3-core/src/main/java/com/jme3/scene/shape/PQTorus.java
index 041051dcfb..fad5f731cc 100644
--- a/jme3-core/src/main/java/com/jme3/scene/shape/PQTorus.java
+++ b/jme3-core/src/main/java/com/jme3/scene/shape/PQTorus.java
@@ -210,6 +210,8 @@ public void updateGeometry(float p, float q, float radius, float width, int step
setBuffer(Type.Normal, 3, fnb);
setBuffer(Type.TexCoord, 2, ftb);
setBuffer(Type.Index, 3, sib);
+
+ updateBound();
}
@Override
diff --git a/jme3-core/src/main/java/com/jme3/shader/Glsl300ShaderGenerator.java b/jme3-core/src/main/java/com/jme3/shader/Glsl300ShaderGenerator.java
new file mode 100644
index 0000000000..450a21a5ff
--- /dev/null
+++ b/jme3-core/src/main/java/com/jme3/shader/Glsl300ShaderGenerator.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2009-2012 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.shader;
+
+import com.jme3.asset.AssetManager;
+import com.jme3.material.ShaderGenerationInfo;
+import com.jme3.shader.Shader.ShaderType;
+
+
+/**
+ * This shader Generator can generate Vertex and Fragment shaders from
+ * ShaderNodes for GLESSL 3.0
+ * Nowdays it's just a subclass of Glsl150ShaderGenerator overriding the version
+ * string because GLSL 1.5 is mostly compatible with GLESSL 3.0
+ *
+ * @author Nehon
+ * @author Joliver82
+ */
+public class Glsl300ShaderGenerator extends Glsl150ShaderGenerator {
+
+ /**
+ * Creates a Glsl300ShaderGenerator
+ *
+ * @param assetManager the assetmanager
+ */
+ public Glsl300ShaderGenerator(AssetManager assetManager) {
+ super(assetManager);
+ }
+
+ @Override
+ protected String getLanguageAndVersion(ShaderType type) {
+ return "GLSL300";
+ }
+
+}
diff --git a/jme3-core/src/main/java/com/jme3/system/AppSettings.java b/jme3-core/src/main/java/com/jme3/system/AppSettings.java
index cab197ce8c..bd8db3107c 100644
--- a/jme3-core/src/main/java/com/jme3/system/AppSettings.java
+++ b/jme3-core/src/main/java/com/jme3/system/AppSettings.java
@@ -70,6 +70,19 @@ public final class AppSettings extends HashMap {
*/
public static final String LWJGL_OPENGL2 = "LWJGL-OpenGL2";
+ /**
+ * Use LWJGL as the display system and force using the core OpenGL3.0 renderer.
+ *
+ * If the underlying system does not support OpenGL3.0, then the context
+ * initialization will throw an exception. Note that currently jMonkeyEngine
+ * does not have any shaders that support OpenGL3.0 therefore this
+ * option is not useful.
+ *
+ *
+ * @see AppSettings#setRenderer(java.lang.String)
+ */
+ public static final String LWJGL_OPENGL30 = "LWJGL-OpenGL30";
+
/**
* Use LWJGL as the display system and force using the core OpenGL3.2 renderer.
*
@@ -80,10 +93,26 @@ public final class AppSettings extends HashMap {
*
* Note: OpenGL 3.2 is used to give 3.x support to Mac users.
*
+ * @deprecated Previously meant 3.2, use LWJGL_OPENGL32 or LWJGL_OPENGL30
* @see AppSettings#setRenderer(java.lang.String)
*/
+ @Deprecated
public static final String LWJGL_OPENGL3 = "LWJGL-OpenGL3";
+ /**
+ * Use LWJGL as the display system and force using the core OpenGL3.2 renderer.
+ *
+ * If the underlying system does not support OpenGL3.2, then the context
+ * initialization will throw an exception. Note that currently jMonkeyEngine
+ * does not have any shaders that support OpenGL3.2 therefore this
+ * option is not useful.
+ *
+ * Note: OpenGL 3.2 is used to give 3.x support to Mac users.
+ *
+ * @see AppSettings#setRenderer(java.lang.String)
+ */
+ public static final String LWJGL_OPENGL32 = LWJGL_OPENGL3;
+
/**
* Use LWJGL as the display system and force using the OpenGL3.3 renderer.
*
@@ -100,10 +129,22 @@ public final class AppSettings extends HashMap {
* If the underlying system does not support OpenGL4.0, then the context
* initialization will throw an exception.
*
+ * @deprecated Use LWJGL_OPENGL40
* @see AppSettings#setRenderer(java.lang.String)
*/
+ @Deprecated
public static final String LWJGL_OPENGL4 = "LWJGL-OpenGL4";
+ /**
+ * Use LWJGL as the display system and force using the OpenGL4.0 renderer.
+ *
+ * If the underlying system does not support OpenGL4.0, then the context
+ * initialization will throw an exception.
+ *
+ * @see AppSettings#setRenderer(java.lang.String)
+ */
+ public static final String LWJGL_OPENGL40 = LWJGL_OPENGL4;
+
/**
* Use LWJGL as the display system and force using the OpenGL4.1 renderer.
*
diff --git a/jme3-core/src/main/java/com/jme3/system/JmeSystemDelegate.java b/jme3-core/src/main/java/com/jme3/system/JmeSystemDelegate.java
index 26e79aacc1..71c4176327 100644
--- a/jme3-core/src/main/java/com/jme3/system/JmeSystemDelegate.java
+++ b/jme3-core/src/main/java/com/jme3/system/JmeSystemDelegate.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009-2012 jMonkeyEngine
+ * Copyright (c) 2009-2019 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -169,8 +169,13 @@ public Platform getPlatform() {
boolean is64 = is64Bit(arch);
if (os.contains("windows")) {
return is64 ? Platform.Windows64 : Platform.Windows32;
- } else if (os.contains("linux") || os.contains("freebsd") || os.contains("sunos")) {
- return is64 ? Platform.Linux64 : Platform.Linux32;
+ } else if (os.contains("linux") || os.contains("freebsd")
+ || os.contains("sunos") || os.contains("unix")) {
+ if (arch.startsWith("arm")) {
+ return is64 ? Platform.Linux_ARM64 : Platform.Linux_ARM32;
+ } else {
+ return is64 ? Platform.Linux64 : Platform.Linux32;
+ }
} else if (os.contains("mac os x") || os.contains("darwin")) {
if (arch.startsWith("ppc")) {
return is64 ? Platform.MacOSX_PPC64 : Platform.MacOSX_PPC32;
diff --git a/jme3-core/src/main/java/com/jme3/system/NullRenderer.java b/jme3-core/src/main/java/com/jme3/system/NullRenderer.java
index 3c289ecc38..76b3fa1463 100644
--- a/jme3-core/src/main/java/com/jme3/system/NullRenderer.java
+++ b/jme3-core/src/main/java/com/jme3/system/NullRenderer.java
@@ -212,4 +212,14 @@ public void readFrameBufferWithFormat(FrameBuffer fb, ByteBuffer byteBuf, Image.
@Override
public void setDefaultAnisotropicFilter(int level) {
}
+
+ @Override
+ public boolean getAlphaToCoverage() {
+ return false;
+ }
+
+ @Override
+ public int getDefaultAnisotropicFilter() {
+ return 0;
+ }
}
diff --git a/jme3-core/src/main/java/com/jme3/system/Platform.java b/jme3-core/src/main/java/com/jme3/system/Platform.java
index f9206d33f8..1b80ff2e25 100644
--- a/jme3-core/src/main/java/com/jme3/system/Platform.java
+++ b/jme3-core/src/main/java/com/jme3/system/Platform.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009-2012 jMonkeyEngine
+ * Copyright (c) 2009-2019 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -44,22 +44,32 @@ public enum Platform {
Windows64(true),
/**
- * Linux 32 bit
+ * Linux 32-bit Intel
*/
Linux32,
/**
- * Linux 64 bit
+ * Linux 64-bit Intel
*/
Linux64(true),
/**
- * Apple Mac OS X 32 bit
+ * Linux 32-bit ARM
+ */
+ Linux_ARM32,
+
+ /**
+ * Linux 64-bit ARM
+ */
+ Linux_ARM64(true),
+
+ /**
+ * Apple Mac OS X 32-bit Intel
*/
MacOSX32,
/**
- * Apple Mac OS X 64 bit
+ * Apple Mac OS X 64-bit Intel
*/
MacOSX64(true),
diff --git a/jme3-core/src/main/java/com/jme3/system/SystemListener.java b/jme3-core/src/main/java/com/jme3/system/SystemListener.java
index e2e604a4b0..132f475234 100644
--- a/jme3-core/src/main/java/com/jme3/system/SystemListener.java
+++ b/jme3-core/src/main/java/com/jme3/system/SystemListener.java
@@ -32,7 +32,7 @@
package com.jme3.system;
/**
- * The ContextListener> provides a means for an application
+ * The {@code SystemListener} provides a means for an application
* to receive events relating to a context.
*/
public interface SystemListener {
diff --git a/jme3-core/src/main/java/com/jme3/texture/Image.java b/jme3-core/src/main/java/com/jme3/texture/Image.java
index eaa3aae8a4..f7cee1b55e 100644
--- a/jme3-core/src/main/java/com/jme3/texture/Image.java
+++ b/jme3-core/src/main/java/com/jme3/texture/Image.java
@@ -494,6 +494,11 @@ public enum Format {
* Requires {@link Caps#FloatTexture}.
*/
RG32F(64,true),
+
+ /**
+ * 10-bit red, green, and blue with 2-bit alpha.
+ */
+ RGB10A2(32),
;
private int bpp;
diff --git a/jme3-core/src/main/java/com/jme3/texture/Texture.java b/jme3-core/src/main/java/com/jme3/texture/Texture.java
index 253423d004..65563928f6 100644
--- a/jme3-core/src/main/java/com/jme3/texture/Texture.java
+++ b/jme3-core/src/main/java/com/jme3/texture/Texture.java
@@ -248,6 +248,7 @@ public enum WrapMode {
*
* @deprecated Not supported by OpenGL 3
*/
+ @Deprecated
MirrorEdgeClamp;
}
@@ -278,21 +279,23 @@ public enum ShadowCompareMode {
*/
Off,
- /**
+ /**
+ * {@code
* Compares the 3rd texture coordinate R to the value
* in this depth texture. If R <= texture value then result is 1.0,
* otherwise, result is 0.0. If filtering is set to bilinear or trilinear
* the implementation may sample the texture multiple times to provide
- * smoother results in the range [0, 1].
+ * smoother results in the range [0, 1].}
*/
LessOrEqual,
/**
+ * {@code
* Compares the 3rd texture coordinate R to the value
* in this depth texture. If R >= texture value then result is 1.0,
* otherwise, result is 0.0. If filtering is set to bilinear or trilinear
* the implementation may sample the texture multiple times to provide
- * smoother results in the range [0, 1].
+ * smoother results in the range [0, 1].}
*/
GreaterOrEqual
}
diff --git a/jme3-core/src/main/java/com/jme3/texture/TextureCubeMap.java b/jme3-core/src/main/java/com/jme3/texture/TextureCubeMap.java
index e2447fac28..f1a0f7d3bd 100644
--- a/jme3-core/src/main/java/com/jme3/texture/TextureCubeMap.java
+++ b/jme3-core/src/main/java/com/jme3/texture/TextureCubeMap.java
@@ -44,14 +44,14 @@
* Describes a cubemap texture.
* The image specified by setImage must contain 6 data units,
* each data contains a 2D image representing a cube's face.
- * The slices are specified in this order:
- *
- * 0 => Positive X (+x)
- * 1 => Negative X (-x)
- * 2 => Positive Y (+y)
- * 3 => Negative Y (-y)
- * 4 => Positive Z (+z)
- * 5 => Negative Z (-z)
+ * The slices are specified in this order:
+ *
+ * 0 -- Positive X (+x)
+ * 1 -- Negative X (-x)
+ * 2 -- Positive Y (+y)
+ * 3 -- Negative Y (-y)
+ * 4 -- Positive Z (+z)
+ * 5 -- Negative Z (-z)
*
* @author Joshua Slack
*/
diff --git a/jme3-core/src/main/java/com/jme3/texture/image/ImageCodec.java b/jme3-core/src/main/java/com/jme3/texture/image/ImageCodec.java
index bbad96ace8..993ce508b4 100644
--- a/jme3-core/src/main/java/com/jme3/texture/image/ImageCodec.java
+++ b/jme3-core/src/main/java/com/jme3/texture/image/ImageCodec.java
@@ -130,6 +130,10 @@ public ImageCodec(int bpp, int flags, int maxAlpha, int maxRed, int maxGreen, in
0, 11, 6, 1));
((BitMaskImageCodec)params.get(Format.RGB5A1)).be = true;
+ params.put(Format.RGB10A2, new BitMaskImageCodec(4, 0,
+ 2, 10, 10, 10,
+ 0, 22, 12, 2));
+
// params.put(Format.RGBA8, new ByteAlignedImageCodec(4, 0,
// 0, 1, 1, 1,
// 0, 0, 1, 2));
diff --git a/jme3-core/src/main/java/com/jme3/util/ListSort.java b/jme3-core/src/main/java/com/jme3/util/ListSort.java
index c45353a0cb..517f2dd6b2 100644
--- a/jme3-core/src/main/java/com/jme3/util/ListSort.java
+++ b/jme3-core/src/main/java/com/jme3/util/ListSort.java
@@ -52,12 +52,13 @@
* for optimal performance, but can be called several times if the length of the
* list changes
*
+ * {@code
* Disclaimer : I was intrigued by the use of val >>> 1 in java 7 Timsort class
* instead of val / 2 (integer division). Micro benching revealed that val >>> 1
* is twice faster than val / 2 in java 6 and has similar perf in java 7. The
* following code uses val >>> 1 when ever a value needs to be divided by 2 and
* rounded to its floor
- *
+ * }
*
* @author Nehon
*/
@@ -66,7 +67,7 @@ public class ListSort {
/**
* Threshold for binary sort vs merge. Original algorithm use 64, java7
* TimSort uses 32 and I used 128, see this post for explanations :
- * http://hub.jmonkeyengine.org/groups/development-discussion-jme3/forum/topic/i-got-that-sorted-out-huhuhu/
+ * https://hub.jmonkeyengine.org/t/i-got-that-sorted-out-huhuhu/24478
*/
private static final int MIN_SIZE = 128;
private T[] array;
diff --git a/jme3-core/src/main/java/com/jme3/util/SortUtil.java b/jme3-core/src/main/java/com/jme3/util/SortUtil.java
index 51edc0adb2..7628495f5c 100644
--- a/jme3-core/src/main/java/com/jme3/util/SortUtil.java
+++ b/jme3-core/src/main/java/com/jme3/util/SortUtil.java
@@ -47,7 +47,7 @@ public class SortUtil {
private static final int INSERTION_SORT_THRESHOLD = 7;
- /**
+ /*
procedure optimizedGnomeSort(a[])
pos := 1
last := 0
diff --git a/jme3-core/src/main/resources/Common/MatDefs/Blur/RadialBlur.j3md b/jme3-core/src/main/resources/Common/MatDefs/Blur/RadialBlur.j3md
index e409926963..977007f073 100644
--- a/jme3-core/src/main/resources/Common/MatDefs/Blur/RadialBlur.j3md
+++ b/jme3-core/src/main/resources/Common/MatDefs/Blur/RadialBlur.j3md
@@ -10,8 +10,8 @@ MaterialDef Radial Blur {
}
Technique {
- VertexShader GLSL120 GLSL150: Common/MatDefs/Post/Post.vert
- FragmentShader GLSL120 GLSL150: Common/MatDefs/Blur/RadialBlur.frag
+ VertexShader GLSL300 GLSL120 GLSL150: Common/MatDefs/Post/Post.vert
+ FragmentShader GLSL300 GLSL120 GLSL150: Common/MatDefs/Blur/RadialBlur.frag
WorldParameters {
}
@@ -20,4 +20,4 @@ MaterialDef Radial Blur {
RESOLVE_MS : NumSamples
}
}
-}
\ No newline at end of file
+}
diff --git a/jme3-core/src/main/resources/Common/MatDefs/Light/Lighting.j3md b/jme3-core/src/main/resources/Common/MatDefs/Light/Lighting.j3md
index 824a173696..4a5fa256ee 100644
--- a/jme3-core/src/main/resources/Common/MatDefs/Light/Lighting.j3md
+++ b/jme3-core/src/main/resources/Common/MatDefs/Light/Lighting.j3md
@@ -133,8 +133,8 @@ MaterialDef Phong Lighting {
Technique {
LightMode SinglePass
- VertexShader GLSL100 GLSL150: Common/MatDefs/Light/SPLighting.vert
- FragmentShader GLSL100 GLSL150: Common/MatDefs/Light/SPLighting.frag
+ VertexShader GLSL310 GLSL300 GLSL100 GLSL150: Common/MatDefs/Light/SPLighting.vert
+ FragmentShader GLSL310 GLSL300 GLSL100 GLSL150: Common/MatDefs/Light/SPLighting.frag
WorldParameters {
WorldViewProjectionMatrix
@@ -180,8 +180,8 @@ MaterialDef Phong Lighting {
LightMode MultiPass
- VertexShader GLSL100 GLSL150: Common/MatDefs/Light/Lighting.vert
- FragmentShader GLSL100 GLSL150: Common/MatDefs/Light/Lighting.frag
+ VertexShader GLSL310 GLSL300 GLSL100 GLSL150: Common/MatDefs/Light/Lighting.vert
+ FragmentShader GLSL310 GLSL300 GLSL100 GLSL150: Common/MatDefs/Light/Lighting.frag
WorldParameters {
WorldViewProjectionMatrix
@@ -225,8 +225,8 @@ MaterialDef Phong Lighting {
Technique PreShadow {
- VertexShader GLSL100 GLSL150 : Common/MatDefs/Shadow/PreShadow.vert
- FragmentShader GLSL100 GLSL150 : Common/MatDefs/Shadow/PreShadow.frag
+ VertexShader GLSL310 GLSL300 GLSL100 GLSL150 : Common/MatDefs/Shadow/PreShadow.vert
+ FragmentShader GLSL310 GLSL300 GLSL100 GLSL150 : Common/MatDefs/Shadow/PreShadow.frag
WorldParameters {
WorldViewProjectionMatrix
@@ -255,8 +255,8 @@ MaterialDef Phong Lighting {
Technique PostShadow {
- VertexShader GLSL100 GLSL150: Common/MatDefs/Shadow/PostShadow.vert
- FragmentShader GLSL100 GLSL150: Common/MatDefs/Shadow/PostShadow.frag
+ VertexShader GLSL310 GLSL300 GLSL100 GLSL150: Common/MatDefs/Shadow/PostShadow.vert
+ FragmentShader GLSL310 GLSL300 GLSL100 GLSL150: Common/MatDefs/Shadow/PostShadow.frag
WorldParameters {
WorldViewProjectionMatrix
@@ -292,8 +292,8 @@ MaterialDef Phong Lighting {
Technique PreNormalPass {
- VertexShader GLSL100 GLSL150 : Common/MatDefs/SSAO/normal.vert
- FragmentShader GLSL100 GLSL150 : Common/MatDefs/SSAO/normal.frag
+ VertexShader GLSL310 GLSL300 GLSL100 GLSL150 : Common/MatDefs/SSAO/normal.vert
+ FragmentShader GLSL310 GLSL300 GLSL100 GLSL150 : Common/MatDefs/SSAO/normal.frag
WorldParameters {
WorldViewProjectionMatrix
@@ -315,8 +315,8 @@ MaterialDef Phong Lighting {
Technique Glow {
- VertexShader GLSL100 GLSL150: Common/MatDefs/Misc/Unshaded.vert
- FragmentShader GLSL100 GLSL150: Common/MatDefs/Light/Glow.frag
+ VertexShader GLSL310 GLSL300 GLSL100 GLSL150: Common/MatDefs/Misc/Unshaded.vert
+ FragmentShader GLSL310 GLSL300 GLSL100 GLSL150: Common/MatDefs/Light/Glow.frag
WorldParameters {
WorldViewProjectionMatrix
diff --git a/jme3-core/src/main/resources/Common/MatDefs/Light/PBRLighting.frag b/jme3-core/src/main/resources/Common/MatDefs/Light/PBRLighting.frag
index 077b08579f..4eaa6a88f5 100644
--- a/jme3-core/src/main/resources/Common/MatDefs/Light/PBRLighting.frag
+++ b/jme3-core/src/main/resources/Common/MatDefs/Light/PBRLighting.frag
@@ -296,7 +296,7 @@ void main(){
weight3 /= weightSum;
#endif
- #if USE_AMBIENT_LIGHT
+ #ifdef USE_AMBIENT_LIGHT
color1.rgb *= g_AmbientLightColor.rgb;
color2.rgb *= g_AmbientLightColor.rgb;
color3.rgb *= g_AmbientLightColor.rgb;
diff --git a/jme3-core/src/main/resources/Common/MatDefs/Light/PBRLighting.j3md b/jme3-core/src/main/resources/Common/MatDefs/Light/PBRLighting.j3md
index 8465d2f0b2..40b4f9a6c7 100644
--- a/jme3-core/src/main/resources/Common/MatDefs/Light/PBRLighting.j3md
+++ b/jme3-core/src/main/resources/Common/MatDefs/Light/PBRLighting.j3md
@@ -123,8 +123,8 @@ MaterialDef PBR Lighting {
Technique {
LightMode SinglePassAndImageBased
- VertexShader GLSL110 GLSL150: Common/MatDefs/Light/PBRLighting.vert
- FragmentShader GLSL110 GLSL150: Common/MatDefs/Light/PBRLighting.frag
+ VertexShader GLSL300 GLSL110 GLSL150: Common/MatDefs/Light/PBRLighting.vert
+ FragmentShader GLSL300 GLSL110 GLSL150: Common/MatDefs/Light/PBRLighting.frag
WorldParameters {
WorldViewProjectionMatrix
@@ -167,8 +167,8 @@ MaterialDef PBR Lighting {
Technique PreShadow {
- VertexShader GLSL100 GLSL150 : Common/MatDefs/Shadow/PreShadow.vert
- FragmentShader GLSL100 GLSL150 : Common/MatDefs/Shadow/PreShadow.frag
+ VertexShader GLSL300 GLSL100 GLSL150 : Common/MatDefs/Shadow/PreShadow.vert
+ FragmentShader GLSL300 GLSL100 GLSL150 : Common/MatDefs/Shadow/PreShadow.frag
WorldParameters {
WorldViewProjectionMatrix
@@ -197,8 +197,8 @@ MaterialDef PBR Lighting {
Technique PostShadow{
- VertexShader GLSL150: Common/MatDefs/Shadow/PostShadow.vert
- FragmentShader GLSL150: Common/MatDefs/Shadow/PostShadow.frag
+ VertexShader GLSL310 GLSL300 GLSL150: Common/MatDefs/Shadow/PostShadow.vert
+ FragmentShader GLSL310 GLSL300 GLSL150: Common/MatDefs/Shadow/PostShadow.frag
WorldParameters {
WorldViewProjectionMatrix
diff --git a/jme3-core/src/main/resources/Common/MatDefs/Misc/Unshaded.j3md b/jme3-core/src/main/resources/Common/MatDefs/Misc/Unshaded.j3md
index f765d20445..4c609dca8d 100644
--- a/jme3-core/src/main/resources/Common/MatDefs/Misc/Unshaded.j3md
+++ b/jme3-core/src/main/resources/Common/MatDefs/Misc/Unshaded.j3md
@@ -62,8 +62,8 @@ MaterialDef Unshaded {
}
Technique {
- VertexShader GLSL100 GLSL150: Common/MatDefs/Misc/Unshaded.vert
- FragmentShader GLSL100 GLSL150: Common/MatDefs/Misc/Unshaded.frag
+ VertexShader GLSL310 GLSL300 GLSL100 GLSL150: Common/MatDefs/Misc/Unshaded.vert
+ FragmentShader GLSL310 GLSL300 GLSL100 GLSL150: Common/MatDefs/Misc/Unshaded.frag
WorldParameters {
WorldViewProjectionMatrix
@@ -88,8 +88,8 @@ MaterialDef Unshaded {
Technique PreNormalPass {
- VertexShader GLSL100 GLSL150 : Common/MatDefs/SSAO/normal.vert
- FragmentShader GLSL100 GLSL150 : Common/MatDefs/SSAO/normal.frag
+ VertexShader GLSL310 GLSL300 GLSL100 GLSL150 : Common/MatDefs/SSAO/normal.vert
+ FragmentShader GLSL310 GLSL300 GLSL100 GLSL150 : Common/MatDefs/SSAO/normal.frag
WorldParameters {
WorldViewProjectionMatrix
@@ -109,8 +109,8 @@ MaterialDef Unshaded {
Technique PreShadow {
- VertexShader GLSL100 GLSL150 : Common/MatDefs/Shadow/PreShadow.vert
- FragmentShader GLSL100 GLSL150 : Common/MatDefs/Shadow/PreShadow.frag
+ VertexShader GLSL310 GLSL300 GLSL100 GLSL150 : Common/MatDefs/Shadow/PreShadow.vert
+ FragmentShader GLSL310 GLSL300 GLSL100 GLSL150 : Common/MatDefs/Shadow/PreShadow.frag
WorldParameters {
WorldViewProjectionMatrix
@@ -140,8 +140,8 @@ MaterialDef Unshaded {
Technique PostShadow {
- VertexShader GLSL100 GLSL150: Common/MatDefs/Shadow/PostShadow.vert
- FragmentShader GLSL100 GLSL150: Common/MatDefs/Shadow/PostShadow.frag
+ VertexShader GLSL310 GLSL300 GLSL100 GLSL150: Common/MatDefs/Shadow/PostShadow.vert
+ FragmentShader GLSL310 GLSL300 GLSL100 GLSL150: Common/MatDefs/Shadow/PostShadow.frag
WorldParameters {
WorldViewProjectionMatrix
@@ -176,8 +176,8 @@ MaterialDef Unshaded {
Technique Glow {
- VertexShader GLSL100 GLSL150: Common/MatDefs/Misc/Unshaded.vert
- FragmentShader GLSL100 GLSL150: Common/MatDefs/Light/Glow.frag
+ VertexShader GLSL310 GLSL300 GLSL100 GLSL150: Common/MatDefs/Misc/Unshaded.vert
+ FragmentShader GLSL310 GLSL300 GLSL100 GLSL150: Common/MatDefs/Light/Glow.frag
WorldParameters {
WorldViewProjectionMatrix
@@ -196,4 +196,4 @@ MaterialDef Unshaded {
NUM_TARGETS_BUFFERS: NumberOfTargetsBuffers
}
}
-}
\ No newline at end of file
+}
diff --git a/jme3-core/src/main/resources/Common/MatDefs/ShaderNodes/Environment/envMapping.j3sn b/jme3-core/src/main/resources/Common/MatDefs/ShaderNodes/Environment/envMapping.j3sn
index 148c88f1c5..529dea4bae 100644
--- a/jme3-core/src/main/resources/Common/MatDefs/ShaderNodes/Environment/envMapping.j3sn
+++ b/jme3-core/src/main/resources/Common/MatDefs/ShaderNodes/Environment/envMapping.j3sn
@@ -2,6 +2,7 @@ ShaderNodeDefinitions{
ShaderNodeDefinition EnvMapping {
Type: Fragment
+ Shader GLSL300: Common/MatDefs/ShaderNodes/Environment/envMapping130.frag
Shader GLSL100: Common/MatDefs/ShaderNodes/Environment/envMapping100.frag
Shader GLSL130: Common/MatDefs/ShaderNodes/Environment/envMapping130.frag
@@ -19,4 +20,4 @@ ShaderNodeDefinitions{
vec4 color
}
}
-}
\ No newline at end of file
+}
diff --git a/jme3-core/src/main/resources/Common/MatDefs/ShaderNodes/Environment/envMapping100.frag b/jme3-core/src/main/resources/Common/MatDefs/ShaderNodes/Environment/envMapping100.frag
index 9d40ec523b..29932c7c5a 100644
--- a/jme3-core/src/main/resources/Common/MatDefs/ShaderNodes/Environment/envMapping100.frag
+++ b/jme3-core/src/main/resources/Common/MatDefs/ShaderNodes/Environment/envMapping100.frag
@@ -1,8 +1,17 @@
#extension GL_ARB_shader_texture_lod : enable
+#extension GL_EXT_shader_texture_lod : enable
void main(){
//@input vec3 refVec the reflection vector
//@input samplerCube cubeMap the cube map
//@output vec4 color the output color
- color = textureCubeLod(cubeMap, refVec, 0.0);
-}
\ No newline at end of file
+ #ifdef GL_ES
+ #ifdef GL_EXT_shader_texture_lod
+ color = textureCubeLodEXT(cubeMap, refVec, 0.0);
+ #else
+ color = textureCube(cubeMap, refVec);
+ #endif
+ #else
+ color = textureCubeLod(cubeMap, refVec, 0.0);
+ #endif
+}
diff --git a/jme3-core/src/main/resources/Common/MatDefs/Shadow/PostShadow.j3md b/jme3-core/src/main/resources/Common/MatDefs/Shadow/PostShadow.j3md
index fd8ea8a24d..ce588b60af 100644
--- a/jme3-core/src/main/resources/Common/MatDefs/Shadow/PostShadow.j3md
+++ b/jme3-core/src/main/resources/Common/MatDefs/Shadow/PostShadow.j3md
@@ -35,8 +35,8 @@ MaterialDef Post Shadow {
}
Technique {
- VertexShader GLSL100 GLSL150: Common/MatDefs/Shadow/PostShadow.vert
- FragmentShader GLSL100 GLSL150: Common/MatDefs/Shadow/PostShadow.frag
+ VertexShader GLSL310 GLSL300 GLSL100 GLSL150: Common/MatDefs/Shadow/PostShadow.vert
+ FragmentShader GLSL310 GLSL300 GLSL100 GLSL150: Common/MatDefs/Shadow/PostShadow.frag
WorldParameters {
WorldViewProjectionMatrix
@@ -61,4 +61,4 @@ MaterialDef Post Shadow {
}
}
-}
\ No newline at end of file
+}
diff --git a/jme3-core/src/main/resources/Common/MatDefs/Shadow/PostShadowFilter.j3md b/jme3-core/src/main/resources/Common/MatDefs/Shadow/PostShadowFilter.j3md
index 0023b0b813..05188796c6 100644
--- a/jme3-core/src/main/resources/Common/MatDefs/Shadow/PostShadowFilter.j3md
+++ b/jme3-core/src/main/resources/Common/MatDefs/Shadow/PostShadowFilter.j3md
@@ -42,8 +42,8 @@ MaterialDef Post Shadow {
}
Technique {
- VertexShader GLSL150: Common/MatDefs/Shadow/PostShadowFilter.vert
- FragmentShader GLSL150: Common/MatDefs/Shadow/PostShadowFilter15.frag
+ VertexShader GLSL310 GLSL150: Common/MatDefs/Shadow/PostShadowFilter.vert
+ FragmentShader GLSL310 GLSL150: Common/MatDefs/Shadow/PostShadowFilter15.frag
WorldParameters {
ResolutionInverse
@@ -88,4 +88,4 @@ MaterialDef Post Shadow {
-}
\ No newline at end of file
+}
diff --git a/jme3-core/src/main/resources/Common/ShaderLib/GLSLCompat.glsllib b/jme3-core/src/main/resources/Common/ShaderLib/GLSLCompat.glsllib
index c1ace91d12..697db195d5 100644
--- a/jme3-core/src/main/resources/Common/ShaderLib/GLSLCompat.glsllib
+++ b/jme3-core/src/main/resources/Common/ShaderLib/GLSLCompat.glsllib
@@ -19,13 +19,18 @@
#endif
#if __VERSION__ >= 130
+# ifdef GL_ES
+out highp vec4 outFragColor;
+# else
out vec4 outFragColor;
+#endif
# define texture1D texture
# define texture2D texture
# define texture3D texture
# define textureCube texture
# define texture2DLod textureLod
# define textureCubeLod textureLod
+# define texture2DArray texture
# if defined VERTEX_SHADER
# define varying out
# define attribute in
@@ -33,4 +38,8 @@ out vec4 outFragColor;
# define varying in
# define gl_FragColor outFragColor
# endif
-#endif
\ No newline at end of file
+#else
+# define isnan(val) !(val<0.0||val>0.0||val==0.0)
+#endif
+
+
diff --git a/jme3-core/src/main/resources/Common/ShaderLib/MultiSample.glsllib b/jme3-core/src/main/resources/Common/ShaderLib/MultiSample.glsllib
index 4ecd331576..8dc1e2a728 100644
--- a/jme3-core/src/main/resources/Common/ShaderLib/MultiSample.glsllib
+++ b/jme3-core/src/main/resources/Common/ShaderLib/MultiSample.glsllib
@@ -16,7 +16,7 @@ uniform int m_NumSamplesDepth;
#endif
// NOTE: Only define multisample functions if multisample is available
-#if defined(GL_ARB_texture_multisample)
+#if defined(GL_ARB_texture_multisample) || (defined GL_ES && __VERSION__>=310)
vec4 textureFetch(in sampler2DMS tex,in vec2 texC, in int numSamples){
ivec2 iTexC = ivec2(texC * vec2(textureSize(tex)));
vec4 color = vec4(0.0);
diff --git a/jme3-core/src/main/resources/Common/ShaderLib/Shadows.glsllib b/jme3-core/src/main/resources/Common/ShaderLib/Shadows.glsllib
index c7c6b88518..eb3380ce1f 100644
--- a/jme3-core/src/main/resources/Common/ShaderLib/Shadows.glsllib
+++ b/jme3-core/src/main/resources/Common/ShaderLib/Shadows.glsllib
@@ -1,16 +1,23 @@
#if __VERSION__ >= 130
// Because gpu_shader5 is actually where those
// gather functions are declared to work on shadowmaps
- #extension GL_ARB_gpu_shader5 : enable
+ // This "if" statement is useless as jme3 changes line ordering, so all extensions are tried to be loaded
+ #ifdef GL_ES
+ #extension GL_OES_gpu_shader5 : enable
+ #else
+ #extension GL_ARB_gpu_shader5 : enable
+ #endif
+
#define IVEC2 ivec2
- #if defined GL_ES
- #define SHADOWMAP sampler2D
- #define SHADOWCOMPARE(tex,coord) step(coord.z, texture2DProj(tex, coord).r)
- #elif defined HARDWARE_SHADOWS
+ #ifdef HARDWARE_SHADOWS
#define SHADOWMAP sampler2DShadow
#define SHADOWCOMPAREOFFSET(tex,coord,offset) textureProjOffset(tex, coord, offset)
#define SHADOWCOMPARE(tex,coord) textureProj(tex, coord)
- #define SHADOWGATHER(tex,coord) textureGather(tex, coord.xy, coord.z)
+ #if defined GL_ES && __VERSION__ <= 300
+ #define SHADOWGATHER(tex,coord) step(coord.z, textureGather(tex, coord.xy))
+ #else
+ #define SHADOWGATHER(tex,coord) textureGather(tex, coord.xy, coord.z)
+ #endif
#else
#define SHADOWMAP sampler2D
#define SHADOWCOMPAREOFFSET(tex,coord,offset) step(coord.z, textureProjOffset(tex, coord, offset).r)
@@ -31,7 +38,10 @@
#endif
#else
#define IVEC2 vec2
- #ifdef HARDWARE_SHADOWS
+ #if defined GL_ES
+ #define SHADOWMAP sampler2D
+ #define SHADOWCOMPARE(tex,coord) step(coord.z, texture2DProj(tex, coord).r)
+ #elif defined HARDWARE_SHADOWS
#define SHADOWMAP sampler2DShadow
#define SHADOWCOMPARE(tex,coord) shadow2DProj(tex, coord).r
#else
@@ -91,10 +101,14 @@ float Shadow_DoShadowCompare(in SHADOWMAP tex,in vec4 projCoord){
}
float Shadow_BorderCheck(in vec2 coord){
- // Fastest, "hack" method (uses 4-5 instructions)
- vec4 t = vec4(coord.xy, 0.0, 1.0);
- t = step(t.wwxy, t.xyzz);
- return dot(t,t);
+ #ifdef GL_ES
+ return 0.0;
+ #else
+ // Fastest, "hack" method (uses 4-5 instructions)
+ vec4 t = vec4(coord.xy, 0.0, 1.0);
+ t = step(t.wwxy, t.xyzz);
+ return dot(t,t);
+ #endif
}
float Shadow_Nearest(in SHADOWMAP tex,in vec4 projCoord){
@@ -117,7 +131,8 @@ float Shadow_DoDither_2x2(in SHADOWMAP tex, in vec4 projCoord){
return 1.0;
float shadow = 0.0;
- IVEC2 o = IVEC2(mod(floor(gl_FragCoord.xy), 2.0));
+ //IVEC2 o = IVEC2(mod(floor(gl_FragCoord.xy), 2.0));
+ vec2 o = vec2(IVEC2(mod(floor(gl_FragCoord.xy), 2.0))); //Strict type checking in GLSL ES
shadow += Shadow_DoShadowCompareOffset(tex, projCoord, (vec2(-1.5, 1.5)+o));
shadow += Shadow_DoShadowCompareOffset(tex, projCoord, (vec2( 0.5, 1.5)+o));
shadow += Shadow_DoShadowCompareOffset(tex, projCoord, (vec2(-1.5, -0.5)+o));
@@ -134,7 +149,7 @@ float Shadow_DoBilinear_2x2(in SHADOWMAP tex, in vec4 projCoord){
vec4 gather = vec4(0.0);
#if __VERSION__ >= 130
- #ifdef GL_ARB_gpu_shader5
+ #if defined GL_ARB_gpu_shader5 || defined GL_OES_gpu_shader5
vec4 coord = vec4(projCoord.xyz / projCoord.www,0.0);
gather = SHADOWGATHER(tex, coord);
#else
diff --git a/jme3-core/src/plugins/java/com/jme3/export/binary/BinaryImporter.java b/jme3-core/src/plugins/java/com/jme3/export/binary/BinaryImporter.java
index d4c24054dc..93f082337b 100644
--- a/jme3-core/src/plugins/java/com/jme3/export/binary/BinaryImporter.java
+++ b/jme3-core/src/plugins/java/com/jme3/export/binary/BinaryImporter.java
@@ -345,16 +345,7 @@ public Savable readObject(int id) {
return out;
- } catch (IOException e) {
- logger.logp(Level.SEVERE, this.getClass().toString(), "readObject(int id)", "Exception", e);
- return null;
- } catch (ClassNotFoundException e) {
- logger.logp(Level.SEVERE, this.getClass().toString(), "readObject(int id)", "Exception", e);
- return null;
- } catch (InstantiationException e) {
- logger.logp(Level.SEVERE, this.getClass().toString(), "readObject(int id)", "Exception", e);
- return null;
- } catch (IllegalAccessException e) {
+ } catch (Exception e) {
logger.logp(Level.SEVERE, this.getClass().toString(), "readObject(int id)", "Exception", e);
return null;
}
diff --git a/jme3-core/src/plugins/java/com/jme3/export/binary/ByteUtils.java b/jme3-core/src/plugins/java/com/jme3/export/binary/ByteUtils.java
index f66a7fc7e1..882cb529fd 100644
--- a/jme3-core/src/plugins/java/com/jme3/export/binary/ByteUtils.java
+++ b/jme3-core/src/plugins/java/com/jme3/export/binary/ByteUtils.java
@@ -452,7 +452,7 @@ public static boolean convertBooleanFromBytes(byte[] byteArray, int offset) {
* of bytes have been read.
*
* @param store
- * the byte array to store in. Should have a length > bytes
+ * the byte array to store in. Array length must be greater than bytes param.
* @param bytes
* the number of bytes to read.
* @param is
diff --git a/jme3-core/src/plugins/java/com/jme3/material/plugins/ConditionParser.java b/jme3-core/src/plugins/java/com/jme3/material/plugins/ConditionParser.java
index 07569ce90b..2e1ff1aa27 100644
--- a/jme3-core/src/plugins/java/com/jme3/material/plugins/ConditionParser.java
+++ b/jme3-core/src/plugins/java/com/jme3/material/plugins/ConditionParser.java
@@ -79,13 +79,11 @@ public static void main(String argv[]) {
* additionally this methods updates the formattedExpression with uppercased
* defines names
*
- * supported expression syntax example:
- *
- * "(LightMap && SeparateTexCoord) || !ColorMap"
- * "#if (defined(LightMap) && defined(SeparateTexCoord)) || !defined(ColorMap)"
- * "#ifdef LightMap"
- * "#ifdef (LightMap && SeparateTexCoord) || !ColorMap"
- *
+ * supported expression syntax example:
+ * {@code "#ifdef (LightMap && SeparateTexCoord) || !ColorMap"}
*
* @param expression the expression to parse
* @return the list of defines
diff --git a/jme3-core/src/plugins/java/com/jme3/material/plugins/ShaderNodeLoaderDelegate.java b/jme3-core/src/plugins/java/com/jme3/material/plugins/ShaderNodeLoaderDelegate.java
index c8c6740463..3e64d0d785 100644
--- a/jme3-core/src/plugins/java/com/jme3/material/plugins/ShaderNodeLoaderDelegate.java
+++ b/jme3-core/src/plugins/java/com/jme3/material/plugins/ShaderNodeLoaderDelegate.java
@@ -1058,11 +1058,11 @@ public void storeVaryings(ShaderNode node, ShaderNodeVariable variable) {
}
/**
- * merges 2 condition with the given operator
+ * Merges 2 conditions with the given operator
*
* @param condition1 the first condition
* @param condition2 the second condition
- * @param operator the operator ("&&" or "||&)
+ * @param operator the operator {@literal ("&&" or "||&)}
* @return the merged condition
*/
public String mergeConditions(String condition1, String condition2, String operator) {
diff --git a/jme3-core/src/plugins/java/com/jme3/shader/plugins/GLSLLoader.java b/jme3-core/src/plugins/java/com/jme3/shader/plugins/GLSLLoader.java
index ce3264b2d5..3c4dd91300 100644
--- a/jme3-core/src/plugins/java/com/jme3/shader/plugins/GLSLLoader.java
+++ b/jme3-core/src/plugins/java/com/jme3/shader/plugins/GLSLLoader.java
@@ -191,7 +191,7 @@ public Object load(AssetInfo info) throws IOException {
if (info.getKey() instanceof ShaderAssetKey) {
injectDependencies = ((ShaderAssetKey) info.getKey()).isInjectDependencies();
}
- if (info.getKey().getExtension().equals("glsllib")) {
+ if (info.getKey().getExtension().equals("glsllib")||info.getKey().getExtension().equals("glsl")) {
// NOTE: Loopback, GLSLLIB is loaded by this loader
// and needs data as InputStream
return reader;
diff --git a/jme3-core/src/test/groovy/com/jme3/app/state/AppStateManagerTest.groovy b/jme3-core/src/test/groovy/com/jme3/app/state/AppStateManagerTest.groovy
new file mode 100644
index 0000000000..45e39c1b79
--- /dev/null
+++ b/jme3-core/src/test/groovy/com/jme3/app/state/AppStateManagerTest.groovy
@@ -0,0 +1,98 @@
+package com.jme3.app.state;
+
+import com.jme3.app.LegacyApplication;
+
+class AppStateManagerTest {
+
+ static class AttachTest extends GroovyTestCase {
+
+ void testDuplicateId() {
+ def state1 = new AbstractAppState("test1") {};
+ def state2 = new AbstractAppState("test1") {};
+
+ def app = new LegacyApplication();
+
+ app.getStateManager().attach(state1);
+
+ shouldFail(IllegalArgumentException) {
+ app.getStateManager().attach(state2);
+ }
+ }
+
+ void testDuplicateNullId() {
+ // Make sure that two states without an ID can
+ // still be registered.
+ def state1 = new AbstractAppState() {};
+ def state2 = new AbstractAppState() {};
+
+ def app = new LegacyApplication();
+
+ app.getStateManager().attach(state1);
+ app.getStateManager().attach(state2);
+ }
+ }
+
+ static class GetStateWithIdTest extends GroovyTestCase {
+ void testIdHit() {
+ def state = new AbstractAppState("test1") {};
+ def app = new LegacyApplication();
+
+ app.stateManager.attach(state);
+
+ assertNotNull app.stateManager.getState("test1", AppState.class);
+ }
+
+ void testIdMiss() {
+ def state = new AbstractAppState("test1") {};
+ def app = new LegacyApplication();
+
+ app.stateManager.attach(state);
+
+ assertNull app.stateManager.getState("test2", AppState.class);
+ }
+
+ void testDetached() {
+ def state = new AbstractAppState("test1") {};
+ def app = new LegacyApplication();
+
+ app.stateManager.attach(state);
+ app.stateManager.detach(state);
+
+ assertNull app.stateManager.getState("test2", AppState.class);
+ }
+ }
+
+ static class StateForIdTest extends GroovyTestCase {
+ void testIdHit() {
+ def state = new AbstractAppState("test1") {};
+ def app = new LegacyApplication();
+
+ app.stateManager.attach(state);
+
+ assertNotNull app.stateManager.stateForId("test1", AppState.class);
+ }
+
+ void testIdMiss() {
+ def state = new AbstractAppState("test1") {};
+ def app = new LegacyApplication();
+
+ app.stateManager.attach(state);
+
+ shouldFail(IllegalArgumentException) {
+ app.stateManager.stateForId("test2", AppState.class);
+ }
+ }
+
+ void testDetached() {
+ def state = new AbstractAppState("test1") {};
+ def app = new LegacyApplication();
+
+ app.stateManager.attach(state);
+ app.stateManager.detach(state);
+
+ shouldFail(IllegalArgumentException) {
+ app.stateManager.stateForId("test2", AppState.class);
+ }
+ }
+ }
+}
diff --git a/jme3-core/src/test/java/com/jme3/asset/LoadShaderSourceTest.java b/jme3-core/src/test/java/com/jme3/asset/LoadShaderSourceTest.java
index 0007bca2c6..e4f3e57a8b 100644
--- a/jme3-core/src/test/java/com/jme3/asset/LoadShaderSourceTest.java
+++ b/jme3-core/src/test/java/com/jme3/asset/LoadShaderSourceTest.java
@@ -46,6 +46,7 @@ public void testLoadShaderSource() {
assetManager.registerLocator(null, ClasspathLocator.class);
assetManager.registerLoader(GLSLLoader.class, "frag");
assetManager.registerLoader(GLSLLoader.class, "glsllib");
+ assetManager.registerLoader(GLSLLoader.class, "glsl");
String showNormals = (String) assetManager.loadAsset("Common/MatDefs/Misc/ShowNormals.frag");
System.out.println(showNormals);
}
diff --git a/jme3-core/src/test/java/com/jme3/material/MaterialTest.java b/jme3-core/src/test/java/com/jme3/material/MaterialTest.java
index 05a9ef3781..17aea47755 100644
--- a/jme3-core/src/test/java/com/jme3/material/MaterialTest.java
+++ b/jme3-core/src/test/java/com/jme3/material/MaterialTest.java
@@ -36,8 +36,15 @@
import com.jme3.renderer.RenderManager;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Box;
+import com.jme3.shader.VarType;
import com.jme3.system.NullRenderer;
import com.jme3.system.TestUtil;
+import com.jme3.texture.Image;
+import com.jme3.texture.Texture2D;
+import com.jme3.texture.Image.Format;
+import com.jme3.texture.image.ColorSpace;
+import com.jme3.util.BufferUtils;
+
import java.util.Arrays;
import java.util.EnumSet;
import static org.junit.Assert.*;
@@ -120,6 +127,30 @@ public void testSelectNamedTechnique_GLSL150Cap() {
checkRequiredCaps(Caps.GLSL150);
}
+ @Test
+ public void testForcedColorSpace(){
+
+ Image img=new Image(Format.RGBA8,2,2,BufferUtils.createByteBuffer(16),null,ColorSpace.sRGB);
+ Image img2=new Image(Format.RGBA8,2,2,BufferUtils.createByteBuffer(16),null,ColorSpace.sRGB);
+ Texture2D tx=new Texture2D(img);
+ Texture2D tx2=new Texture2D(img2);
+
+ assertTrue(tx2.getImage().getColorSpace()==ColorSpace.sRGB);
+ assertTrue(tx2.getImage().getColorSpace()==ColorSpace.sRGB);
+
+ AssetManager assetManager = TestUtil.createAssetManager();
+ MaterialDef def=new MaterialDef(assetManager,"test");
+ def.addMaterialParamTexture(VarType.Texture2D, "ColorMap",ColorSpace.Linear, null);
+ Material mat=new Material(def);
+
+ mat.setTexture("ColorMap",tx);
+ assertTrue(tx.getImage().getColorSpace()==ColorSpace.Linear);
+
+ mat.setTexture("ColorMap",tx2);
+ assertTrue(tx2.getImage().getColorSpace()==ColorSpace.Linear);
+
+ }
+
@Test
public void testSelectNamedTechnique_GLSL100Cap() {
supportGlsl(100);
diff --git a/jme3-core/src/test/java/com/jme3/scene/shape/ShapeBoundsTest.java b/jme3-core/src/test/java/com/jme3/scene/shape/ShapeBoundsTest.java
new file mode 100644
index 0000000000..b87d618d8f
--- /dev/null
+++ b/jme3-core/src/test/java/com/jme3/scene/shape/ShapeBoundsTest.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2009-2019 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.scene.shape;
+
+import com.jme3.bounding.BoundingBox;
+import com.jme3.bounding.BoundingSphere;
+import com.jme3.bounding.BoundingVolume;
+import com.jme3.math.Vector3f;
+import com.jme3.scene.Geometry;
+import com.jme3.scene.VertexBuffer;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Tests that all shapes have had a world bound calculated, and that vertices are within those bounds. Test
+ * added for issue #1121. This is a clear failure: BoundingBox [Center: (0.0, 0.0, 0.0) xExtent: 0.0 yExtent:
+ * 0.0 zExtent: 0.0]
+ *
+ * @author lou
+ */
+public class ShapeBoundsTest {
+
+ @Test
+ public void testBox() {
+ Box shape = new Box(2f, 3f, 0.8f);
+ Geometry geometry = new Geometry("geom", shape);
+ testBounds(geometry);
+ }
+
+ @Test
+ public void testCurve() {
+ Vector3f[] controlp = new Vector3f[4];
+ controlp[0] = new Vector3f(0, 0, 0);
+ controlp[1] = new Vector3f(1, 1, 1);
+ controlp[2] = new Vector3f(2, 1, 1);
+ controlp[3] = new Vector3f(3, 2, 1);
+ Curve shape = new Curve(controlp, 32);
+ Geometry geometry = new Geometry("geom", shape);
+ testBounds(geometry);
+ }
+
+ @Test
+ public void testCylinder() {
+ Cylinder shape = new Cylinder(16, 16, 2f, 3f);
+ Geometry geometry = new Geometry("geom", shape);
+ testBounds(geometry);
+ }
+
+ @Test
+ public void testDome() {
+ Dome shape = new Dome(16, 16, 5f);
+ Geometry geometry = new Geometry("geom", shape);
+ testBounds(geometry);
+ }
+
+ @Test
+ public void testLine() {
+ Line shape = new Line(new Vector3f(0, 0, 0), new Vector3f(1, 2, 3));
+ Geometry geometry = new Geometry("geom", shape);
+ testBounds(geometry);
+ }
+
+ @Test
+ public void testPqTorus() {
+ PQTorus shape = new PQTorus(2f, 3f, 0.8f, 0.2f, 64, 16);
+ Geometry geometry = new Geometry("geom", shape);
+ testBounds(geometry);
+ }
+
+ @Test
+ public void testQuad() {
+ Quad shape = new Quad(64, 16);
+ Geometry geometry = new Geometry("geom", shape);
+ BoundingVolume bv = geometry.getWorldBound();
+ BoundingBox bb = (BoundingBox) bv;
+ //Quad z extent 0 is normal, so not using testBounds() here.
+ Assert.assertTrue(bb.getXExtent() > 0 && bb.getYExtent() > 0);
+ testVertices(geometry);
+ }
+
+ @Test
+ public void Sphere() {
+ Sphere shape = new Sphere(32, 32, 5f);
+ Geometry geometry = new Geometry("geom", shape);
+ testBounds(geometry);
+ }
+
+ @Test
+ public void StripBox() {
+ StripBox shape = new StripBox(0.2f, 64f, 16f);
+ Geometry geometry = new Geometry("geom", shape);
+ testBounds(geometry);
+ }
+
+ @Test
+ public void Torus() {
+ Torus shape = new Torus(32, 32, 2f, 3f);
+ Geometry geometry = new Geometry("geom", shape);
+ testBounds(geometry);
+ }
+
+ private void testBounds(Geometry geometry) {
+ BoundingVolume bv = geometry.getWorldBound();
+
+ if (bv instanceof BoundingBox) {
+ BoundingBox bb = (BoundingBox) bv;
+ Assert.assertTrue(bb.getXExtent() > 0 && bb.getYExtent() > 0 && bb.getZExtent() > 0);
+ } else if (bv instanceof BoundingSphere) {
+ BoundingSphere bs = (BoundingSphere) bv;
+ Assert.assertTrue(bs.getRadius() > 1f);
+ }
+
+ testVertices(geometry);
+ }
+
+ private void testVertices(Geometry geometry) {
+ BoundingVolume bv = geometry.getWorldBound();
+ Assert.assertNotNull(bv);
+
+ for (int e = 0; e < geometry.getVertexCount(); e++) {
+ float x = (Float) geometry.getMesh().getBuffer(VertexBuffer.Type.Position).getElementComponent(e, 0);
+ float y = (Float) geometry.getMesh().getBuffer(VertexBuffer.Type.Position).getElementComponent(e, 1);
+ float z = (Float) geometry.getMesh().getBuffer(VertexBuffer.Type.Position).getElementComponent(e, 2);
+ Vector3f vertex = new Vector3f(x, y, z);
+ Assert.assertTrue("Vertex outside world bound: " + vertex, bv.intersects(vertex));
+ }
+ }
+}
diff --git a/jme3-core/src/tools/java/jme3tools/shadercheck/ShaderCheck.java b/jme3-core/src/tools/java/jme3tools/shadercheck/ShaderCheck.java
index 98d379b38a..ad4bf1dd18 100644
--- a/jme3-core/src/tools/java/jme3tools/shadercheck/ShaderCheck.java
+++ b/jme3-core/src/tools/java/jme3tools/shadercheck/ShaderCheck.java
@@ -31,7 +31,7 @@ private static void initAssetManager(){
assetManager.registerLocator("/", ClasspathLocator.class);
assetManager.registerLoader(J3MLoader.class, "j3m");
assetManager.registerLoader(J3MLoader.class, "j3md");
- assetManager.registerLoader(GLSLLoader.class, "vert", "frag","geom","tsctrl","tseval","glsllib");
+ assetManager.registerLoader(GLSLLoader.class, "vert", "frag","geom","tsctrl","tseval","glsllib","glsl");
}
private static void checkMatDef(String matdefName) {
diff --git a/jme3-desktop/src/main/java/com/jme3/system/AWTContext.java b/jme3-desktop/src/main/java/com/jme3/system/AWTContext.java
index 78cde8f744..d72ee71c82 100644
--- a/jme3-desktop/src/main/java/com/jme3/system/AWTContext.java
+++ b/jme3-desktop/src/main/java/com/jme3/system/AWTContext.java
@@ -126,7 +126,7 @@ public void setWidth(final int width) {
*/
protected AppSettings createSettings() {
final AppSettings settings = new AppSettings(true);
- settings.setRenderer(AppSettings.LWJGL_OPENGL3);
+ settings.setRenderer(AppSettings.LWJGL_OPENGL32);
return settings;
}
@@ -145,7 +145,7 @@ public Type getType() {
@Override
public void setSettings(AppSettings settings) {
this.settings.copyFrom(settings);
- this.settings.setRenderer(AppSettings.LWJGL_OPENGL3);
+ this.settings.setRenderer(AppSettings.LWJGL_OPENGL32);
this.backgroundContext.setSettings(settings);
}
diff --git a/jme3-desktop/src/main/java/com/jme3/system/NativeLibraryLoader.java b/jme3-desktop/src/main/java/com/jme3/system/NativeLibraryLoader.java
index 707937e78a..1cba8bcf28 100644
--- a/jme3-desktop/src/main/java/com/jme3/system/NativeLibraryLoader.java
+++ b/jme3-desktop/src/main/java/com/jme3/system/NativeLibraryLoader.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009-2012 jMonkeyEngine
+ * Copyright (c) 2009-2019 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -175,6 +175,8 @@ public static void registerNativeLibrary(String name, Platform platform,
registerNativeLibrary("bulletjme", Platform.Windows64, "native/windows/x86_64/bulletjme.dll");
registerNativeLibrary("bulletjme", Platform.Linux32, "native/linux/x86/libbulletjme.so");
registerNativeLibrary("bulletjme", Platform.Linux64, "native/linux/x86_64/libbulletjme.so");
+ registerNativeLibrary("bulletjme", Platform.Linux_ARM32, "native/linux/arm32/libbulletjme.so");
+ registerNativeLibrary("bulletjme", Platform.Linux_ARM64, "native/linux/arm64/libbulletjme.so");
registerNativeLibrary("bulletjme", Platform.MacOSX32, "native/osx/x86/libbulletjme.dylib");
registerNativeLibrary("bulletjme", Platform.MacOSX64, "native/osx/x86_64/libbulletjme.dylib");
@@ -624,8 +626,8 @@ public static void loadNativeLibrary(String name, boolean isRequired) {
in = conn.getInputStream();
} catch (IOException ex) {
// Maybe put more detail here? Not sure..
- throw new UnsatisfiedLinkError("Failed to open file: '" + url +
- "'. Error: " + ex);
+ throw new UncheckedIOException("Failed to open file: '" + url +
+ "'. Error: " + ex, ex);
}
File targetFile = new File(extactionDirectory, loadedAsFileName);
@@ -665,8 +667,8 @@ public static void loadNativeLibrary(String name, boolean isRequired) {
if (ex.getMessage().contains("used by another process")) {
return;
} else {
- throw new UnsatisfiedLinkError("Failed to extract native "
- + "library to: " + targetFile);
+ throw new UncheckedIOException("Failed to extract native "
+ + "library to: " + targetFile, ex);
}
} finally {
// XXX: HACK. Vary loading method based on library name..
diff --git a/jme3-effects/src/main/java/com/jme3/post/filters/CrossHatchFilter.java b/jme3-effects/src/main/java/com/jme3/post/filters/CrossHatchFilter.java
index 4f50e7dd13..9e94513556 100644
--- a/jme3-effects/src/main/java/com/jme3/post/filters/CrossHatchFilter.java
+++ b/jme3-effects/src/main/java/com/jme3/post/filters/CrossHatchFilter.java
@@ -157,7 +157,7 @@ public void setColorInfluencePaper(float colorInfluencePaper) {
}
/**
- * Sets line/paper color ratio for areas with values < luminance5,
+ * Sets line/paper color ratio for areas with values less than luminance5,
* really dark areas get no lines but a filled blob instead
* @param fillValue
*/
diff --git a/jme3-effects/src/main/java/com/jme3/water/SimpleWaterProcessor.java b/jme3-effects/src/main/java/com/jme3/water/SimpleWaterProcessor.java
index a628514ceb..677cc6d20a 100644
--- a/jme3-effects/src/main/java/com/jme3/water/SimpleWaterProcessor.java
+++ b/jme3-effects/src/main/java/com/jme3/water/SimpleWaterProcessor.java
@@ -81,7 +81,7 @@
* //attaching the water to the root node
* rootNode.attachChild(water);
*
- * @author Normen Hansen & Rémy Bouquet
+ * @author Normen Hansen and Rémy Bouquet
*/
public class SimpleWaterProcessor implements SceneProcessor {
diff --git a/jme3-effects/src/main/resources/Common/MatDefs/Post/FXAA.j3md b/jme3-effects/src/main/resources/Common/MatDefs/Post/FXAA.j3md
index 68f329892b..2debc760c7 100644
--- a/jme3-effects/src/main/resources/Common/MatDefs/Post/FXAA.j3md
+++ b/jme3-effects/src/main/resources/Common/MatDefs/Post/FXAA.j3md
@@ -8,10 +8,10 @@ MaterialDef FXAA {
Float ReduceMul
}
Technique {
- VertexShader GLSL100 GLSL150: Common/MatDefs/Post/FXAA.vert
- FragmentShader GLSL100 GLSL150: Common/MatDefs/Post/FXAA.frag
+ VertexShader GLSL300 GLSL100 GLSL150: Common/MatDefs/Post/FXAA.vert
+ FragmentShader GLSL300 GLSL100 GLSL150: Common/MatDefs/Post/FXAA.frag
WorldParameters {
ResolutionInverse
}
}
-}
\ No newline at end of file
+}
diff --git a/jme3-effects/src/main/resources/Common/MatDefs/Post/LightScattering.j3md b/jme3-effects/src/main/resources/Common/MatDefs/Post/LightScattering.j3md
index 613955536b..590dbdc051 100644
--- a/jme3-effects/src/main/resources/Common/MatDefs/Post/LightScattering.j3md
+++ b/jme3-effects/src/main/resources/Common/MatDefs/Post/LightScattering.j3md
@@ -14,8 +14,8 @@ MaterialDef Light Scattering {
}
Technique {
- VertexShader GLSL150 GLSL120: Common/MatDefs/Post/Post.vert
- FragmentShader GLSL150 GLSL120: Common/MatDefs/Post/LightScattering.frag
+ VertexShader GLSL300 GLSL150 GLSL120: Common/MatDefs/Post/Post.vert
+ FragmentShader GLSL300 GLSL150 GLSL120: Common/MatDefs/Post/LightScattering.frag
WorldParameters {
}
@@ -26,4 +26,4 @@ MaterialDef Light Scattering {
DISPLAY: Display
}
}
-}
\ No newline at end of file
+}
diff --git a/jme3-effects/src/main/resources/Common/MatDefs/SSAO/ssao.j3md b/jme3-effects/src/main/resources/Common/MatDefs/SSAO/ssao.j3md
index 6cf780e1f1..0f5b5433e7 100644
--- a/jme3-effects/src/main/resources/Common/MatDefs/SSAO/ssao.j3md
+++ b/jme3-effects/src/main/resources/Common/MatDefs/SSAO/ssao.j3md
@@ -18,8 +18,8 @@ MaterialDef SSAO {
}
Technique {
- VertexShader GLSL150 GLSL120: Common/MatDefs/Post/Post.vert
- FragmentShader GLSL150 GLSL120: Common/MatDefs/SSAO/ssao.frag
+ VertexShader GLSL300 GLSL150 GLSL120: Common/MatDefs/Post/Post.vert
+ FragmentShader GLSL300 GLSL150 GLSL120: Common/MatDefs/SSAO/ssao.frag
WorldParameters {
WorldViewMatrix
@@ -34,4 +34,4 @@ MaterialDef SSAO {
}
}
-}
\ No newline at end of file
+}
diff --git a/jme3-effects/src/main/resources/Common/MatDefs/SSAO/ssaoBlur.frag b/jme3-effects/src/main/resources/Common/MatDefs/SSAO/ssaoBlur.frag
index ef6b278ec5..aaa7bd8acb 100644
--- a/jme3-effects/src/main/resources/Common/MatDefs/SSAO/ssaoBlur.frag
+++ b/jme3-effects/src/main/resources/Common/MatDefs/SSAO/ssaoBlur.frag
@@ -32,77 +32,77 @@ vec4 convolutionFilter(){
float zsum = 1.0;
float Zp =readDepth(texCoord);
- vec2 sample = vec2(x - 2.0 * xScale, y - 2.0 * yScale);
- float zTmp = readDepth(sample);
+ vec2 samplePos = vec2(x - 2.0 * xScale, y - 2.0 * yScale);
+ float zTmp = readDepth(samplePos);
float coefZ = 1.0 / (epsilon + abs(Zp - zTmp));
zsum += coefZ;
- sum += coefZ* texture2D( m_SSAOMap, sample);
+ sum += coefZ* texture2D( m_SSAOMap, samplePos);
- sample = vec2(x - 0.0 * xScale, y - 2.0 * yScale);
- zTmp =readDepth(sample);
+ samplePos = vec2(x - 0.0 * xScale, y - 2.0 * yScale);
+ zTmp =readDepth(samplePos);
coefZ = 1.0 / (epsilon + abs(Zp - zTmp));
zsum += coefZ;
- sum += coefZ* texture2D( m_SSAOMap, sample);
+ sum += coefZ* texture2D( m_SSAOMap, samplePos);
- sample = vec2(x + 2.0 * xScale, y - 2.0 * yScale);
- zTmp =readDepth(sample);
+ samplePos = vec2(x + 2.0 * xScale, y - 2.0 * yScale);
+ zTmp =readDepth(samplePos);
coefZ = 1.0 / (epsilon + abs(Zp - zTmp));
zsum += coefZ;
- sum += coefZ* texture2D( m_SSAOMap, sample);
+ sum += coefZ* texture2D( m_SSAOMap, samplePos);
- sample = vec2(x - 1.0 * xScale, y - 1.0 * yScale);
- zTmp =readDepth(sample);
+ samplePos = vec2(x - 1.0 * xScale, y - 1.0 * yScale);
+ zTmp =readDepth(samplePos);
coefZ = 1.0 / (epsilon + abs(Zp - zTmp));
zsum += coefZ;
- sum += coefZ* texture2D( m_SSAOMap, sample);
+ sum += coefZ* texture2D( m_SSAOMap, samplePos);
- sample = vec2(x + 1.0 * xScale, y - 1.0 * yScale);
- zTmp =readDepth(sample);
+ samplePos = vec2(x + 1.0 * xScale, y - 1.0 * yScale);
+ zTmp =readDepth(samplePos);
coefZ = 1.0 / (epsilon + abs(Zp - zTmp));
zsum += coefZ;
- sum += coefZ* texture2D( m_SSAOMap, sample);
+ sum += coefZ* texture2D( m_SSAOMap, samplePos);
- sample = vec2(x - 2.0 * xScale, y - 0.0 * yScale);
- zTmp =readDepth(sample);
+ samplePos = vec2(x - 2.0 * xScale, y - 0.0 * yScale);
+ zTmp =readDepth(samplePos);
coefZ = 1.0 / (epsilon + abs(Zp - zTmp));
zsum += coefZ;
- sum += coefZ* texture2D( m_SSAOMap, sample);
+ sum += coefZ* texture2D( m_SSAOMap, samplePos);
- sample = vec2(x + 2.0 * xScale, y - 0.0 * yScale);
- zTmp =readDepth(sample);
+ samplePos = vec2(x + 2.0 * xScale, y - 0.0 * yScale);
+ zTmp =readDepth(samplePos);
coefZ = 1.0 / (epsilon + abs(Zp - zTmp));
zsum += coefZ;
- sum += coefZ* texture2D( m_SSAOMap, sample);
+ sum += coefZ* texture2D( m_SSAOMap, samplePos);
- sample = vec2(x - 1.0 * xScale, y + 1.0 * yScale);
- zTmp =readDepth(sample);
+ samplePos = vec2(x - 1.0 * xScale, y + 1.0 * yScale);
+ zTmp =readDepth(samplePos);
coefZ = 1.0 / (epsilon + abs(Zp - zTmp));
zsum += coefZ;
- sum += coefZ* texture2D( m_SSAOMap, sample);
+ sum += coefZ* texture2D( m_SSAOMap, samplePos);
- sample = vec2(x + 1.0 * xScale, y + 1.0 * yScale);
- zTmp =readDepth(sample);
+ samplePos = vec2(x + 1.0 * xScale, y + 1.0 * yScale);
+ zTmp =readDepth(samplePos);
coefZ = 1.0 / (epsilon + abs(Zp - zTmp));
zsum += coefZ;
- sum += coefZ* texture2D( m_SSAOMap, sample);
+ sum += coefZ* texture2D( m_SSAOMap, samplePos);
- sample = vec2(x - 2.0 * xScale, y + 2.0 * yScale);
- zTmp =readDepth(sample);
+ samplePos = vec2(x - 2.0 * xScale, y + 2.0 * yScale);
+ zTmp =readDepth(samplePos);
coefZ = 1.0 / (epsilon + abs(Zp - zTmp));
zsum += coefZ;
- sum += coefZ* texture2D( m_SSAOMap, sample);
+ sum += coefZ* texture2D( m_SSAOMap, samplePos);
- sample = vec2(x - 0.0 * xScale, y + 2.0 * yScale);
- zTmp =readDepth(sample);
+ samplePos = vec2(x - 0.0 * xScale, y + 2.0 * yScale);
+ zTmp =readDepth(samplePos);
coefZ = 1.0 / (epsilon + abs(Zp - zTmp));
zsum += coefZ;
- sum += coefZ* texture2D( m_SSAOMap, sample);
+ sum += coefZ* texture2D( m_SSAOMap, samplePos);
- sample = vec2(x + 2.0 * xScale, y + 2.0 * yScale);
- zTmp =readDepth(sample);
+ samplePos = vec2(x + 2.0 * xScale, y + 2.0 * yScale);
+ zTmp =readDepth(samplePos);
coefZ = 1.0 / (epsilon + abs(Zp - zTmp));
zsum += coefZ;
- sum += coefZ* texture2D( m_SSAOMap, sample);
+ sum += coefZ* texture2D( m_SSAOMap, samplePos);
return sum / zsum;
@@ -124,4 +124,4 @@ vec4 getColor(vec4 color){
void main(){
gl_FragColor = getColor(convolutionFilter());
-}
\ No newline at end of file
+}
diff --git a/jme3-effects/src/main/resources/Common/MatDefs/SSAO/ssaoBlur.j3md b/jme3-effects/src/main/resources/Common/MatDefs/SSAO/ssaoBlur.j3md
index f5a1892cab..2314876d6d 100644
--- a/jme3-effects/src/main/resources/Common/MatDefs/SSAO/ssaoBlur.j3md
+++ b/jme3-effects/src/main/resources/Common/MatDefs/SSAO/ssaoBlur.j3md
@@ -14,8 +14,8 @@ MaterialDef SSAOBlur {
}
Technique {
- VertexShader GLSL150 GLSL120: Common/MatDefs/Post/Post.vert
- FragmentShader GLSL150 GLSL120: Common/MatDefs/SSAO/ssaoBlur.frag
+ VertexShader GLSL300 GLSL150 GLSL120: Common/MatDefs/Post/Post.vert
+ FragmentShader GLSL300 GLSL150 GLSL120: Common/MatDefs/SSAO/ssaoBlur.frag
WorldParameters {
WorldViewMatrix
@@ -28,4 +28,4 @@ MaterialDef SSAOBlur {
RESOLVE_DEPTH_MS : NumSamplesDepth
}
}
-}
\ No newline at end of file
+}
diff --git a/jme3-effects/src/main/resources/Common/MatDefs/Water/Textures/water_normalmap.dds b/jme3-effects/src/main/resources/Common/MatDefs/Water/Textures/water_normalmap.dds
index 13582e148c..529b8327b4 100644
Binary files a/jme3-effects/src/main/resources/Common/MatDefs/Water/Textures/water_normalmap.dds and b/jme3-effects/src/main/resources/Common/MatDefs/Water/Textures/water_normalmap.dds differ
diff --git a/jme3-effects/src/main/resources/Common/MatDefs/Water/Water.frag b/jme3-effects/src/main/resources/Common/MatDefs/Water/Water.frag
index c52a8d6921..d97e23dcb0 100644
--- a/jme3-effects/src/main/resources/Common/MatDefs/Water/Water.frag
+++ b/jme3-effects/src/main/resources/Common/MatDefs/Water/Water.frag
@@ -48,9 +48,8 @@ uniform vec3 m_Center;
uniform float m_Radius;
#endif
-
-vec2 scale = vec2(m_WaveScale, m_WaveScale);
-float refractionScale = m_WaveScale;
+vec2 scale; // = vec2(m_WaveScale, m_WaveScale);
+float refractionScale; // = m_WaveScale;
// Modifies 4 sampled normals. Increase first values to have more
// smaller "waves" or last to have more bigger "waves"
@@ -62,8 +61,18 @@ const float visibility = 3.0;
// foam intensity
uniform float m_FoamIntensity ;
+vec2 m_FrustumNearFar; //=vec2(1.0,m_UnderWaterFogDistance);
+const float LOG2 = 1.442695;
+
+
varying vec2 texCoord;
+void setGlobals(){
+scale = vec2(m_WaveScale, m_WaveScale);
+refractionScale = m_WaveScale;
+m_FrustumNearFar=vec2(1.0,m_UnderWaterFogDistance);
+}
+
mat3 MatrixInverse(in mat3 inMatrix){
float det = dot(cross(inMatrix[0], inMatrix[1]), inMatrix[2]);
mat3 T = transpose(inMatrix);
@@ -119,9 +128,6 @@ float fresnelTerm(in vec3 normal,in vec3 eyeVec){
return saturate(fresnel * (1.0 - saturate(m_R0)) + m_R0 - m_RefractionStrength);
}
-vec2 m_FrustumNearFar=vec2(1.0,m_UnderWaterFogDistance);
-const float LOG2 = 1.442695;
-
vec4 underWater(int sampleNum){
@@ -225,7 +231,7 @@ vec4 underWater(int sampleNum){
#endif
float fogDepth= (2.0 * m_FrustumNearFar.x) / (m_FrustumNearFar.y + m_FrustumNearFar.x - sceneDepth* (m_FrustumNearFar.y-m_FrustumNearFar.x));
- float fogIntensity= 18 * m_WaterTransparency;
+ float fogIntensity= 18.0 * m_WaterTransparency;
fogFactor = exp2( -fogIntensity * fogIntensity * fogDepth * fogDepth * LOG2 );
fogFactor = clamp(fogFactor, 0.0, 1.0);
color =mix(m_DeepWaterColor.rgb,color,fogFactor);
@@ -284,7 +290,7 @@ vec4 main_multiSample(int sampleNum){
samples = 10;
#endif
- float biasFactor = 1.0 / samples;
+ float biasFactor = 1.0 / float(samples);
for (int i = 0; i < samples; i++){
texC = (surfacePoint.xz + eyeVecNorm.xz * biasFactor) * scale + m_Time * 0.03 * m_WindDirection;
@@ -344,7 +350,7 @@ vec4 main_multiSample(int sampleNum){
normal = normalize(normal0a * normalModifier.x + normal1a * normalModifier.y +normal2a * normalModifier.z + normal3a * normalModifier.w);
- #if __VERSION__ >= 130
+ #if __VERSION__ >= 130 && !defined GL_ES
// XXX: Here's another way to fix the terrain edge issue,
// But it requires GLSL 1.3 and still looks kinda incorrect
// around edges
@@ -435,13 +441,14 @@ vec4 main_multiSample(int sampleNum){
}
void main(){
+ setGlobals();
#ifdef RESOLVE_MS
vec4 color = vec4(0.0);
for (int i = 0; i < m_NumSamples; i++){
color += main_multiSample(i);
}
- gl_FragColor = color / m_NumSamples;
+ gl_FragColor = color / float(m_NumSamples);
#else
gl_FragColor = main_multiSample(0);
#endif
-}
\ No newline at end of file
+}
diff --git a/jme3-effects/src/main/resources/Common/MatDefs/Water/Water.j3md b/jme3-effects/src/main/resources/Common/MatDefs/Water/Water.j3md
index b75bd2c45f..49c5a06e53 100644
--- a/jme3-effects/src/main/resources/Common/MatDefs/Water/Water.j3md
+++ b/jme3-effects/src/main/resources/Common/MatDefs/Water/Water.j3md
@@ -51,8 +51,8 @@ MaterialDef Advanced Water {
}
Technique {
- VertexShader GLSL150 GLSL120 : Common/MatDefs/Post/Post.vert
- FragmentShader GLSL150 GLSL120: Common/MatDefs/Water/Water.frag
+ VertexShader GLSL310 GLSL300 GLSL150 GLSL120 : Common/MatDefs/Post/Post.vert
+ FragmentShader GLSL310 GLSL300 GLSL150 GLSL120: Common/MatDefs/Water/Water.frag
WorldParameters {
ViewProjectionMatrixInverse
@@ -72,4 +72,4 @@ MaterialDef Advanced Water {
}
}
-}
\ No newline at end of file
+}
diff --git a/jme3-examples/build.gradle b/jme3-examples/build.gradle
index 08e2a8dadd..7989235c48 100644
--- a/jme3-examples/build.gradle
+++ b/jme3-examples/build.gradle
@@ -22,9 +22,12 @@ dependencies {
compile project(':jme3-core')
compile project(':jme3-desktop')
compile project(':jme3-effects')
-// compile project(':jme3-bullet')
-// compile project(':jme3-bullet-native')
- compile project(':jme3-jbullet')
+
+ // EITHER use jme3-bullet + jme3-bullet-native OR ELSE jme3-jbullet
+ compile project(':jme3-bullet')
+ compile project(':jme3-bullet-native')
+// compile project(':jme3-jbullet')
+
compile project(':jme3-jogg')
compile project(':jme3-jogl')
compile project(':jme3-lwjgl')
diff --git a/jme3-examples/src/main/java/jme3test/animation/TestIssue1138.java b/jme3-examples/src/main/java/jme3test/animation/TestIssue1138.java
new file mode 100644
index 0000000000..ac390aaf51
--- /dev/null
+++ b/jme3-examples/src/main/java/jme3test/animation/TestIssue1138.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2019 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 jme3test.animation;
+
+import com.jme3.anim.AnimComposer;
+import com.jme3.anim.Joint;
+import com.jme3.anim.SkinningControl;
+import com.jme3.app.SimpleApplication;
+import com.jme3.light.AmbientLight;
+import com.jme3.math.Vector3f;
+import com.jme3.scene.Node;
+
+/**
+ * Test case for JME issue #1138: Elephant's legUp animation sets Joint
+ * translation to NaN.
+ *
+ * If successful, the animation cycle will complete without throwing an
+ * IllegalStateException.
+ *
+ * @author Stephen Gold
+ */
+public class TestIssue1138 extends SimpleApplication {
+
+ SkinningControl sControl;
+
+ public static void main(String... argv) {
+ new TestIssue1138().start();
+ }
+
+ @Override
+ public void simpleInitApp() {
+ Node cgModel = (Node) assetManager.loadModel(
+ "Models/Elephant/Elephant.mesh.xml");
+ rootNode.attachChild(cgModel);
+ cgModel.rotate(0f, -1f, 0f);
+ cgModel.scale(0.04f);
+
+ AnimComposer composer = cgModel.getControl(AnimComposer.class);
+ composer.setCurrentAction("legUp");
+ sControl = cgModel.getControl(SkinningControl.class);
+
+ AmbientLight light = new AmbientLight();
+ rootNode.addLight(light);
+ }
+
+ @Override
+ public void simpleUpdate(float tpf) {
+ for (Joint joint : sControl.getArmature().getJointList()) {
+ Vector3f translation = joint.getLocalTranslation();
+ if (!Vector3f.isValidVector(translation)) {
+ String msg = "Invalid translation for joint " + joint.getName();
+ throw new IllegalStateException(msg);
+ }
+ }
+ }
+}
diff --git a/jme3-examples/src/main/java/jme3test/app/TestAppStateLifeCycle.java b/jme3-examples/src/main/java/jme3test/app/TestAppStateLifeCycle.java
index b6517c9d2b..3bbc316b4e 100644
--- a/jme3-examples/src/main/java/jme3test/app/TestAppStateLifeCycle.java
+++ b/jme3-examples/src/main/java/jme3test/app/TestAppStateLifeCycle.java
@@ -64,7 +64,10 @@ public void simpleInitApp() {
rootNode.attachChild(geom);
System.out.println("Attaching test state.");
- stateManager.attach(new TestState());
+ stateManager.attach(new TestState());
+
+ System.out.println("Attaching test state with an ID.");
+ stateManager.attach(new TestState("Test ID"));
}
@Override
@@ -74,51 +77,64 @@ public void simpleUpdate(float tpf) {
System.out.println("Detaching test state.");
stateManager.detach(stateManager.getState(TestState.class));
System.out.println("Done");
- }
+ }
+
+ if( stateManager.hasState("Test ID") ) {
+ System.out.println("Detaching test state with an ID.");
+ stateManager.detach(stateManager.getState("Test ID", TestState.class));
+ System.out.println("Done");
+ }
}
public class TestState extends AbstractAppState {
+ public TestState() {
+ }
+
+ public TestState( String id ) {
+ super(id);
+ }
+
@Override
public void initialize(AppStateManager stateManager, Application app) {
super.initialize(stateManager, app);
- System.out.println("Initialized");
+ System.out.println("Initialized, id:" + getId());
}
@Override
public void stateAttached(AppStateManager stateManager) {
super.stateAttached(stateManager);
- System.out.println("Attached");
+ System.out.println("Attached, id:" + getId());
}
@Override
public void update(float tpf) {
super.update(tpf);
- System.out.println("update");
+ System.out.println("update, id:" + getId());
}
@Override
public void render(RenderManager rm) {
super.render(rm);
- System.out.println("render");
+ System.out.println("render, id:" + getId());
}
@Override
public void postRender() {
super.postRender();
- System.out.println("postRender");
+ System.out.println("postRender, id:" + getId());
}
@Override
public void stateDetached(AppStateManager stateManager) {
super.stateDetached(stateManager);
- System.out.println("Detached");
+ System.out.println("Detached, id:" + getId());
}
@Override
public void cleanup() {
super.cleanup();
- System.out.println("Cleanup");
+ System.out.println("Cleanup, id:" + getId());
}
}
diff --git a/jme3-examples/src/main/java/jme3test/bullet/PhysicsHoverControl.java b/jme3-examples/src/main/java/jme3test/bullet/PhysicsHoverControl.java
index f914f5da56..901b3433c3 100644
--- a/jme3-examples/src/main/java/jme3test/bullet/PhysicsHoverControl.java
+++ b/jme3-examples/src/main/java/jme3test/bullet/PhysicsHoverControl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009-2018 jMonkeyEngine
+ * Copyright (c) 2009-2019 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -146,6 +146,7 @@ public void prePhysicsTick(PhysicsSpace space, float f) {
Vector3f dir = getForwardVector(tempVect2).multLocal(1, 0, 1).normalizeLocal();
getLinearVelocity(tempVect3);
Vector3f linearVelocity = tempVect3.multLocal(1, 0, 1);
+ float groundSpeed = linearVelocity.length();
if (steeringValue != 0) {
if (rotationVelocity < 1 && rotationVelocity > -1) {
@@ -164,16 +165,18 @@ public void prePhysicsTick(PhysicsSpace space, float f) {
// if we are not going where we want to go.
// this will prevent "drifting" and thus improve control
// of the vehicle
- float d = dir.dot(linearVelocity.normalize());
- Vector3f counter = dir.project(linearVelocity).normalizeLocal().negateLocal().multLocal(1 - d);
- applyForce(counter.multLocal(mass * 10), Vector3f.ZERO);
+ if (groundSpeed > FastMath.ZERO_TOLERANCE) {
+ float d = dir.dot(linearVelocity.normalize());
+ Vector3f counter = dir.project(linearVelocity).normalizeLocal().negateLocal().multLocal(1 - d);
+ applyForce(counter.multLocal(mass * 10), Vector3f.ZERO);
+ }
if (linearVelocity.length() < 30) {
applyForce(dir.multLocal(accelerationValue), Vector3f.ZERO);
}
} else {
// counter the acceleration value
- if (linearVelocity.length() > FastMath.ZERO_TOLERANCE) {
+ if (groundSpeed > FastMath.ZERO_TOLERANCE) {
linearVelocity.normalizeLocal().negateLocal();
applyForce(linearVelocity.mult(mass * 10), Vector3f.ZERO);
}
diff --git a/jme3-examples/src/main/java/jme3test/bullet/PhysicsTestHelper.java b/jme3-examples/src/main/java/jme3test/bullet/PhysicsTestHelper.java
index c0fa6f0653..4d8a5a92f9 100644
--- a/jme3-examples/src/main/java/jme3test/bullet/PhysicsTestHelper.java
+++ b/jme3-examples/src/main/java/jme3test/bullet/PhysicsTestHelper.java
@@ -36,6 +36,7 @@
import com.jme3.asset.TextureKey;
import com.jme3.bullet.PhysicsSpace;
import com.jme3.bullet.collision.shapes.CollisionShape;
+import com.jme3.bullet.collision.shapes.GImpactCollisionShape;
import com.jme3.bullet.collision.shapes.MeshCollisionShape;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.input.MouseInput;
@@ -44,13 +45,18 @@
import com.jme3.light.AmbientLight;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
+import com.jme3.math.FastMath;
+import com.jme3.math.Vector3f;
import com.jme3.renderer.queue.RenderQueue.ShadowMode;
import com.jme3.scene.Geometry;
+import com.jme3.scene.Mesh;
import com.jme3.scene.Node;
+import com.jme3.scene.VertexBuffer;
import com.jme3.scene.shape.Box;
import com.jme3.scene.shape.Sphere;
import com.jme3.scene.shape.Sphere.TextureMode;
import com.jme3.texture.Texture;
+import com.jme3.util.BufferUtils;
/**
*
@@ -59,8 +65,7 @@
public class PhysicsTestHelper {
/**
- * creates a simple physics test world with a floor, an obstacle and some
- * test boxes
+ * creates a simple physics test world with a floor, an obstacle and some test boxes
*
* @param rootNode where lights and geometries should be added
* @param assetManager for loading assets
@@ -107,7 +112,7 @@ public static void createPhysicsTestWorld(Node rootNode, AssetManager assetManag
space.add(sphereGeometry);
}
-
+
public static void createPhysicsTestWorldSoccer(Node rootNode, AssetManager assetManager, PhysicsSpace space) {
AmbientLight light = new AmbientLight();
light.setColor(ColorRGBA.LightGray);
@@ -140,24 +145,24 @@ public static void createPhysicsTestWorldSoccer(Node rootNode, AssetManager asse
space.add(ballGeometry);
}
{
- //immovable Box with mesh collision shape
- Box box = new Box(1, 1, 1);
- Geometry boxGeometry = new Geometry("Box", box);
- boxGeometry.setMaterial(material);
- boxGeometry.setLocalTranslation(4, 1, 2);
- boxGeometry.addControl(new RigidBodyControl(new MeshCollisionShape(box), 0));
- rootNode.attachChild(boxGeometry);
- space.add(boxGeometry);
+ //immovable Box with mesh collision shape
+ Box box = new Box(1, 1, 1);
+ Geometry boxGeometry = new Geometry("Box", box);
+ boxGeometry.setMaterial(material);
+ boxGeometry.setLocalTranslation(4, 1, 2);
+ boxGeometry.addControl(new RigidBodyControl(new MeshCollisionShape(box), 0));
+ rootNode.attachChild(boxGeometry);
+ space.add(boxGeometry);
}
{
- //immovable Box with mesh collision shape
- Box box = new Box(1, 1, 1);
- Geometry boxGeometry = new Geometry("Box", box);
- boxGeometry.setMaterial(material);
- boxGeometry.setLocalTranslation(4, 3, 4);
- boxGeometry.addControl(new RigidBodyControl(new MeshCollisionShape(box), 0));
- rootNode.attachChild(boxGeometry);
- space.add(boxGeometry);
+ //immovable Box with mesh collision shape
+ Box box = new Box(1, 1, 1);
+ Geometry boxGeometry = new Geometry("Box", box);
+ boxGeometry.setMaterial(material);
+ boxGeometry.setLocalTranslation(4, 3, 4);
+ boxGeometry.addControl(new RigidBodyControl(new MeshCollisionShape(box), 0));
+ rootNode.attachChild(boxGeometry);
+ space.add(boxGeometry);
}
}
@@ -211,8 +216,7 @@ public static Node createPhysicsTestNode(AssetManager manager, CollisionShape sh
}
/**
- * creates the necessary inputlistener and action to shoot balls from the
- * camera
+ * creates the necessary inputlistener and action to shoot balls from the camera
*
* @param app the application that's running
* @param rootNode where ball geometries should be added
@@ -246,4 +250,116 @@ public void onAction(String name, boolean keyPressed, float tpf) {
app.getInputManager().addMapping("shoot", new MouseButtonTrigger(MouseInput.BUTTON_LEFT));
app.getInputManager().addListener(actionListener, "shoot");
}
+
+ /**
+ * Creates a curved "floor" with a GImpactCollisionShape provided as the RigidBodyControl's collision
+ * shape. Surface has four slightly concave corners to allow for multiple tests and minimize falling off
+ * the edge of the floor.
+ *
+ * @param assetManager for loading assets
+ * @param floorDimensions width/depth of the "floor" (X/Z)
+ * @param position sets the floor's local translation
+ * @return
+ */
+ public static Geometry createGImpactTestFloor(AssetManager assetManager, float floorDimensions, Vector3f position) {
+ Geometry floor = createTestFloor(assetManager, floorDimensions, position, ColorRGBA.Red);
+ RigidBodyControl floorControl = new RigidBodyControl(new GImpactCollisionShape(floor.getMesh()), 0);
+ floor.addControl(floorControl);
+ return floor;
+ }
+
+ /**
+ * Creates a curved "floor" with a MeshCollisionShape provided as the RigidBodyControl's collision shape.
+ * Surface has four slightly concave corners to allow for multiple tests and minimize falling off the edge
+ * of the floor.
+ *
+ * @param assetManager for loading assets
+ * @param floorDimensions width/depth of the "floor" (X/Z)
+ * @param position sets the floor's local translation
+ * @return
+ */
+ public static Geometry createMeshTestFloor(AssetManager assetManager, float floorDimensions, Vector3f position) {
+ Geometry floor = createTestFloor(assetManager, floorDimensions, position, new ColorRGBA(0.5f, 0.5f, 0.9f, 1));
+ RigidBodyControl floorControl = new RigidBodyControl(new MeshCollisionShape(floor.getMesh()), 0);
+ floor.addControl(floorControl);
+ return floor;
+ }
+
+ private static Geometry createTestFloor(AssetManager assetManager, float floorDimensions, Vector3f position, ColorRGBA color) {
+ Geometry floor = new Geometry("floor", createFloorMesh(20, floorDimensions));
+ Material material = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
+ material.getAdditionalRenderState().setWireframe(true);
+ material.setColor("Color", color);
+ floor.setMaterial(material);
+ floor.setLocalTranslation(position);
+ return floor;
+ }
+
+ private static Mesh createFloorMesh(int meshDetail, float floorDimensions) {
+ if (meshDetail < 10) {
+ meshDetail = 10;
+ }
+ int numVertices = meshDetail * meshDetail * 2 * 3;//width * depth * two tris * 3 verts per tri
+
+ int[] indexBuf = new int[numVertices];
+ int i = 0;
+ for (int x = 0; x < meshDetail; x++) {
+ for (int z = 0; z < meshDetail; z++) {
+ indexBuf[i] = i++;
+ indexBuf[i] = i++;
+ indexBuf[i] = i++;
+ indexBuf[i] = i++;
+ indexBuf[i] = i++;
+ indexBuf[i] = i++;
+ }
+ }
+
+ float[] vertBuf = new float[numVertices * 3];
+ float xIncrement = floorDimensions / meshDetail;
+ float zIncrement = floorDimensions / meshDetail;
+ int j = 0;
+ for (int x = 0; x < meshDetail; x++) {
+ float xPos = x * xIncrement;
+ for (int z = 0; z < meshDetail; z++) {
+ float zPos = z * zIncrement;
+ //First tri
+ vertBuf[j++] = xPos;
+ vertBuf[j++] = getY(xPos, zPos, floorDimensions);
+ vertBuf[j++] = zPos;
+ vertBuf[j++] = xPos;
+ vertBuf[j++] = getY(xPos, zPos + zIncrement, floorDimensions);
+ vertBuf[j++] = zPos + zIncrement;
+ vertBuf[j++] = xPos + xIncrement;
+ vertBuf[j++] = getY(xPos + xIncrement, zPos, floorDimensions);
+ vertBuf[j++] = zPos;
+ //Second tri
+ vertBuf[j++] = xPos;
+ vertBuf[j++] = getY(xPos, zPos + zIncrement, floorDimensions);
+ vertBuf[j++] = zPos + zIncrement;
+ vertBuf[j++] = xPos + xIncrement;
+ vertBuf[j++] = getY(xPos + xIncrement, zPos + zIncrement, floorDimensions);
+ vertBuf[j++] = zPos + zIncrement;
+ vertBuf[j++] = xPos + xIncrement;
+ vertBuf[j++] = getY(xPos + xIncrement, zPos, floorDimensions);
+ vertBuf[j++] = zPos;
+ }
+ }
+
+ Mesh m = new Mesh();
+ m.setBuffer(VertexBuffer.Type.Index, 1, BufferUtils.createIntBuffer(indexBuf));
+ m.setBuffer(VertexBuffer.Type.Position, 3, BufferUtils.createFloatBuffer(vertBuf));
+ m.updateBound();
+ return m;
+ }
+
+ private static float getY(float x, float z, float max) {
+ float yMaxHeight = 8;
+ float xv = FastMath.unInterpolateLinear(FastMath.abs(x - (max / 2)), 0, max) * FastMath.TWO_PI;
+ float zv = FastMath.unInterpolateLinear(FastMath.abs(z - (max / 2)), 0, max) * FastMath.TWO_PI;
+
+ float xComp = (FastMath.sin(xv) + 1) * 0.5f;
+ float zComp = (FastMath.sin(zv) + 1) * 0.5f;
+
+ return -yMaxHeight * xComp * zComp;
+ }
}
diff --git a/jme3-examples/src/main/java/jme3test/bullet/TestHoveringTank.java b/jme3-examples/src/main/java/jme3test/bullet/TestHoveringTank.java
index c247bfe854..922ce973b2 100644
--- a/jme3-examples/src/main/java/jme3test/bullet/TestHoveringTank.java
+++ b/jme3-examples/src/main/java/jme3test/bullet/TestHoveringTank.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009-2012 jMonkeyEngine
+ * Copyright (c) 2009-2019 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -80,6 +80,15 @@ public class TestHoveringTank extends SimpleApplication implements AnalogListene
PointLight pl;
Geometry lightMdl;
Geometry collisionMarker;
+ /**
+ * initial location of the tank (in world/physics-space coordinates)
+ */
+ final private Vector3f startLocation = new Vector3f(-140f, 50f, -23f);
+ /**
+ * initial orientation of the tank (in world/physics-space coordinates)
+ */
+ final private Quaternion startOrientation
+ = new Quaternion(new float[]{0f, 0.01f, 0f});
public static void main(String[] args) {
TestHoveringTank app = new TestHoveringTank();
@@ -143,8 +152,8 @@ private void buildPlayer() {
spaceCraft = assetManager.loadModel("Models/HoverTank/Tank2.mesh.xml");
CollisionShape colShape = CollisionShapeFactory.createDynamicMeshShape(spaceCraft);
spaceCraft.setShadowMode(ShadowMode.CastAndReceive);
- spaceCraft.setLocalTranslation(new Vector3f(-140, 50, -23));
- spaceCraft.setLocalRotation(new Quaternion(new float[]{0, 0.01f, 0}));
+ spaceCraft.setLocalTranslation(startLocation);
+ spaceCraft.setLocalRotation(startOrientation);
hoverControl = new PhysicsHoverControl(colShape, 500);
@@ -206,8 +215,10 @@ public void onAction(String binding, boolean value, float tpf) {
} else if (binding.equals("Reset")) {
if (value) {
System.out.println("Reset");
- hoverControl.setPhysicsLocation(new Vector3f(-140, 14, -23));
- hoverControl.setPhysicsRotation(new Matrix3f());
+ hoverControl.setPhysicsLocation(startLocation);
+ hoverControl.setPhysicsRotation(startOrientation);
+ hoverControl.setAngularVelocity(Vector3f.ZERO);
+ hoverControl.setLinearVelocity(Vector3f.ZERO);
hoverControl.clearForces();
} else {
}
@@ -272,7 +283,7 @@ private void createTerrain() {
Texture normalMap2 = assetManager.loadTexture("Textures/Terrain/splat/road_normal.png");
normalMap2.setWrap(WrapMode.Repeat);
matRock.setTexture("NormalMap", normalMap0);
- matRock.setTexture("NormalMap_1", normalMap2);
+ matRock.setTexture("NormalMap_1", normalMap1);
matRock.setTexture("NormalMap_2", normalMap2);
AbstractHeightMap heightmap = null;
diff --git a/jme3-examples/src/main/java/jme3test/bullet/TestIssue1120.java b/jme3-examples/src/main/java/jme3test/bullet/TestIssue1120.java
new file mode 100644
index 0000000000..e4a14344ad
--- /dev/null
+++ b/jme3-examples/src/main/java/jme3test/bullet/TestIssue1120.java
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2009-2019 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 jme3test.bullet;
+
+import com.jme3.app.SimpleApplication;
+import com.jme3.bullet.BulletAppState;
+import com.jme3.bullet.PhysicsSpace;
+import com.jme3.bullet.collision.shapes.GImpactCollisionShape;
+import com.jme3.bullet.control.RigidBodyControl;
+import com.jme3.bullet.debug.BulletDebugAppState;
+import com.jme3.font.BitmapFont;
+import com.jme3.font.BitmapText;
+import com.jme3.input.KeyInput;
+import com.jme3.input.MouseInput;
+import com.jme3.input.controls.ActionListener;
+import com.jme3.input.controls.KeyTrigger;
+import com.jme3.input.controls.MouseButtonTrigger;
+import com.jme3.light.DirectionalLight;
+import com.jme3.material.Material;
+import com.jme3.math.ColorRGBA;
+import com.jme3.math.Quaternion;
+import com.jme3.math.Vector3f;
+import com.jme3.scene.Geometry;
+import com.jme3.scene.Mesh;
+import com.jme3.scene.Spatial;
+import com.jme3.scene.shape.Cylinder;
+import com.jme3.system.AppSettings;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Test demonstrating a GImpactCollisionShape falling through a curved mesh, when using JBullet. Bullet native
+ * does not experience this issue at the time this test was created.
+ *
+ * @author lou
+ */
+public class TestIssue1120 extends SimpleApplication {
+
+ private static TestIssue1120 test;
+ private BulletAppState bulletAppState;
+ private final boolean physicsDebug = true;
+ protected BitmapFont font;
+ private final BitmapText[] testInfo = new BitmapText[2];
+ private BitmapText speedText;
+ private final List testObjects = new ArrayList<>();
+ private static final boolean SKIP_SETTINGS = false;//Used for repeated runs of this test during dev
+ private float bulletSpeed = 0.5f;
+
+ public static void main(String[] args) {
+ test = new TestIssue1120();
+ test.setSettings(new AppSettings(true));
+ test.settings.setFrameRate(60);
+ if (SKIP_SETTINGS) {
+ test.settings.setWidth(1920);
+ test.settings.setHeight(1150);
+ test.showSettings = !SKIP_SETTINGS;
+ }
+ test.start();
+ }
+
+ @Override
+ public void simpleInitApp() {
+ cam.setLocation(new Vector3f(-7.285349f, -2.2638104f, 4.954474f));
+ cam.setRotation(new Quaternion(0.07345789f, 0.92521834f, -0.2876841f, 0.23624739f));
+ getFlyByCamera().setMoveSpeed(5);
+
+ DirectionalLight dl = new DirectionalLight();
+ dl.setDirection(new Vector3f(-1, -1, -1).normalizeLocal());
+ dl.setColor(ColorRGBA.Green);
+ rootNode.addLight(dl);
+
+ //Setup interactive test controls
+ inputManager.addMapping("restart", new KeyTrigger(KeyInput.KEY_SPACE));
+ inputManager.addMapping("pause", new MouseButtonTrigger(MouseInput.BUTTON_LEFT));
+ inputManager.addMapping("+", new KeyTrigger(KeyInput.KEY_ADD), new KeyTrigger(KeyInput.KEY_EQUALS));
+ inputManager.addMapping("-", new KeyTrigger(KeyInput.KEY_SUBTRACT), new KeyTrigger(KeyInput.KEY_MINUS));
+ inputManager.addListener((ActionListener) (String name, boolean isPressed, float tpf) -> {
+ if (!isPressed) {
+ return;
+ }
+ switch (name) {
+ case "restart":
+ cleanup();
+ initializeNewTest();
+ break;
+ case "pause":
+ bulletAppState.setSpeed(bulletAppState.getSpeed() > 0.1 ? 0 : bulletSpeed);
+ break;
+ case "+":
+ bulletSpeed += 0.1f;
+ if (bulletSpeed > 1f) {
+ bulletSpeed = 1f;
+ }
+ bulletAppState.setSpeed(bulletSpeed);
+ break;
+ case "-":
+ bulletSpeed -= 0.1f;
+ if (bulletSpeed < 0.1f) {
+ bulletSpeed = 0.1f;
+ }
+ bulletAppState.setSpeed(bulletSpeed);
+ break;
+ }
+ }, "pause", "restart", "+", "-");
+
+ guiNode = getGuiNode();
+ font = assetManager.loadFont("Interface/Fonts/Default.fnt");
+ testInfo[0] = new BitmapText(font);
+ testInfo[1] = new BitmapText(font);
+ speedText = new BitmapText(font);
+
+ float lineHeight = testInfo[0].getLineHeight();
+ testInfo[0].setText("Camera move: W/A/S/D/Q/Z +/-: Increase/Decrease Speed");
+ testInfo[0].setLocalTranslation(5, test.settings.getHeight(), 0);
+ guiNode.attachChild(testInfo[0]);
+ testInfo[1].setText("Left Click: Toggle pause Space: Restart test");
+ testInfo[1].setLocalTranslation(5, test.settings.getHeight() - lineHeight, 0);
+ guiNode.attachChild(testInfo[1]);
+
+ speedText.setLocalTranslation(202, lineHeight * 1, 0);
+ guiNode.attachChild(speedText);
+
+ initializeNewTest();
+ }
+
+ private void initializeNewTest() {
+ bulletAppState = new BulletAppState();
+ bulletAppState.setDebugEnabled(physicsDebug);
+ stateManager.attach(bulletAppState);
+
+ bulletAppState.setSpeed(bulletSpeed);
+
+ dropTest();
+
+ Geometry leftFloor = PhysicsTestHelper.createMeshTestFloor(assetManager, 20, new Vector3f(-11, -5, -10));
+ addObject(leftFloor);
+
+ //Hide physics debug visualization for floors
+ if (physicsDebug) {
+ BulletDebugAppState bulletDebugAppState = stateManager.getState(BulletDebugAppState.class);
+ bulletDebugAppState.setFilter((Object obj) -> {
+ return !(obj.equals(leftFloor.getControl(RigidBodyControl.class)));
+ });
+ }
+ }
+
+ private void addObject(Spatial s) {
+ testObjects.add(s);
+ rootNode.attachChild(s);
+ physicsSpace().add(s);
+ }
+
+ private void dropTest() {
+ attachTestObject(new Cylinder(2, 16, 0.2f, 2f, true), new Vector3f(0f, 2f, -5f), 2);
+ attachTestObject(new Cylinder(2, 16, 0.2f, 2f, true), new Vector3f(-1f, 2f, -5f), 2);
+ attachTestObject(new Cylinder(2, 16, 0.2f, 2f, true), new Vector3f(-2f, 2f, -5f), 2);
+ attachTestObject(new Cylinder(2, 16, 0.2f, 2f, true), new Vector3f(-3f, 2f, -5f), 2);
+ }
+
+ private void attachTestObject(Mesh mesh, Vector3f position, float mass) {
+ Material material = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
+ Geometry g = new Geometry("mesh", mesh);
+ g.setLocalTranslation(position);
+ g.setMaterial(material);
+
+ RigidBodyControl control = new RigidBodyControl(new GImpactCollisionShape(mesh), mass);
+ g.addControl(control);
+ addObject(g);
+ }
+
+ private PhysicsSpace physicsSpace() {
+ return bulletAppState.getPhysicsSpace();
+ }
+
+ @Override
+ public void simpleUpdate(float tpf) {
+ speedText.setText("Speed: " + String.format("%.1f", bulletSpeed));
+ }
+
+ private void cleanup() {
+ stateManager.detach(bulletAppState);
+ stateManager.detach(stateManager.getState(BulletDebugAppState.class));
+ for (Spatial s : testObjects) {
+ rootNode.detachChild(s);
+ }
+ }
+}
diff --git a/jme3-examples/src/main/java/jme3test/bullet/TestIssue1125.java b/jme3-examples/src/main/java/jme3test/bullet/TestIssue1125.java
new file mode 100644
index 0000000000..d39c629f6c
--- /dev/null
+++ b/jme3-examples/src/main/java/jme3test/bullet/TestIssue1125.java
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2019 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 jme3test.bullet;
+
+import com.jme3.app.SimpleApplication;
+import com.jme3.bullet.BulletAppState;
+import com.jme3.bullet.PhysicsSpace;
+import com.jme3.bullet.collision.shapes.CollisionShape;
+import com.jme3.bullet.control.RigidBodyControl;
+import com.jme3.bullet.util.CollisionShapeFactory;
+import com.jme3.font.BitmapText;
+import com.jme3.material.Material;
+import com.jme3.material.RenderState;
+import com.jme3.math.ColorRGBA;
+import com.jme3.math.Quaternion;
+import com.jme3.math.Vector3f;
+import com.jme3.terrain.geomipmap.TerrainQuad;
+import java.util.logging.Logger;
+
+/**
+ * Test case for JME issue #1125: heightfield collision shapes don't match
+ * TerrainQuad.
+ *
+ * If successful, just one set of grid diagonals will be visible. If
+ * unsuccessful, you'll see both green diagonals (the TerrainQuad) and
+ * perpendicular blue diagonals (physics debug).
+ *
+ * Use this test with jme3-bullet only; it can yield false success with
+ * jme3-jbullet due to JME issue #1129.
+ *
+ * @author Stephen Gold sgold@sonic.net
+ */
+public class TestIssue1125 extends SimpleApplication {
+ // *************************************************************************
+ // constants and loggers
+
+ /**
+ * message logger for this class
+ */
+ final public static Logger logger
+ = Logger.getLogger(TestIssue1125.class.getName());
+ // *************************************************************************
+ // fields
+
+ /**
+ * height array for a small heightfield
+ */
+ final private float[] nineHeights = new float[9];
+ /**
+ * green wireframe material for the TerrainQuad
+ */
+ private Material quadMaterial;
+ /**
+ * space for physics simulation
+ */
+ private PhysicsSpace physicsSpace;
+ // *************************************************************************
+ // new methods exposed
+
+ /**
+ * Main entry point for the TestIssue1125 application.
+ *
+ * @param ignored array of command-line arguments (not null)
+ */
+ public static void main(String[] ignored) {
+ new TestIssue1125().start();
+ }
+ // *************************************************************************
+ // SimpleApplication methods
+
+ /**
+ * Initialize this application.
+ */
+ @Override
+ public void simpleInitApp() {
+ configureCamera();
+ configureMaterials();
+ viewPort.setBackgroundColor(new ColorRGBA(0.5f, 0.2f, 0.2f, 1f));
+ configurePhysics();
+ initializeHeightData();
+ addTerrain();
+ showHints();
+ }
+ // *************************************************************************
+ // private methods
+
+ /**
+ * Add 3x3 terrain to the scene and the PhysicsSpace.
+ */
+ private void addTerrain() {
+ int patchSize = 3;
+ int mapSize = 3;
+ TerrainQuad quad
+ = new TerrainQuad("terrain", patchSize, mapSize, nineHeights);
+ rootNode.attachChild(quad);
+ quad.setMaterial(quadMaterial);
+
+ CollisionShape shape = CollisionShapeFactory.createMeshShape(quad);
+ float massForStatic = 0f;
+ RigidBodyControl rbc = new RigidBodyControl(shape, massForStatic);
+ rbc.setPhysicsSpace(physicsSpace);
+ quad.addControl(rbc);
+ }
+
+ /**
+ * Configure the camera during startup.
+ */
+ private void configureCamera() {
+ float fHeight = cam.getFrustumTop() - cam.getFrustumBottom();
+ float fWidth = cam.getFrustumRight() - cam.getFrustumLeft();
+ float fAspect = fWidth / fHeight;
+ float yDegrees = 45f;
+ float near = 0.02f;
+ float far = 20f;
+ cam.setFrustumPerspective(yDegrees, fAspect, near, far);
+
+ flyCam.setMoveSpeed(5f);
+
+ cam.setLocation(new Vector3f(2f, 4.7f, 0.4f));
+ cam.setRotation(new Quaternion(0.348f, -0.64f, 0.4f, 0.556f));
+ }
+
+ /**
+ * Configure materials during startup.
+ */
+ private void configureMaterials() {
+ quadMaterial = new Material(assetManager,
+ "Common/MatDefs/Misc/Unshaded.j3md");
+ quadMaterial.setColor("Color", ColorRGBA.Green.clone());
+ RenderState ars = quadMaterial.getAdditionalRenderState();
+ ars.setWireframe(true);
+ }
+
+ /**
+ * Configure physics during startup.
+ */
+ private void configurePhysics() {
+ BulletAppState bulletAppState = new BulletAppState();
+ stateManager.attach(bulletAppState);
+ bulletAppState.setDebugEnabled(true);
+ physicsSpace = bulletAppState.getPhysicsSpace();
+ }
+
+ /**
+ * Initialize the height data during startup.
+ */
+ private void initializeHeightData() {
+ nineHeights[0] = 1f;
+ nineHeights[1] = 0f;
+ nineHeights[2] = 1f;
+ nineHeights[3] = 0f;
+ nineHeights[4] = 0.5f;
+ nineHeights[5] = 0f;
+ nineHeights[6] = 1f;
+ nineHeights[7] = 0f;
+ nineHeights[8] = 1f;
+ }
+
+ private void showHints() {
+ guiFont = assetManager.loadFont("Interface/Fonts/Default.fnt");
+ int numLines = 3;
+ BitmapText lines[] = new BitmapText[numLines];
+ for (int i = 0; i < numLines; ++i) {
+ lines[i] = new BitmapText(guiFont);
+ }
+
+ String p = "Test for jMonkeyEngine issue #1125";
+ if (isNativeBullet()) {
+ lines[0].setText(p + " with native Bullet");
+ } else {
+ lines[0].setText(p + " with JBullet (may yield false success)");
+ }
+ lines[1].setText("Use W/A/S/D/Q/Z/arrow keys to move the camera.");
+ lines[2].setText("F5: render stats, C: camera pos, M: mem stats");
+
+ float textHeight = guiFont.getCharSet().getLineHeight();
+ float viewHeight = cam.getHeight();
+ float viewWidth = cam.getWidth();
+ for (int i = 0; i < numLines; ++i) {
+ float left = Math.round((viewWidth - lines[i].getLineWidth()) / 2f);
+ float top = viewHeight - i * textHeight;
+ lines[i].setLocalTranslation(left, top, 0f);
+ guiNode.attachChild(lines[i]);
+ }
+ }
+
+ /**
+ * Determine which physics library is in use.
+ *
+ * @return true for C++ Bullet, false for JBullet (jme3-jbullet)
+ */
+ private boolean isNativeBullet() {
+ try {
+ Class clazz = Class.forName("com.jme3.bullet.util.NativeMeshUtil");
+ return clazz != null;
+ } catch (ClassNotFoundException exception) {
+ return false;
+ }
+ }
+}
diff --git a/jme3-examples/src/main/java/jme3test/bullet/TestWalkingChar.java b/jme3-examples/src/main/java/jme3test/bullet/TestWalkingChar.java
index 4359154d12..532052da07 100644
--- a/jme3-examples/src/main/java/jme3test/bullet/TestWalkingChar.java
+++ b/jme3-examples/src/main/java/jme3test/bullet/TestWalkingChar.java
@@ -262,7 +262,7 @@ private void createTerrain() {
Texture normalMap2 = assetManager.loadTexture("Textures/Terrain/splat/road_normal.png");
normalMap2.setWrap(WrapMode.Repeat);
matRock.setTexture("NormalMap", normalMap0);
- matRock.setTexture("NormalMap_1", normalMap2);
+ matRock.setTexture("NormalMap_1", normalMap1);
matRock.setTexture("NormalMap_2", normalMap2);
AbstractHeightMap heightmap = null;
diff --git a/jme3-examples/src/main/java/jme3test/bullet/shape/TestGimpactShape.java b/jme3-examples/src/main/java/jme3test/bullet/shape/TestGimpactShape.java
new file mode 100644
index 0000000000..484f0f1774
--- /dev/null
+++ b/jme3-examples/src/main/java/jme3test/bullet/shape/TestGimpactShape.java
@@ -0,0 +1,343 @@
+/*
+ * Copyright (c) 2009-2019 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 jme3test.bullet.shape;
+
+import com.jme3.app.SimpleApplication;
+import com.jme3.bullet.BulletAppState;
+import com.jme3.bullet.PhysicsSpace;
+import com.jme3.bullet.collision.shapes.GImpactCollisionShape;
+import com.jme3.bullet.control.RigidBodyControl;
+import com.jme3.bullet.debug.BulletDebugAppState;
+import com.jme3.font.BitmapFont;
+import com.jme3.font.BitmapText;
+import com.jme3.input.KeyInput;
+import com.jme3.input.controls.ActionListener;
+import com.jme3.input.controls.KeyTrigger;
+import com.jme3.light.DirectionalLight;
+import com.jme3.material.Material;
+import com.jme3.math.ColorRGBA;
+import com.jme3.math.FastMath;
+import com.jme3.math.Vector3f;
+import com.jme3.scene.Geometry;
+import com.jme3.scene.Mesh;
+import com.jme3.scene.Node;
+import com.jme3.scene.Spatial;
+import com.jme3.scene.shape.PQTorus;
+import com.jme3.scene.shape.Torus;
+import com.jme3.system.AppSettings;
+import java.util.ArrayList;
+import java.util.List;
+import jme3test.bullet.PhysicsTestHelper;
+
+/**
+ * This test demonstrates various GImpactCollisionShapes colliding against two identical curved surfaces. The
+ * left surface is a MeshCollisionShape, right surface is another GImpactCollisionShape. An ideal result is
+ * for all objects to land and change to a blue colored mesh indicating they are inactive. Falling through the
+ * floor, or never going inactive (bouncing forever) are failure conditions.
+ *
+ * Observations as of June 2019 (JME v3.3.0-alpha2):
+ *
+ *
+ * With default starting parameters, Native Bullet should pass the test parameters above. JBullet fails due to
+ * the rocket/MeshCollisionShape never going inactive.
+ *
+ *
+ * Native Bullet behaves better than JBullet. JBullet sometimes allows objects to "gain too much energy" after
+ * a collision, such as the rocket or teapot. Native also does this, to a lesser degree. This generally
+ * appears to happen at larger object scales.
+ *
+ *
+ * JBullet allows some objects to get "stuck" inside the floor, which usually results in a fall-through
+ * eventually, generally a larger scales for this test.
+ *
+ *
+ * Some shapes such as PQTorus & signpost never go inactive at larger scales for both Native and JBullet (test
+ * at 1.5 and 1.9 scale)
+ *
+ *
+ *
+ * @author lou
+ */
+public class TestGimpactShape extends SimpleApplication {
+
+ private static TestGimpactShape test;
+ private BulletAppState bulletAppState;
+ private int solverNumIterations = 10;
+ private BitmapFont font;
+ private final BitmapText[] testInfo = new BitmapText[2];
+ private BitmapText timeElapsedTxt;
+ private BitmapText solverNumIterationsTxt;
+ private BitmapText testScale;
+ private final List testObjects = new ArrayList<>();
+ private float testTimer = 0;
+ private float scaleMod = 1;
+ private boolean restart = true;
+ private static final boolean SKIP_SETTINGS = false;//Used for repeated runs of this test during dev
+
+ public static void main(String[] args) {
+ test = new TestGimpactShape();
+ test.setSettings(new AppSettings(true));
+ test.settings.setVSync(true);
+ if (SKIP_SETTINGS) {
+ test.settings.setWidth(1920);
+ test.settings.setHeight(1150);
+ test.showSettings = !SKIP_SETTINGS;
+ }
+ test.start();
+ }
+
+ @Override
+ public void simpleInitApp() {
+ test = this;
+ getCamera().setLocation(new Vector3f(40, 30, 160));
+ getCamera().lookAt(new Vector3f(40, -5, 0), Vector3f.UNIT_Y);
+ getFlyByCamera().setMoveSpeed(25);
+
+ DirectionalLight dl = new DirectionalLight();
+ dl.setDirection(new Vector3f(-1, -1, -1).normalizeLocal());
+ dl.setColor(ColorRGBA.Green);
+ rootNode.addLight(dl);
+
+ //Setup test instructions
+ guiNode = getGuiNode();
+ font = assetManager.loadFont("Interface/Fonts/Default.fnt");
+ testInfo[0] = new BitmapText(font);
+ testInfo[1] = new BitmapText(font);
+ timeElapsedTxt = new BitmapText(font);
+ solverNumIterationsTxt = new BitmapText(font);
+ testScale = new BitmapText(font);
+
+ float lineHeight = testInfo[0].getLineHeight();
+ testInfo[0].setText("Camera move:W/A/S/D/Q/Z Solver iterations: 1=10, 2=20, 3=30");
+ testInfo[0].setLocalTranslation(5, test.settings.getHeight(), 0);
+ guiNode.attachChild(testInfo[0]);
+ testInfo[1].setText("P: Toggle pause Inc/Dec object scale: +, - Space: Restart test");
+ testInfo[1].setLocalTranslation(5, test.settings.getHeight() - lineHeight, 0);
+ guiNode.attachChild(testInfo[1]);
+
+ timeElapsedTxt.setLocalTranslation(202, lineHeight * 1, 0);
+ guiNode.attachChild(timeElapsedTxt);
+ solverNumIterationsTxt.setLocalTranslation(202, lineHeight * 2, 0);
+ guiNode.attachChild(solverNumIterationsTxt);
+ testScale.setLocalTranslation(202, lineHeight * 3, 0);
+ guiNode.attachChild(testScale);
+
+ //Setup interactive test controls
+ inputManager.addMapping("restart", new KeyTrigger(KeyInput.KEY_SPACE));
+ inputManager.addListener((ActionListener) (String name, boolean isPressed, float tpf) -> {
+ restart = true;
+ }, "restart");
+
+ inputManager.addMapping("pause", new KeyTrigger(KeyInput.KEY_P));
+ inputManager.addListener((ActionListener) (String name, boolean isPressed, float tpf) -> {
+ if (!isPressed) {
+ return;
+ }
+ bulletAppState.setSpeed(bulletAppState.getSpeed() > 0.1 ? 0 : 1);
+ }, "pause");
+
+ inputManager.addMapping("1", new KeyTrigger(KeyInput.KEY_1));
+ inputManager.addMapping("2", new KeyTrigger(KeyInput.KEY_2));
+ inputManager.addMapping("3", new KeyTrigger(KeyInput.KEY_3));
+ inputManager.addMapping("+", new KeyTrigger(KeyInput.KEY_ADD), new KeyTrigger(KeyInput.KEY_EQUALS));
+ inputManager.addMapping("-", new KeyTrigger(KeyInput.KEY_SUBTRACT), new KeyTrigger(KeyInput.KEY_MINUS));
+ inputManager.addListener((ActionListener) (String name, boolean isPressed, float tpf) -> {
+ if (!isPressed) {
+ return;
+ }
+ switch (name) {
+ case "1":
+ solverNumIterations = 10;
+ break;
+ case "2":
+ solverNumIterations = 20;
+ break;
+ case "3":
+ solverNumIterations = 30;
+ break;
+ case "+":
+ scaleMod += scaleMod < 1.9f ? 0.1f : 0;
+ break;
+ case "-":
+ scaleMod -= scaleMod > 0.5f ? 0.1f : 0;
+ break;
+ }
+ restart = true;
+ }, "1", "2", "3", "+", "-");
+
+ initializeNewTest();
+ }
+
+ private void initializeNewTest() {
+ testScale.setText("Object scale: " + String.format("%.1f", scaleMod));
+ solverNumIterationsTxt.setText("Solver Iterations: " + solverNumIterations);
+
+ bulletAppState = new BulletAppState();
+ bulletAppState.setDebugEnabled(true);
+ stateManager.attach(bulletAppState);
+ bulletAppState.getPhysicsSpace().setSolverNumIterations(solverNumIterations);
+
+ float floorSize = 80;
+ //Left side test - GImpact objects collide with MeshCollisionShape floor
+ Vector3f leftFloorPos = new Vector3f(-41, -5, -10);
+ Vector3f leftFloorCenter = leftFloorPos.add(floorSize / 2, 0, floorSize / 2);
+
+ dropTest1(leftFloorCenter);
+ dropTest2(leftFloorCenter);
+ dropPot(leftFloorCenter);
+ dropSword(leftFloorCenter);
+ dropSign(leftFloorCenter);
+ dropRocket(leftFloorCenter);
+
+ Geometry leftFloor = PhysicsTestHelper.createMeshTestFloor(assetManager, floorSize, leftFloorPos);
+ addObject(leftFloor);
+
+ //Right side test - GImpact objects collide with GImpact floor
+ Vector3f rightFloorPos = new Vector3f(41, -5, -10);
+ Vector3f rightFloorCenter = rightFloorPos.add(floorSize / 2, 0, floorSize / 2);
+
+ dropTest1(rightFloorCenter);
+ dropTest2(rightFloorCenter);
+ dropPot(rightFloorCenter);
+ dropSword(rightFloorCenter);
+ dropSign(rightFloorCenter);
+ dropRocket(rightFloorCenter);
+
+ Geometry rightFloor = PhysicsTestHelper.createGImpactTestFloor(assetManager, floorSize, rightFloorPos);
+ addObject(rightFloor);
+
+ //Hide physics debug visualization for floors
+ BulletDebugAppState bulletDebugAppState = stateManager.getState(BulletDebugAppState.class);
+ bulletDebugAppState.setFilter((Object obj) -> {
+ return !(obj.equals(rightFloor.getControl(RigidBodyControl.class))
+ || obj.equals(leftFloor.getControl(RigidBodyControl.class)));
+ });
+ }
+
+ private void addObject(Spatial s) {
+ testObjects.add(s);
+ rootNode.attachChild(s);
+ physicsSpace().add(s);
+ }
+
+ private void dropTest1(Vector3f offset) {
+ offset = offset.add(-18, 6, -18);
+ attachTestObject(new Torus(16, 16, 0.15f, 0.5f), new Vector3f(-12f, 0f, 5f).add(offset), 1);
+ attachTestObject(new PQTorus(2f, 3f, 0.6f, 0.2f, 48, 16), new Vector3f(0, 0, 0).add(offset), 5);
+
+ }
+
+ private void dropTest2(Vector3f offset) {
+ offset = offset.add(18, 6, -18);
+ attachTestObject(new Torus(16, 16, 0.3f, 0.8f), new Vector3f(12f, 0f, 5f).add(offset), 3);
+ attachTestObject(new PQTorus(3f, 5f, 0.8f, 0.2f, 96, 16), new Vector3f(0, 0, 0).add(offset), 10);
+ }
+
+ private void dropPot(Vector3f offset) {
+ drop(offset.add(-12, 7, 15), "Models/Teapot/Teapot.mesh.xml", 1.0f, 2);
+ }
+
+ private void dropSword(Vector3f offset) {
+ drop(offset.add(-10, 5, 3), "Models/Sinbad/Sword.mesh.xml", 1.0f, 2);
+ }
+
+ private void dropSign(Vector3f offset) {
+ drop(offset.add(9, 15, 5), "Models/Sign Post/Sign Post.mesh.xml", 1.0f, 1);
+ }
+
+ private void dropRocket(Vector3f offset) {
+ RigidBodyControl c = drop(offset.add(26, 4, 7), "Models/SpaceCraft/Rocket.mesh.xml", 4.0f, 3);
+ c.setAngularDamping(0.5f);
+ c.setLinearDamping(0.5f);
+ }
+
+ private RigidBodyControl drop(Vector3f offset, String model, float scale, float mass) {
+ scale *= scaleMod;
+ Node n = (Node) assetManager.loadModel(model);
+ n.setLocalTranslation(offset);
+ n.rotate(0, 0, -FastMath.HALF_PI);
+
+ Geometry tp = ((Geometry) n.getChild(0));
+ tp.scale(scale);
+ Material mat = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");
+ tp.setMaterial(mat);
+
+ Mesh mesh = tp.getMesh();
+ GImpactCollisionShape shape = new GImpactCollisionShape(mesh);
+ shape.setScale(new Vector3f(scale, scale, scale));
+
+ RigidBodyControl control = new RigidBodyControl(shape, mass);
+ n.addControl(control);
+ addObject(n);
+ return control;
+ }
+
+ private void attachTestObject(Mesh mesh, Vector3f position, float mass) {
+ Material material = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
+ material.setTexture("ColorMap", assetManager.loadTexture("Interface/Logo/Monkey.jpg"));
+ Geometry g = new Geometry("mesh", mesh);
+ g.scale(scaleMod);
+ g.setLocalTranslation(position);
+ g.setMaterial(material);
+
+ GImpactCollisionShape shape = new GImpactCollisionShape(mesh);
+ shape.setScale(new Vector3f(scaleMod, scaleMod, scaleMod));
+ RigidBodyControl control = new RigidBodyControl(shape, mass);
+ g.addControl(control);
+ addObject(g);
+ }
+
+ private PhysicsSpace physicsSpace() {
+ return bulletAppState.getPhysicsSpace();
+ }
+
+ @Override
+ public void simpleUpdate(float tpf) {
+ testTimer += tpf * bulletAppState.getSpeed();
+
+ if (restart) {
+ cleanup();
+ initializeNewTest();
+ restart = false;
+ testTimer = 0;
+ }
+ timeElapsedTxt.setText("Time Elapsed: " + String.format("%.3f", testTimer));
+ }
+
+ private void cleanup() {
+ stateManager.detach(bulletAppState);
+ stateManager.detach(stateManager.getState(BulletDebugAppState.class));
+ for (Spatial s : testObjects) {
+ rootNode.detachChild(s);
+ }
+ }
+}
diff --git a/jme3-examples/src/main/java/jme3test/gui/TestRtlBitmapText.java b/jme3-examples/src/main/java/jme3test/gui/TestRtlBitmapText.java
new file mode 100644
index 0000000000..ed65c4a071
--- /dev/null
+++ b/jme3-examples/src/main/java/jme3test/gui/TestRtlBitmapText.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2009-2019 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 jme3test.gui;
+
+import com.jme3.app.SimpleApplication;
+import com.jme3.font.BitmapFont;
+import com.jme3.font.BitmapText;
+import com.jme3.font.LineWrapMode;
+import com.jme3.font.Rectangle;
+
+/**
+ * Test case for JME issue #1158: BitmapText right to left line wrapping not work
+ */
+public class TestRtlBitmapText extends SimpleApplication {
+
+ // A right to left text.
+ private String text = ".text left to right test a is This";
+
+ public static void main(String[] args) {
+ TestRtlBitmapText app = new TestRtlBitmapText();
+ app.start();
+ }
+
+ @Override
+ public void simpleInitApp() {
+ BitmapFont fnt = assetManager.loadFont("Interface/Fonts/Default.fnt");
+ // A right to left BitmapText
+ BitmapText txt = new BitmapText(fnt, true);
+ txt.setBox(new Rectangle(0, 0, 150, 0));
+ txt.setLineWrapMode(LineWrapMode.Word);
+ txt.setAlignment(BitmapFont.Align.Right);
+ txt.setText(text);
+ txt.setLocalTranslation(cam.getWidth() / 2, cam.getHeight() / 2, 0);
+ guiNode.attachChild(txt);
+ }
+}
diff --git a/jme3-examples/src/main/java/jme3test/light/TestSpotLightTerrain.java b/jme3-examples/src/main/java/jme3test/light/TestSpotLightTerrain.java
index 02bd48abbd..43e7beba29 100644
--- a/jme3-examples/src/main/java/jme3test/light/TestSpotLightTerrain.java
+++ b/jme3-examples/src/main/java/jme3test/light/TestSpotLightTerrain.java
@@ -165,7 +165,7 @@ private void makeTerrain() {
Texture normalMap2 = assetManager.loadTexture("Textures/Terrain/splat/road_normal.png");
normalMap2.setWrap(WrapMode.Repeat);
matTerrain.setTexture("NormalMap", normalMap0);
- matTerrain.setTexture("NormalMap_1", normalMap2);
+ matTerrain.setTexture("NormalMap_1", normalMap1);
matTerrain.setTexture("NormalMap_2", normalMap2);
matTerrain.setTexture("NormalMap_4", normalMap2);
diff --git a/jme3-examples/src/main/java/jme3test/post/TestDepthOfField.java b/jme3-examples/src/main/java/jme3test/post/TestDepthOfField.java
index 263d45ff3d..6fee9e404b 100644
--- a/jme3-examples/src/main/java/jme3test/post/TestDepthOfField.java
+++ b/jme3-examples/src/main/java/jme3test/post/TestDepthOfField.java
@@ -166,7 +166,7 @@ private void createTerrain(Node rootNode) {
Texture normalMap2 = assetManager.loadTexture("Textures/Terrain/splat/road_normal.png");
normalMap2.setWrap(WrapMode.Repeat);
matRock.setTexture("NormalMap", normalMap0);
- matRock.setTexture("NormalMap_1", normalMap2);
+ matRock.setTexture("NormalMap_1", normalMap1);
matRock.setTexture("NormalMap_2", normalMap2);
AbstractHeightMap heightmap = null;
diff --git a/jme3-examples/src/main/java/jme3test/post/TestFog.java b/jme3-examples/src/main/java/jme3test/post/TestFog.java
index 6d3b667aba..3ecac03a0d 100644
--- a/jme3-examples/src/main/java/jme3test/post/TestFog.java
+++ b/jme3-examples/src/main/java/jme3test/post/TestFog.java
@@ -180,7 +180,7 @@ private void createTerrain(Node rootNode) {
Texture normalMap2 = assetManager.loadTexture("Textures/Terrain/splat/road_normal.png");
normalMap2.setWrap(Texture.WrapMode.Repeat);
matRock.setTexture("NormalMap", normalMap0);
- matRock.setTexture("NormalMap_1", normalMap2);
+ matRock.setTexture("NormalMap_1", normalMap1);
matRock.setTexture("NormalMap_2", normalMap2);
AbstractHeightMap heightmap = null;
diff --git a/jme3-examples/src/main/java/jme3test/renderer/TestAlphaToCoverage.java b/jme3-examples/src/main/java/jme3test/renderer/TestAlphaToCoverage.java
new file mode 100644
index 0000000000..1765e5478f
--- /dev/null
+++ b/jme3-examples/src/main/java/jme3test/renderer/TestAlphaToCoverage.java
@@ -0,0 +1,54 @@
+package jme3test.renderer;
+import com.jme3.app.SimpleApplication;
+
+import com.jme3.renderer.lwjgl.LwjglGL;
+import com.jme3.renderer.opengl.GL;
+import com.jme3.renderer.opengl.GLExt;
+import com.jme3.renderer.opengl.GLFbo;
+import com.jme3.renderer.opengl.GLRenderer;
+import com.jme3.renderer.lwjgl.LwjglGLExt;
+import com.jme3.renderer.lwjgl.LwjglGLFboEXT;
+import com.jme3.renderer.Caps;
+
+import java.util.EnumSet;
+
+/**
+ * Simple application to test the getter and setters of AlphaToCoverage and
+ * DefaultAnisotropicFilter from the GLRenderer class.
+ *
+ * Since the app doesn't display anything relevant a stop() has been added
+ * This starts and closes the app on a successful run
+ */
+public class TestAlphaToCoverage extends SimpleApplication {
+
+ public static void main(String[] args) {
+ new TestAlphaToCoverage().start();
+ }
+
+ public GL gl = new LwjglGL();
+ public GLExt glext = new LwjglGLExt();
+ public GLFbo glfbo = new LwjglGLFboEXT();
+ private GLRenderer glRenderer= new GLRenderer(gl,glext,glfbo);
+
+ public EnumSet caps = glRenderer.getCaps();
+
+
+
+ @Override
+ public void simpleInitApp() {
+ glRenderer.setAlphaToCoverage(false);
+ assert !glRenderer.getAlphaToCoverage();
+
+ caps.add(Caps.Multisample);
+ glRenderer.setAlphaToCoverage(true);
+ assert glRenderer.getAlphaToCoverage();
+ glRenderer.setAlphaToCoverage(false);
+ assert !glRenderer.getAlphaToCoverage();
+
+ glRenderer.setDefaultAnisotropicFilter(1);
+ assert glRenderer.getDefaultAnisotropicFilter() == 1;
+
+ stop();
+ }
+
+}
diff --git a/jme3-examples/src/main/java/jme3test/terrain/TerrainGridAlphaMapTest.java b/jme3-examples/src/main/java/jme3test/terrain/TerrainGridAlphaMapTest.java
index ef0f6c1bbe..cf5e9d75c1 100644
--- a/jme3-examples/src/main/java/jme3test/terrain/TerrainGridAlphaMapTest.java
+++ b/jme3-examples/src/main/java/jme3test/terrain/TerrainGridAlphaMapTest.java
@@ -294,7 +294,9 @@ public void onAction(final String name, final boolean keyPressed, final float tp
TerrainGridAlphaMapTest.this.down = false;
}
} else if (name.equals("Jumps")) {
- TerrainGridAlphaMapTest.this.player3.jump();
+ if (usePhysics && keyPressed) {
+ player3.jump();
+ }
}
}
};
diff --git a/jme3-examples/src/main/java/jme3test/terrain/TerrainTestCollision.java b/jme3-examples/src/main/java/jme3test/terrain/TerrainTestCollision.java
index 6822251ba7..faa67fd137 100644
--- a/jme3-examples/src/main/java/jme3test/terrain/TerrainTestCollision.java
+++ b/jme3-examples/src/main/java/jme3test/terrain/TerrainTestCollision.java
@@ -64,6 +64,9 @@
import com.jme3.texture.Texture;
import com.jme3.texture.Texture.WrapMode;
+import java.util.ArrayList;
+import java.util.List;
+
/**
* Creates a terrain object and a collision node to go with it. Then
* drops several balls from the sky that collide with the terrain
@@ -83,7 +86,7 @@ public class TerrainTestCollision extends SimpleApplication {
protected BitmapText hintText;
PointLight pl;
Geometry lightMdl;
- Geometry collisionMarker;
+ List collisionMarkers;
private BulletAppState bulletAppState;
Geometry collisionSphere;
Geometry collisionBox;
@@ -103,6 +106,7 @@ public void initialize() {
@Override
public void simpleInitApp() {
+ collisionMarkers = new ArrayList<>();
bulletAppState = new BulletAppState();
bulletAppState.setThreadingType(BulletAppState.ThreadingType.PARALLEL);
stateManager.attach(bulletAppState);
@@ -142,6 +146,8 @@ public void simpleInitApp() {
terrain.setLocked(false); // unlock it so we can edit the height
rootNode.attachChild(terrain);
+ // if set to false, only the first collision is returned and collision is slightly faster.
+ terrain.setSupportMultipleCollisions(true);
/**
* Create PhysicsRigidBodyControl for collision
@@ -227,15 +233,19 @@ public void update() {
super.update();
}
- private void createCollisionMarker() {
- Sphere s = new Sphere(6, 6, 1);
- collisionMarker = new Geometry("collisionMarker");
- collisionMarker.setMesh(s);
- Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
- mat.setColor("Color", ColorRGBA.Orange);
- collisionMarker.setMaterial(mat);
- rootNode.attachChild(collisionMarker);
+ private void createCollisionMarkers(int num) {
+ for (int i = 0; i < num; i++) {
+ Sphere s = new Sphere(6, 6, 1);
+ Geometry collisionMarker = new Geometry("collisionMarker");
+ collisionMarker.setMesh(s);
+ Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
+ mat.setColor("Color", i == 0 ? ColorRGBA.Orange : ColorRGBA.Blue);
+ collisionMarker.setMaterial(mat);
+ rootNode.attachChild(collisionMarker);
+ collisionMarkers.add(collisionMarker);
+ }
}
+
private ActionListener actionListener = new ActionListener() {
public void onAction(String binding, boolean keyPressed, float tpf) {
@@ -247,24 +257,35 @@ public void onAction(String binding, boolean keyPressed, float tpf) {
terrain.setMaterial(matRock);
}
} else if (binding.equals("shoot") && !keyPressed) {
-
Vector3f origin = cam.getWorldCoordinates(new Vector2f(settings.getWidth() / 2, settings.getHeight() / 2), 0.0f);
Vector3f direction = cam.getWorldCoordinates(new Vector2f(settings.getWidth() / 2, settings.getHeight() / 2), 0.3f);
direction.subtractLocal(origin).normalizeLocal();
-
Ray ray = new Ray(origin, direction);
CollisionResults results = new CollisionResults();
- int numCollisions = terrain.collideWith(ray, results);
- if (numCollisions > 0) {
- CollisionResult hit = results.getClosestCollision();
- if (collisionMarker == null) {
- createCollisionMarker();
+
+ if (terrain.collideWith(ray, results) > 0) {
+ CollisionResult hit = results.getClosestCollision(); // sorts the collection before printing
+ printCollisions(results);
+
+ // Remove old markers.
+ for (Geometry g: collisionMarkers) {
+ g.removeFromParent();
}
+ collisionMarkers.clear();
+
+ createCollisionMarkers(results.size());
+
+ // Position Closest Collision
Vector2f loc = new Vector2f(hit.getContactPoint().x, hit.getContactPoint().z);
float height = terrain.getHeight(loc);
- System.out.println("collide " + hit.getContactPoint() + ", height: " + height + ", distance: " + hit.getDistance());
- collisionMarker.setLocalTranslation(new Vector3f(hit.getContactPoint().x, height, hit.getContactPoint().z));
+ System.out.println("Closest Collision: " + hit.getContactPoint() + ", height: " + height + ", distance: " + hit.getDistance());
+ collisionMarkers.get(0).setLocalTranslation(new Vector3f(hit.getContactPoint().x, height, hit.getContactPoint().z));
+
+ // Position Rest: When getClosestCollision has been called, the results are sorted, and thus 0 is closest.
+ for (int i = 1; i < results.size(); i++) {
+ collisionMarkers.get(i).setLocalTranslation(results.getCollision(i).getContactPoint());
+ }
}
} else if (binding.equals("cameraDown") && !keyPressed) {
getCamera().lookAtDirection(new Vector3f(0, -1, 0), Vector3f.UNIT_Y);
@@ -302,4 +323,14 @@ private void testCollision(Vector3f oldLoc) {
selectedCollisionObject.setLocalTranslation(oldLoc);
}
}
+
+ private void printCollisions(CollisionResults cr) {
+ System.out.println("================ Collision Results ================");
+ for (int i = 0; i < cr.size(); i++) {
+ CollisionResult res = cr.getCollision(i);
+ System.out.println("Result " + i);
+ System.out.println("\t\t" + res.toString());
+ }
+ System.out.println("================ END Collision Results ================");
+ }
}
diff --git a/jme3-examples/src/main/java/jme3test/terrain/TerrainTestReadWrite.java b/jme3-examples/src/main/java/jme3test/terrain/TerrainTestReadWrite.java
index b6bba1c82c..8610962985 100644
--- a/jme3-examples/src/main/java/jme3test/terrain/TerrainTestReadWrite.java
+++ b/jme3-examples/src/main/java/jme3test/terrain/TerrainTestReadWrite.java
@@ -130,7 +130,7 @@ private void createMap() {
Texture normalMap2 = assetManager.loadTexture("Textures/Terrain/splat/road_normal.png");
normalMap2.setWrap(WrapMode.Repeat);
matTerrain.setTexture("NormalMap", normalMap0);
- matTerrain.setTexture("NormalMap_1", normalMap2);
+ matTerrain.setTexture("NormalMap_1", normalMap1);
matTerrain.setTexture("NormalMap_2", normalMap2);
matWire = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
diff --git a/jme3-examples/src/main/java/jme3test/texture/TestTexture3D.java b/jme3-examples/src/main/java/jme3test/texture/TestTexture3D.java
index a7e553a9a1..1e151bf741 100644
--- a/jme3-examples/src/main/java/jme3test/texture/TestTexture3D.java
+++ b/jme3-examples/src/main/java/jme3test/texture/TestTexture3D.java
@@ -128,4 +128,4 @@ private Texture getTexture() throws IOException {
data.add(bb);
return new Texture3D(new Image(Format.RGB8, 10, 10, 10, data, null, ColorSpace.Linear));
}
-}
\ No newline at end of file
+}
diff --git a/jme3-examples/src/main/java/jme3test/texture/TestTextureArray.java b/jme3-examples/src/main/java/jme3test/texture/TestTextureArray.java
index 391e4efcc6..1757c021bd 100644
--- a/jme3-examples/src/main/java/jme3test/texture/TestTextureArray.java
+++ b/jme3-examples/src/main/java/jme3test/texture/TestTextureArray.java
@@ -84,4 +84,4 @@ public static void main(String[] args)
app.start();
}
-}
\ No newline at end of file
+}
diff --git a/jme3-examples/src/main/java/jme3test/texture/TestTextureArrayCompressed.java b/jme3-examples/src/main/java/jme3test/texture/TestTextureArrayCompressed.java
index 2187c58d87..738f4b94c2 100644
--- a/jme3-examples/src/main/java/jme3test/texture/TestTextureArrayCompressed.java
+++ b/jme3-examples/src/main/java/jme3test/texture/TestTextureArrayCompressed.java
@@ -31,8 +31,8 @@ public void simpleInitApp()
}
- Texture tex1 = assetManager.loadTexture( "Textures/Terrain/Pond/Pond.dds");
- Texture tex2 = assetManager.loadTexture("Textures/Terrain/BrickWall/BrickWall.dds");
+ Texture tex1 = assetManager.loadTexture( "Textures/Terrain/Pond/Pond_dxt5.dds");
+ Texture tex2 = assetManager.loadTexture("Textures/Terrain/BrickWall/BrickWall_dxt5.dds");
List images = new ArrayList();
images.add(tex1.getImage());
images.add(tex2.getImage());
@@ -84,4 +84,4 @@ public static void main(String[] args)
app.start();
}
-}
\ No newline at end of file
+}
diff --git a/jme3-examples/src/main/java/jme3test/water/TestMultiPostWater.java b/jme3-examples/src/main/java/jme3test/water/TestMultiPostWater.java
index 2611d9696d..9e9caf9d0a 100644
--- a/jme3-examples/src/main/java/jme3test/water/TestMultiPostWater.java
+++ b/jme3-examples/src/main/java/jme3test/water/TestMultiPostWater.java
@@ -160,7 +160,7 @@ private void createTerrain(Node rootNode) {
Texture normalMap2 = assetManager.loadTexture("Textures/Terrain/splat/road_normal.png");
normalMap2.setWrap(WrapMode.Repeat);
matRock.setTexture("NormalMap", normalMap0);
- matRock.setTexture("NormalMap_1", normalMap2);
+ matRock.setTexture("NormalMap_1", normalMap1);
matRock.setTexture("NormalMap_2", normalMap2);
AbstractHeightMap heightmap = null;
diff --git a/jme3-examples/src/main/java/jme3test/water/TestPostWater.java b/jme3-examples/src/main/java/jme3test/water/TestPostWater.java
index 21e11d153a..3d650c170b 100644
--- a/jme3-examples/src/main/java/jme3test/water/TestPostWater.java
+++ b/jme3-examples/src/main/java/jme3test/water/TestPostWater.java
@@ -276,7 +276,7 @@ private void createTerrain(Node rootNode) {
Texture normalMap2 = assetManager.loadTexture("Textures/Terrain/splat/road_normal.png");
normalMap2.setWrap(WrapMode.Repeat);
matRock.setTexture("NormalMap", normalMap0);
- matRock.setTexture("NormalMap_1", normalMap2);
+ matRock.setTexture("NormalMap_1", normalMap1);
matRock.setTexture("NormalMap_2", normalMap2);
AbstractHeightMap heightmap = null;
diff --git a/jme3-examples/src/main/resources/jme3test/texture/UnshadedArray.frag b/jme3-examples/src/main/resources/jme3test/texture/UnshadedArray.frag
index 355cf60928..4b888e81d8 100644
--- a/jme3-examples/src/main/resources/jme3test/texture/UnshadedArray.frag
+++ b/jme3-examples/src/main/resources/jme3test/texture/UnshadedArray.frag
@@ -1,3 +1,5 @@
+#import "Common/ShaderLib/GLSLCompat.glsllib"
+
#extension GL_EXT_texture_array : enable
// #extension GL_EXT_gpu_shader4 : enable
@@ -8,7 +10,7 @@ uniform vec4 m_Color;
#endif
#ifdef HAS_COLORMAP
- #if !defined(GL_EXT_texture_array)
+ #if !defined(GL_EXT_texture_array) && __VERSION__ < 130
#error Texture arrays are not supported, but required for this shader.
#endif
@@ -54,4 +56,4 @@ void main(){
#endif
gl_FragColor = color;
-}
\ No newline at end of file
+}
diff --git a/jme3-examples/src/main/resources/jme3test/texture/UnshadedArray.j3md b/jme3-examples/src/main/resources/jme3test/texture/UnshadedArray.j3md
index 6a3219e602..bcbee23d89 100644
--- a/jme3-examples/src/main/resources/jme3test/texture/UnshadedArray.j3md
+++ b/jme3-examples/src/main/resources/jme3test/texture/UnshadedArray.j3md
@@ -14,8 +14,8 @@ MaterialDef Unshaded {
}
Technique {
- VertexShader GLSL100: jme3test/texture/UnshadedArray.vert
- FragmentShader GLSL100: jme3test/texture/UnshadedArray.frag
+ VertexShader GLSL300 GLSL100: jme3test/texture/UnshadedArray.vert
+ FragmentShader GLSL300 GLSL100: jme3test/texture/UnshadedArray.frag
WorldParameters {
WorldViewProjectionMatrix
@@ -32,8 +32,8 @@ MaterialDef Unshaded {
Technique PreNormalPass {
- VertexShader GLSL100 : Common/MatDefs/SSAO/normal.vert
- FragmentShader GLSL100 : Common/MatDefs/SSAO/normal.frag
+ VertexShader GLSL300 GLSL100 : Common/MatDefs/SSAO/normal.vert
+ FragmentShader GLSL300 GLSL100 : Common/MatDefs/SSAO/normal.frag
WorldParameters {
WorldViewProjectionMatrix
@@ -50,8 +50,8 @@ MaterialDef Unshaded {
Technique Glow {
- VertexShader GLSL100: Cjme3test/texture/UnshadedArray.vert
- FragmentShader GLSL100: Common/MatDefs/Light/Glow.frag
+ VertexShader GLSL300 GLSL100: jme3test/texture/UnshadedArray.vert
+ FragmentShader GLSL300 GLSL100: Common/MatDefs/Light/Glow.frag
WorldParameters {
WorldViewProjectionMatrix
@@ -63,4 +63,4 @@ MaterialDef Unshaded {
HAS_COLORMAP // Must be passed so that Unshaded.vert exports texCoord.
}
}
-}
\ No newline at end of file
+}
diff --git a/jme3-examples/src/main/resources/jme3test/texture/UnshadedArray.vert b/jme3-examples/src/main/resources/jme3test/texture/UnshadedArray.vert
index 9d1153c3d4..3f85e3063b 100644
--- a/jme3-examples/src/main/resources/jme3test/texture/UnshadedArray.vert
+++ b/jme3-examples/src/main/resources/jme3test/texture/UnshadedArray.vert
@@ -1,3 +1,5 @@
+#import "Common/ShaderLib/GLSLCompat.glsllib"
+
uniform mat4 g_WorldViewProjectionMatrix;
attribute vec3 inPosition;
diff --git a/jme3-examples/src/main/resources/jme3test/texture/tex3D.frag b/jme3-examples/src/main/resources/jme3test/texture/tex3D.frag
index 55862acf93..2e811ad03b 100644
--- a/jme3-examples/src/main/resources/jme3test/texture/tex3D.frag
+++ b/jme3-examples/src/main/resources/jme3test/texture/tex3D.frag
@@ -1,7 +1,9 @@
+#import "Common/ShaderLib/GLSLCompat.glsllib"
+
uniform sampler3D m_Texture;
varying vec3 texCoord;
void main(){
gl_FragColor= texture3D(m_Texture,texCoord);
-}
\ No newline at end of file
+}
diff --git a/jme3-examples/src/main/resources/jme3test/texture/tex3D.j3md b/jme3-examples/src/main/resources/jme3test/texture/tex3D.j3md
index 1ba2605948..61b35c99aa 100644
--- a/jme3-examples/src/main/resources/jme3test/texture/tex3D.j3md
+++ b/jme3-examples/src/main/resources/jme3test/texture/tex3D.j3md
@@ -5,8 +5,8 @@ MaterialDef My MaterialDef {
}
Technique {
- VertexShader GLSL100: jme3test/texture/tex3D.vert
- FragmentShader GLSL100: jme3test/texture/tex3D.frag
+ VertexShader GLSL300 GLSL100: jme3test/texture/tex3D.vert
+ FragmentShader GLSL300 GLSL100: jme3test/texture/tex3D.frag
WorldParameters {
WorldViewProjectionMatrix
diff --git a/jme3-examples/src/main/resources/jme3test/texture/tex3D.vert b/jme3-examples/src/main/resources/jme3test/texture/tex3D.vert
index f91b7b3097..4681a36250 100644
--- a/jme3-examples/src/main/resources/jme3test/texture/tex3D.vert
+++ b/jme3-examples/src/main/resources/jme3test/texture/tex3D.vert
@@ -1,3 +1,5 @@
+#import "Common/ShaderLib/GLSLCompat.glsllib"
+
uniform mat4 g_WorldViewProjectionMatrix;
attribute vec3 inTexCoord;
@@ -8,4 +10,4 @@ varying vec3 texCoord;
void main(){
gl_Position = g_WorldViewProjectionMatrix * vec4(inPosition,1.0);
texCoord=inTexCoord;
-}
\ No newline at end of file
+}
diff --git a/jme3-examples/src/main/resources/jme3test/texture/tex3DThumb.frag b/jme3-examples/src/main/resources/jme3test/texture/tex3DThumb.frag
index e70bc5b25a..9664f996a4 100644
--- a/jme3-examples/src/main/resources/jme3test/texture/tex3DThumb.frag
+++ b/jme3-examples/src/main/resources/jme3test/texture/tex3DThumb.frag
@@ -1,3 +1,5 @@
+#import "Common/ShaderLib/GLSLCompat.glsllib"
+
uniform sampler3D m_Texture;
uniform int m_Rows;
uniform float m_InvDepth;
@@ -12,4 +14,4 @@ void main(){
vec3 texC = vec3(fract(texCoord.x),fract(texCoord.y),(depthy * rows + depthx) * m_InvDepth);
gl_FragColor = texture3D(m_Texture, texC);
-}
\ No newline at end of file
+}
diff --git a/jme3-examples/src/main/resources/jme3test/texture/tex3DThumb.j3md b/jme3-examples/src/main/resources/jme3test/texture/tex3DThumb.j3md
index a42bd381ed..ee00681d34 100644
--- a/jme3-examples/src/main/resources/jme3test/texture/tex3DThumb.j3md
+++ b/jme3-examples/src/main/resources/jme3test/texture/tex3DThumb.j3md
@@ -7,8 +7,8 @@ MaterialDef Tex3DThumb {
}
Technique {
- VertexShader GLSL100: jme3test/texture/tex3DThumb.vert
- FragmentShader GLSL100: jme3test/texture/tex3DThumb.frag
+ VertexShader GLSL300 GLSL100: jme3test/texture/tex3DThumb.vert
+ FragmentShader GLSL300 GLSL100: jme3test/texture/tex3DThumb.frag
WorldParameters {
WorldViewProjectionMatrix
diff --git a/jme3-examples/src/main/resources/jme3test/texture/tex3DThumb.vert b/jme3-examples/src/main/resources/jme3test/texture/tex3DThumb.vert
index 6d27bc030c..2514cb532c 100644
--- a/jme3-examples/src/main/resources/jme3test/texture/tex3DThumb.vert
+++ b/jme3-examples/src/main/resources/jme3test/texture/tex3DThumb.vert
@@ -1,3 +1,5 @@
+#import "Common/ShaderLib/GLSLCompat.glsllib"
+
uniform mat4 g_WorldViewProjectionMatrix;
attribute vec2 inTexCoord;
@@ -8,4 +10,4 @@ varying vec2 texCoord;
void main(){
gl_Position = g_WorldViewProjectionMatrix * vec4(inPosition,1.0);
texCoord=inTexCoord;
-}
\ No newline at end of file
+}
diff --git a/jme3-jbullet/src/main/java/com/jme3/bullet/PhysicsSpace.java b/jme3-jbullet/src/main/java/com/jme3/bullet/PhysicsSpace.java
index 2099f7f23f..42ac5040a5 100644
--- a/jme3-jbullet/src/main/java/com/jme3/bullet/PhysicsSpace.java
+++ b/jme3-jbullet/src/main/java/com/jme3/bullet/PhysicsSpace.java
@@ -788,7 +788,7 @@ public float addSingleResult(LocalRayResult lrr, boolean bln) {
/**
* Performs a sweep collision test and returns the results as a list of PhysicsSweepTestResults
- * You have to use different Transforms for start and end (at least distance > 0.4f).
+ * You have to use different Transforms for start and end (at least distance greater than 0.4f).
* SweepTest will not see a collision if it starts INSIDE an object and is moving AWAY from its center.
*/
public List sweepTest(CollisionShape shape, Transform start, Transform end) {
@@ -804,7 +804,7 @@ public List sweepTest(CollisionShape shape, Transform st
/**
* Performs a sweep collision test and returns the results as a list of PhysicsSweepTestResults
- * You have to use different Transforms for start and end (at least distance > 0.4f).
+ * You have to use different Transforms for start and end (at least distance greater than 0.4f).
* SweepTest will not see a collision if it starts INSIDE an object and is moving AWAY from its center.
*/
public List sweepTest(CollisionShape shape, Transform start, Transform end, List results) {
@@ -917,7 +917,7 @@ public void setWorldMax(Vector3f worldMax) {
*
* The default is 10. Use 4 for low quality, 20 for high quality.
*
- * @param numIterations The number of iterations used by the contact & constraint solver.
+ * @param numIterations The number of iterations used by the contact and constraint solver.
*/
public void setSolverNumIterations(int numIterations) {
dynamicsWorld.getSolverInfo().numIterations = numIterations;
diff --git a/jme3-jbullet/src/main/java/com/jme3/bullet/collision/shapes/GImpactCollisionShape.java b/jme3-jbullet/src/main/java/com/jme3/bullet/collision/shapes/GImpactCollisionShape.java
index 5a7921fc0e..8dfe2b2f63 100644
--- a/jme3-jbullet/src/main/java/com/jme3/bullet/collision/shapes/GImpactCollisionShape.java
+++ b/jme3-jbullet/src/main/java/com/jme3/bullet/collision/shapes/GImpactCollisionShape.java
@@ -125,9 +125,14 @@ protected void createShape() {
TriangleIndexVertexArray tiv = new TriangleIndexVertexArray(numTriangles, triangleIndexBase, triangleIndexStride, numVertices, vertexBase, vertexStride);
cShape = new GImpactMeshShape(tiv);
cShape.setLocalScaling(Converter.convert(worldScale));
- ((GImpactMeshShape)cShape).updateBound();
cShape.setLocalScaling(Converter.convert(getScale()));
cShape.setMargin(margin);
+ ((GImpactMeshShape) cShape).updateBound();
}
+ @Override
+ public void setScale(Vector3f scale) {
+ super.setScale(scale);
+ ((GImpactMeshShape) cShape).updateBound();
+ }
}
diff --git a/jme3-jbullet/src/main/java/com/jme3/bullet/objects/PhysicsVehicle.java b/jme3-jbullet/src/main/java/com/jme3/bullet/objects/PhysicsVehicle.java
index 529cb9c86e..b0bccaa4b3 100644
--- a/jme3-jbullet/src/main/java/com/jme3/bullet/objects/PhysicsVehicle.java
+++ b/jme3-jbullet/src/main/java/com/jme3/bullet/objects/PhysicsVehicle.java
@@ -301,7 +301,7 @@ public float getSuspensionCompression() {
* After adding the wheel, use direct wheel access.
* The damping coefficient for when the suspension is compressed.
* Set to k * 2.0 * FastMath.sqrt(m_suspensionStiffness) so k is proportional to critical damping.
- * k = 0.0 undamped & bouncy, k = 1.0 critical damping
+ * k = 0.0 undamped/bouncy, k = 1.0 critical damping
* 0.1 to 0.3 are good values
* @param suspensionCompression the suspensionCompression to set
*/
@@ -312,7 +312,7 @@ public void setSuspensionCompression(float suspensionCompression) {
/**
* The damping coefficient for when the suspension is compressed.
* Set to k * 2.0 * FastMath.sqrt(m_suspensionStiffness) so k is proportional to critical damping.
- * k = 0.0 undamped & bouncy, k = 1.0 critical damping
+ * k = 0.0 undamped/bouncy, k = 1.0 critical damping
* 0.1 to 0.3 are good values
* @param wheel
* @param suspensionCompression
diff --git a/jme3-jbullet/src/main/java/com/jme3/bullet/objects/VehicleWheel.java b/jme3-jbullet/src/main/java/com/jme3/bullet/objects/VehicleWheel.java
index 789e0c6828..0490626a96 100644
--- a/jme3-jbullet/src/main/java/com/jme3/bullet/objects/VehicleWheel.java
+++ b/jme3-jbullet/src/main/java/com/jme3/bullet/objects/VehicleWheel.java
@@ -178,7 +178,7 @@ public float getWheelsDampingCompression() {
/**
* the damping coefficient for when the suspension is compressed.
* Set to k * 2.0 * FastMath.sqrt(m_suspensionStiffness) so k is proportional to critical damping.
- * k = 0.0 undamped & bouncy, k = 1.0 critical damping
+ * k = 0.0 undamped/bouncy, k = 1.0 critical damping
* 0.1 to 0.3 are good values
* @param wheelsDampingCompression
*/
diff --git a/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglContext.java b/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglContext.java
index 624ad3e027..4d2d776c52 100644
--- a/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglContext.java
+++ b/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglContext.java
@@ -113,12 +113,11 @@ protected int[] getGLVersion(String renderer) {
maj = 2;
min = 0;
break;
- // case AppSettings.LWJGL_OPENGL30:
- // maj=3;
- // min=0;
- // break;
- case AppSettings.LWJGL_OPENGL3:
- // case AppSettings.LWJGL_OPENGL32:
+ case AppSettings.LWJGL_OPENGL30:
+ maj = 3;
+ min = 0;
+ break;
+ case AppSettings.LWJGL_OPENGL32:
maj = 3;
min = 2;
break;
@@ -126,8 +125,7 @@ protected int[] getGLVersion(String renderer) {
maj = 3;
min = 3;
break;
- case AppSettings.LWJGL_OPENGL4:
- // case AppSettings.LWJGL_OPENGL40:
+ case AppSettings.LWJGL_OPENGL40:
maj = 4;
min = 0;
break;
diff --git a/jme3-lwjgl3/build.gradle b/jme3-lwjgl3/build.gradle
index 442aa091e8..324c027b4b 100644
--- a/jme3-lwjgl3/build.gradle
+++ b/jme3-lwjgl3/build.gradle
@@ -2,7 +2,7 @@ if (!hasProperty('mainClass')) {
ext.mainClass = ''
}
-def lwjglVersion = '3.2.1'
+def lwjglVersion = '3.2.3'
sourceCompatibility = '1.8'
diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglContext.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglContext.java
index a34ce795f5..8f3afca85a 100644
--- a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglContext.java
+++ b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglContext.java
@@ -105,9 +105,10 @@ public abstract class LwjglContext implements JmeContext {
private static final Set SUPPORTED_RENDERS = new HashSet<>(Arrays.asList(
AppSettings.LWJGL_OPENGL2,
- AppSettings.LWJGL_OPENGL3,
+ AppSettings.LWJGL_OPENGL30,
+ AppSettings.LWJGL_OPENGL32,
AppSettings.LWJGL_OPENGL33,
- AppSettings.LWJGL_OPENGL4,
+ AppSettings.LWJGL_OPENGL40,
AppSettings.LWJGL_OPENGL41,
AppSettings.LWJGL_OPENGL42,
AppSettings.LWJGL_OPENGL43,
diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglWindow.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglWindow.java
index a5d8254dba..e84c5c3ce6 100644
--- a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglWindow.java
+++ b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglWindow.java
@@ -76,7 +76,11 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
private static final Map RENDER_CONFIGS = new HashMap<>();
static {
- RENDER_CONFIGS.put(AppSettings.LWJGL_OPENGL3, () -> {
+ RENDER_CONFIGS.put(AppSettings.LWJGL_OPENGL30, () -> {
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
+ });
+ RENDER_CONFIGS.put(AppSettings.LWJGL_OPENGL32, () -> {
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
});
@@ -84,7 +88,7 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
});
- RENDER_CONFIGS.put(AppSettings.LWJGL_OPENGL4, () -> {
+ RENDER_CONFIGS.put(AppSettings.LWJGL_OPENGL40, () -> {
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
});
diff --git a/jme3-networking/src/main/java/com/jme3/network/base/ConnectorAdapter.java b/jme3-networking/src/main/java/com/jme3/network/base/ConnectorAdapter.java
index 6f4935f8fb..100747ffd7 100644
--- a/jme3-networking/src/main/java/com/jme3/network/base/ConnectorAdapter.java
+++ b/jme3-networking/src/main/java/com/jme3/network/base/ConnectorAdapter.java
@@ -65,6 +65,7 @@ public class ConnectorAdapter extends Thread
private MessageListener