diff --git a/.classpath b/.classpath
new file mode 100644
index 0000000..acfeeee
--- /dev/null
+++ b/.classpath
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..f547dc2
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+/.gradle/
+/bin/
diff --git a/.project b/.project
new file mode 100644
index 0000000..72f65b4
--- /dev/null
+++ b/.project
@@ -0,0 +1,36 @@
+
+
+ CactusServer
+ Project CactusServer created by Buildship.
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.wst.common.project.facet.core.builder
+
+
+
+
+ org.eclipse.wst.validation.validationbuilder
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.wst.common.project.facet.core.nature
+ org.eclipse.wst.common.modulecore.ModuleCoreNature
+ org.eclipse.jem.workbench.JavaEMFNature
+ org.eclipse.buildship.core.gradleprojectnature
+
+
diff --git a/.settings/org.eclipse.buildship.core.prefs b/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 0000000..408b507
--- /dev/null
+++ b/.settings/org.eclipse.buildship.core.prefs
@@ -0,0 +1,2 @@
+connection.project.dir=
+eclipse.preferences.version=1
diff --git a/.settings/org.eclipse.wst.common.component b/.settings/org.eclipse.wst.common.component
new file mode 100644
index 0000000..daedf95
--- /dev/null
+++ b/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/.settings/org.eclipse.wst.common.project.facet.core.xml b/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 0000000..ebcbb70
--- /dev/null
+++ b/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/WEB-INF/web.xml b/WEB-INF/web.xml
new file mode 100644
index 0000000..1c83f13
--- /dev/null
+++ b/WEB-INF/web.xml
@@ -0,0 +1,5 @@
+
+
+
+ webtest
+
\ No newline at end of file
diff --git a/aopalliance-repackaged-2.5.0-b42.jar b/aopalliance-repackaged-2.5.0-b42.jar
new file mode 100644
index 0000000..83558eb
--- /dev/null
+++ b/aopalliance-repackaged-2.5.0-b42.jar
Binary files differ
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000..40f5044
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,19 @@
+
+apply plugin: 'war'
+apply plugin: 'eclipse-wtp'
+
+repositories {
+ jcenter()
+}
+
+configurations {
+ all*.exclude module: 'servlet-api'
+}
+
+dependencies {
+ compile fileTree(dir: './', includes: ['*.jar'])
+ compile 'org.glassfish.jersey.containers:jersey-container-servlet:2.+'
+ compile group: 'commons-collections', name: 'commons-collections', version: '3.2'
+ compile group: 'javax.servlet', name: 'javax.servlet-api', version: '3.1.0'
+ testCompile group: 'junit', name: 'junit', version: '4.+'
+}
\ No newline at end of file
diff --git a/cdi-api-1.1.jar b/cdi-api-1.1.jar
new file mode 100644
index 0000000..d8aaf7e
--- /dev/null
+++ b/cdi-api-1.1.jar
Binary files differ
diff --git a/cv97r140.jar b/cv97r140.jar
new file mode 100644
index 0000000..b742046
--- /dev/null
+++ b/cv97r140.jar
Binary files differ
diff --git a/el-api-2.2.jar b/el-api-2.2.jar
new file mode 100644
index 0000000..da6730c
--- /dev/null
+++ b/el-api-2.2.jar
Binary files differ
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..27768f1
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..4c637cc
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.3-bin.zip
diff --git a/gradlew b/gradlew
new file mode 100644
index 0000000..cccdd3d
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+ cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 0000000..e95643d
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/hk2-api-2.5.0-b42.jar b/hk2-api-2.5.0-b42.jar
new file mode 100644
index 0000000..c72ce98
--- /dev/null
+++ b/hk2-api-2.5.0-b42.jar
Binary files differ
diff --git a/hk2-locator-2.5.0-b42.jar b/hk2-locator-2.5.0-b42.jar
new file mode 100644
index 0000000..d05a71b
--- /dev/null
+++ b/hk2-locator-2.5.0-b42.jar
Binary files differ
diff --git a/hk2-utils-2.5.0-b42.jar b/hk2-utils-2.5.0-b42.jar
new file mode 100644
index 0000000..fa5066f
--- /dev/null
+++ b/hk2-utils-2.5.0-b42.jar
Binary files differ
diff --git a/j3dcore.jar b/j3dcore.jar
new file mode 100644
index 0000000..aea76e1
--- /dev/null
+++ b/j3dcore.jar
Binary files differ
diff --git a/j3dutils.jar b/j3dutils.jar
new file mode 100644
index 0000000..0e2e9c7
--- /dev/null
+++ b/j3dutils.jar
Binary files differ
diff --git a/javassist-3.22.0-CR2.jar b/javassist-3.22.0-CR2.jar
new file mode 100644
index 0000000..0b02004
--- /dev/null
+++ b/javassist-3.22.0-CR2.jar
Binary files differ
diff --git a/javax.inject-1.jar b/javax.inject-1.jar
new file mode 100644
index 0000000..b2a9d0b
--- /dev/null
+++ b/javax.inject-1.jar
Binary files differ
diff --git a/javax.json-1.1.jar b/javax.json-1.1.jar
new file mode 100644
index 0000000..a47350c
--- /dev/null
+++ b/javax.json-1.1.jar
Binary files differ
diff --git a/javax.json-api-1.1.jar b/javax.json-api-1.1.jar
new file mode 100644
index 0000000..94f556d
--- /dev/null
+++ b/javax.json-api-1.1.jar
Binary files differ
diff --git a/javax.json.bind-api-1.0.jar b/javax.json.bind-api-1.0.jar
new file mode 100644
index 0000000..f971d6f
--- /dev/null
+++ b/javax.json.bind-api-1.0.jar
Binary files differ
diff --git a/javax.servlet-api-3.0.1.jar b/javax.servlet-api-3.0.1.jar
new file mode 100644
index 0000000..4e2edcc
--- /dev/null
+++ b/javax.servlet-api-3.0.1.jar
Binary files differ
diff --git a/jaxb-api-2.2.7.jar b/jaxb-api-2.2.7.jar
new file mode 100644
index 0000000..ae2adee
--- /dev/null
+++ b/jaxb-api-2.2.7.jar
Binary files differ
diff --git a/jboss-interceptors-api_1.1_spec-1.0.0.Beta1.jar b/jboss-interceptors-api_1.1_spec-1.0.0.Beta1.jar
new file mode 100644
index 0000000..9f9fd82
--- /dev/null
+++ b/jboss-interceptors-api_1.1_spec-1.0.0.Beta1.jar
Binary files differ
diff --git a/jersey-client.jar b/jersey-client.jar
new file mode 100644
index 0000000..5a130a7
--- /dev/null
+++ b/jersey-client.jar
Binary files differ
diff --git a/jersey-common.jar b/jersey-common.jar
new file mode 100644
index 0000000..3b35ecc
--- /dev/null
+++ b/jersey-common.jar
Binary files differ
diff --git a/jersey-container-servlet-core.jar b/jersey-container-servlet-core.jar
new file mode 100644
index 0000000..5674f5d
--- /dev/null
+++ b/jersey-container-servlet-core.jar
Binary files differ
diff --git a/jersey-container-servlet.jar b/jersey-container-servlet.jar
new file mode 100644
index 0000000..00f27b2
--- /dev/null
+++ b/jersey-container-servlet.jar
Binary files differ
diff --git a/jersey-hk2.jar b/jersey-hk2.jar
new file mode 100644
index 0000000..2d80a43
--- /dev/null
+++ b/jersey-hk2.jar
Binary files differ
diff --git a/jersey-media-jaxb.jar b/jersey-media-jaxb.jar
new file mode 100644
index 0000000..8211696
--- /dev/null
+++ b/jersey-media-jaxb.jar
Binary files differ
diff --git a/jersey-media-json-binding.jar b/jersey-media-json-binding.jar
new file mode 100644
index 0000000..3007732
--- /dev/null
+++ b/jersey-media-json-binding.jar
Binary files differ
diff --git a/jersey-media-sse.jar b/jersey-media-sse.jar
new file mode 100644
index 0000000..8df13c5
--- /dev/null
+++ b/jersey-media-sse.jar
Binary files differ
diff --git a/jersey-server.jar b/jersey-server.jar
new file mode 100644
index 0000000..71b81bd
--- /dev/null
+++ b/jersey-server.jar
Binary files differ
diff --git a/jsonic-1.3.10-javadoc.jar b/jsonic-1.3.10-javadoc.jar
new file mode 100644
index 0000000..67630af
--- /dev/null
+++ b/jsonic-1.3.10-javadoc.jar
Binary files differ
diff --git a/jsonic-1.3.10-sources.jar b/jsonic-1.3.10-sources.jar
new file mode 100644
index 0000000..a5cc106
--- /dev/null
+++ b/jsonic-1.3.10-sources.jar
Binary files differ
diff --git a/jsonic-1.3.10.jar b/jsonic-1.3.10.jar
new file mode 100644
index 0000000..05ef593
--- /dev/null
+++ b/jsonic-1.3.10.jar
Binary files differ
diff --git a/jsr250-api-1.0.jar b/jsr250-api-1.0.jar
new file mode 100644
index 0000000..c1f29bf
--- /dev/null
+++ b/jsr250-api-1.0.jar
Binary files differ
diff --git a/org.osgi.core-4.2.0.jar b/org.osgi.core-4.2.0.jar
new file mode 100644
index 0000000..b986ac1
--- /dev/null
+++ b/org.osgi.core-4.2.0.jar
Binary files differ
diff --git a/persistence-api-1.0.jar b/persistence-api-1.0.jar
new file mode 100644
index 0000000..fe5dbcd
--- /dev/null
+++ b/persistence-api-1.0.jar
Binary files differ
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000..c7c0479
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1,18 @@
+/*
+ * This settings file was generated by the Gradle 'init' task.
+ *
+ * The settings file is used to specify which projects to include in your build.
+ * In a single project build this file can be empty or even removed.
+ *
+ * Detailed information about configuring a multi-project build in Gradle can be found
+ * in the user guide at https://docs.gradle.org/4.3/userguide/multi_project_builds.html
+ */
+
+/*
+// To declare projects as part of a multi-project build use the 'include' method
+include 'shared'
+include 'api'
+include 'services:webservice'
+*/
+
+rootProject.name = 'CactusServer'
diff --git a/src/main/java/fight3D/Attackable.java b/src/main/java/fight3D/Attackable.java
new file mode 100644
index 0000000..28e63d3
--- /dev/null
+++ b/src/main/java/fight3D/Attackable.java
@@ -0,0 +1,19 @@
+package fight3D;
+import javax.media.j3d.BranchGroup;
+
+import framework.model3D.Object3D;
+
+
+public interface Attackable {
+
+ abstract public Object3D getBody();
+ abstract public String getPartName();
+ abstract public Player getOwner();
+ abstract public int getAP();
+ abstract public boolean isMovable();
+ abstract public boolean isAlive();
+ abstract public void appear();
+ abstract public void disappear();
+ abstract public boolean isActivate();
+
+}
diff --git a/src/main/java/fight3D/AttackingPart.java b/src/main/java/fight3D/AttackingPart.java
new file mode 100644
index 0000000..8b26717
--- /dev/null
+++ b/src/main/java/fight3D/AttackingPart.java
@@ -0,0 +1,88 @@
+package fight3D;
+import javax.media.j3d.BranchGroup;
+
+import framework.model3D.Object3D;
+
+
+/**
+ * �v���C���[�̑̂̒��̍U���Ɏg�p���Ă��镔��
+ * @author �V�c����
+ *
+ */
+public class AttackingPart implements Attackable {
+
+ private String partName = null;
+ private Player owner;
+ private boolean fActive = true;
+ private long timeLag = 0; // �U���������n�߂�܂ł̎��ԁi�������ԁj
+
+ //�R���X�g���N�^
+ public AttackingPart(String pn, Player o, long t){
+ partName = pn;
+ owner = o;
+ timeLag = t;
+ }
+
+ @Override
+ //�U���͂�Ԃ�
+ public int getAP() {
+ // TODO Auto-generated method stub
+ return owner.character.getPower();
+ }
+
+ @Override
+ //���́i�R�����j�̌`��������
+ public Object3D getBody() {
+ // TODO Auto-generated method stub
+ return owner.body;
+
+ }
+
+ @Override
+ public String getPartName() {
+ // TODO Auto-generated method stub
+ return partName;
+ }
+
+ @Override
+ //�N���U���������i�L���ȍU���j
+ public Player getOwner() {
+ // TODO Auto-generated method stub
+ return owner;
+ }
+
+ @Override
+ //�U�����镨�i�̂̈ꕔ�═��j�ƈꏏ�Ɏ��g���������Ƃ��ł��邩
+ public boolean isMovable() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ //�U�����I�������A������
+ void onEndAnimation() {
+ disappear();
+ }
+
+ //���݂��Ă��邩
+ public boolean isAlive() {
+ return fActive;
+ }
+
+ @Override
+ public void appear() {
+ // TODO Auto-generated method stub
+ fActive = true;
+ }
+
+ @Override
+ public void disappear() {
+ // TODO Auto-generated method stub
+ fActive = false;
+ }
+
+ @Override
+ public boolean isActivate() {
+ // TODO Auto-generated method stub
+ return (owner.animation.time >= timeLag);
+ }
+}
diff --git a/src/main/java/fight3D/Character.java b/src/main/java/fight3D/Character.java
new file mode 100644
index 0000000..90c499f
--- /dev/null
+++ b/src/main/java/fight3D/Character.java
@@ -0,0 +1,295 @@
+package fight3D;
+import framework.animation.Animation3D;
+import framework.audio.Sound3D;
+import framework.gameMain.Mode;
+import framework.gameMain.ModeOnGround;
+import framework.gameMain.ActorModel;
+import framework.physics.Velocity3D;
+
+
+
+public class Character extends ActorModel {
+
+ private String name, comment;
+ private String attackingPartName = null;
+ private String upperAttackingPartName = null;
+ private String jumpAttackingPartName = null;
+ private long attackTimeLag = 0;
+ private long upperAttackTimeLag = 0;
+ private long jumpAttackTimeLag = 0;
+ private WeaponModel weaponModel, upperWeaponModel, jumpWeaponModel;
+ private Velocity3D weaponSpeed = new Velocity3D(4.0, 0.0, 0.0);
+ private Velocity3D upperWeaponSpeed = new Velocity3D(4.0, 0.0, 0.0);
+ private Velocity3D jumpWeaponSpeed = new Velocity3D(4.0, 0.0, 0.0);
+ private double runSpeed = 5.0, jumpPower = 10.0;
+ private int p, jf, d, s;
+
+
+ private static Animation3D defaultAnimation = new Animation3D();
+ public Animation3D rightMoveAnimation = defaultAnimation;
+ public Animation3D leftMoveAnimation = defaultAnimation;
+ public Animation3D jumpAnimation = defaultAnimation;
+ public Animation3D damagedAnimation = defaultAnimation;
+ public Animation3D attackAnimation = defaultAnimation;
+ public Animation3D upperAttackAnimation = defaultAnimation;
+ public Animation3D jumpAttackAnimation = defaultAnimation;
+ public Sound3D jumpSound = null;
+ public Sound3D attackSound = null;
+ public Sound3D upperAttackSound = null;
+ public Sound3D jumpAttackSound = null;
+ public Sound3D damagedSound = null;
+
+ public Character(String fileName) {
+ super(fileName);
+ }
+
+ /**
+ * �A�j���[�V������Ԃ�
+ * @param m �v���C���[�̃��[�h
+ * @param s �v���C���[�̏��
+ * @return �A�j���[�V����
+ */
+ public Animation3D getAnimation(Mode m, State s) {
+ if(m instanceof ModeOnGround) {
+ //���E�ɓ����A�j���[�V�����͒n��ɂ���Ƃ��̂�
+ if(s instanceof StateLeftMove) {
+ return new Animation3D(leftMoveAnimation);
+ }
+ else if(s instanceof StateRightMove) {
+ return new Animation3D(rightMoveAnimation);
+ }
+ }
+ if(s instanceof StateJump) {
+ return new Animation3D(jumpAnimation);
+ }
+ else if(s instanceof StateAttack){
+ return new Animation3D(attackAnimation);
+ }
+ else if(s instanceof StateUpperAttack){
+ return new Animation3D(upperAttackAnimation);
+ }
+ else if(s instanceof StateJumpAttack){
+ return new Animation3D(jumpAttackAnimation);
+ }
+ else if(s instanceof StateDamaged){
+ return new Animation3D(damagedAnimation);
+ }
+ return new Animation3D(defaultAnimation);
+ }
+
+ /**
+ * ���ʉ���Ԃ�
+ * @param m �v���C���[�̃��[�h
+ * @param s �v���C���[�̏��
+ * @return ���ʉ�
+ */
+ public Sound3D getSoundEffect(Mode m, State s) {
+ if(s instanceof StateJump) {
+ return jumpSound;
+ }
+ else if(s instanceof StateAttack){
+ return attackSound;
+ }
+ else if(s instanceof StateUpperAttack){
+ return upperAttackSound;
+ }
+ else if(s instanceof StateJumpAttack){
+ return jumpAttackSound;
+ }
+ else if(s instanceof StateDamaged){
+ return damagedSound;
+ }
+ return null;
+ }
+
+// public Attackable getAttackable(Player p){
+// Attackable a = new AttackingPart(attackingPartName , p);
+// return a;
+// }
+
+ public void setName(String n) {
+ name = n;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setComment(String comment) {
+ this.comment = comment;
+ }
+
+ public String getComment() {
+ return comment;
+ }
+
+ // �U�����镔���̖��O�i�ʏ�U���A������̍U���A�������̍U���j
+ public void setAttackingPartName(String apn) {
+ attackingPartName = apn;
+ }
+ public String getAttackingPartName() {
+ return attackingPartName;
+ }
+
+ public void setUpperAttackingPartName(String s) {
+ upperAttackingPartName = s;
+ }
+
+ public String getUpperAttackingPartName() {
+ return upperAttackingPartName;
+ }
+
+ public void setJumpAttackingPartName(String s) {
+ jumpAttackingPartName = s;
+ }
+
+ public String getJumpAttackingPartName() {
+ return jumpAttackingPartName;
+ }
+
+ // ���탂�f���i�ʏ�U���A������̍U���A�������̍U���j
+ public void setWeaponModel(WeaponModel w) {
+ weaponModel = w;
+ }
+ public WeaponModel getWeaponModel() {
+ return weaponModel;
+ }
+
+ public void setUpperWeaponModel(WeaponModel w) {
+ upperWeaponModel = w;
+ }
+
+ public WeaponModel getUpperWeaponModel() {
+ return upperWeaponModel;
+ }
+
+ public void setJumpWeaponModel(WeaponModel w) {
+ jumpWeaponModel = w;
+ }
+
+ public WeaponModel getJumpWeaponModel() {
+ return jumpWeaponModel;
+ }
+
+ //��ѓ���̑����i�ʏ�U���A������̍U���A�������̍U���j
+ public void setWeaponSpeed(double x, double y, double z) {
+ this.weaponSpeed = new Velocity3D(x, y, z);
+ }
+
+ public Velocity3D getWeaponSpeed() {
+ return weaponSpeed;
+ }
+
+ public void setUpperWeaponSpeed(double x, double y, double z) {
+ upperWeaponSpeed = new Velocity3D(x, y, z);
+ }
+
+ public Velocity3D getUpperWeaponSpeed() {
+ return upperWeaponSpeed;
+ }
+
+ public void setJumpWeaponSpeed(double x, double y, double z) {
+ jumpWeaponSpeed = new Velocity3D(x, y, z);
+ }
+
+ public Velocity3D getJumpWeaponSpeed() {
+ return jumpWeaponSpeed;
+ }
+
+ //�ړ��̑���
+ public void setRunSpeed(double rs) {
+ this.runSpeed = rs;
+ }
+
+ public double getRunSpeed() {
+ return runSpeed;
+ }
+
+ //�U����
+ public void setPower(int p) {
+ this.p = p;
+ }
+
+ public int getPower() {
+ return p;
+ }
+
+ //�W�����v��
+ public void setJumpPower(double e) {
+ this.jumpPower = e;
+ }
+
+ public double getJumpPower() {
+ return jumpPower;
+ }
+
+ //�W�����v��
+ public void setJumpFrequency(int jf) {
+ this.jf = jf;
+ }
+
+ public int getJumpFrequency() {
+ return jf;
+ }
+
+ //�h���
+ public void setDefense(int d) {
+ this.d = d;
+ }
+
+ public int getDefense() {
+ return d;
+ }
+
+ public void setSize(int s) {
+ this.s = s;
+ }
+
+ public int getSize() {
+ return s;
+ }
+
+ //Weapon��AttackingPart�Ƃǂ���������Ă��邩�����\�b�h
+ public boolean hasAttackingPart(){
+ if(getAttackingPartName() != null)
+ return true;
+ else return false;
+ }
+
+ public boolean hasUpperAttackingPart(){
+ if(getUpperAttackingPartName() != null)
+ return true;
+ else return false;
+ }
+
+ public boolean hasJumpAttackingPart(){
+ if(getJumpAttackingPartName() != null)
+ return true;
+ else return false;
+ }
+
+ public void setAttackTimeLag(long attackTimeLag) {
+ this.attackTimeLag = attackTimeLag;
+ }
+
+ public long getAttackTimeLag() {
+ return attackTimeLag;
+ }
+
+ public void setUpperAttackTimeLag(long upperAttackTimeLag) {
+ this.upperAttackTimeLag = upperAttackTimeLag;
+ }
+
+ public long getUpperAttackTimeLag() {
+ return upperAttackTimeLag;
+ }
+
+ public void setJumpAttackTimeLag(long jumpAttackTimeLag) {
+ this.jumpAttackTimeLag = jumpAttackTimeLag;
+ }
+
+ public long getJumpAttackTimeLag() {
+ return jumpAttackTimeLag;
+ }
+
+}
diff --git a/src/main/java/fight3D/CharacterManager.java b/src/main/java/fight3D/CharacterManager.java
new file mode 100644
index 0000000..9e63f0f
--- /dev/null
+++ b/src/main/java/fight3D/CharacterManager.java
@@ -0,0 +1,305 @@
+package fight3D;
+
+import java.util.ArrayList;
+
+import framework.animation.Animation3D;
+import framework.animation.AnimationFactory;
+import framework.audio.Sound3D;
+import framework.gameMain.AbstractManager;
+
+public class CharacterManager extends AbstractManager{
+
+ private static CharacterManager theInstance = null;
+
+ private static String filename = "data";
+ private static String characterFile = "character.def";
+
+ private static final String NAME_TAG = "Name";
+ private static final String MODEL_FILE_TAG = "ModelFile";
+ private static final String RIGHTMOVE_ANIMATION_FILE_TAG = "RightMoveAnimationFile";
+ private static final String LEFTMOVE_ANIMATION_FILE_TAG = "LeftMoveAnimationFile";
+
+ private static final String JUMP_ANIMATION_FILE_TAG = "JumpAnimationFile";
+ private static final String JUMP_SOUND_FILE_TAG = "JumpSoundFile";
+ private static final String JUMP_POWER_TAG = "JumpPower";
+ private static final String JUMP_FREQUENCY_TAG = "JumpFrequency";
+
+ private static final String DAMAGED_ANIMATION_FILE_TAG = "DamagedAnimationFile";
+ private static final String DAMAGED_SOUND_FILE_TAG = "DamagedSoundFile";
+
+ private static final String RUN_SPEED_TAG = "RunSpeed";
+ private static final String POWER_TAG = "Power";
+ private static final String DEFENSE_TAG = "Defense";
+
+ private static final String ATTACKING_PART_NAME_TAG = "AttackingPartName";
+ private static final String ATTACK_ANIMATION_FILE_TAG = "AttackAnimationFile";
+ private static final String ATTACK_SOUND_FILE_TAG = "AttackSoundFile";
+ private static final String ATTACK_TIME_LAG_TAG = "AttackTimeLag";
+ private static final String WEAPON_FILE_TAG = "WeaponFile";
+ private static final String WEAPON_ANIMATION_FILE_TAG = "WeaponAnimationFile";
+ private static final String WEAPON_SPEED_TAG = "WeaponSpeed";
+
+ private static final String UPPER_ATTACKING_PART_NAME_TAG = "UpperAttackingPartName";
+ private static final String UPPER_ATTACK_ANIMATION_FILE_TAG = "UpperAttackAnimationFile";
+ private static final String UPPER_ATTACK_SOUND_FILE_TAG = "UpperAttackSoundFile";
+ private static final String UPPER_ATTACK_TIME_LAG_TAG = "UpperAttackTimeLag";
+ private static final String UPPER_WEAPON_FILE_TAG = "UpperWeaponFile";
+ private static final String UPPER_WEAPON_ANIMATION_FILE_TAG = "UpperWeaponAnimationFile";
+ private static final String UPPER_WEAPON_SPEED_TAG = "UpperWeaponSpeed";
+
+ private static final String JUMP_ATTACKING_PART_NAME_TAG = "JumpAttackingPartName";
+ private static final String JUMP_ATTACK_ANIMATION_FILE_TAG = "JumpAttackAnimationFile";
+ private static final String JUMP_ATTACK_SOUND_FILE_TAG = "JumpAttackSoundFile";
+ private static final String JUMP_ATTACK_TIME_LAG_TAG = "JumpAttackTimeLag";
+ private static final String JUMP_WEAPON_FILE_TAG = "JumpWeaponFile";
+ private static final String JUMP_WEAPON_ANIMATION_FILE_TAG = "JumpWeaponAnimationFile";
+ private static final String JUMP_WEAPON_SPEED_TAG = "JumpWeaponSpeed";
+
+ private static final String SIZE_TAG = "Size";
+
+ private static final String COMMENT_TAG = "Comment";
+
+ private ArrayList characterList = new ArrayList();
+
+ private CharacterManager() {
+ addSeekFile(characterFile);
+ setTag(NAME_TAG);
+ setTag(MODEL_FILE_TAG);
+ setTag(RIGHTMOVE_ANIMATION_FILE_TAG);
+ setTag(LEFTMOVE_ANIMATION_FILE_TAG);
+ setTag(JUMP_ANIMATION_FILE_TAG);
+ setTag(JUMP_SOUND_FILE_TAG);
+ setTag(JUMP_POWER_TAG);
+ setTag(JUMP_FREQUENCY_TAG);
+ setTag(DAMAGED_ANIMATION_FILE_TAG);
+ setTag(DAMAGED_SOUND_FILE_TAG);
+ setTag(RUN_SPEED_TAG);
+ setTag(POWER_TAG);
+ setTag(DEFENSE_TAG);
+ setTag(ATTACKING_PART_NAME_TAG);
+ setTag(ATTACK_ANIMATION_FILE_TAG);
+ setTag(ATTACK_SOUND_FILE_TAG);
+ setTag(ATTACK_TIME_LAG_TAG);
+ setTag(WEAPON_FILE_TAG);
+ setTag(WEAPON_ANIMATION_FILE_TAG);
+ setTag(WEAPON_SPEED_TAG);
+ setTag(UPPER_ATTACKING_PART_NAME_TAG);
+ setTag(UPPER_ATTACK_ANIMATION_FILE_TAG);
+ setTag(UPPER_ATTACK_SOUND_FILE_TAG);
+ setTag(UPPER_ATTACK_TIME_LAG_TAG);
+ setTag(UPPER_WEAPON_FILE_TAG);
+ setTag(UPPER_WEAPON_ANIMATION_FILE_TAG);
+ setTag(UPPER_WEAPON_SPEED_TAG);
+ setTag(JUMP_ATTACKING_PART_NAME_TAG);
+ setTag(JUMP_ATTACK_ANIMATION_FILE_TAG);
+ setTag(JUMP_ATTACK_SOUND_FILE_TAG);
+ setTag(JUMP_ATTACK_TIME_LAG_TAG);
+ setTag(JUMP_WEAPON_FILE_TAG);
+ setTag(JUMP_WEAPON_ANIMATION_FILE_TAG);
+ setTag(JUMP_WEAPON_SPEED_TAG);
+ setTag(SIZE_TAG);
+ setTag(COMMENT_TAG);
+ seek(filename);
+ }
+
+ static public CharacterManager getInstance() {
+ if(theInstance == null) {
+ theInstance = new CharacterManager();
+ }
+ return theInstance;
+ }
+
+ /**
+ * �L�����N�^�[��Ԃ��܂��B
+ * @param id�L�����N�^�[�i���o�[
+ * @return
+ */
+ public Character getCharacter(int id) {
+ if(id < characterList.size()) {
+ return characterList.get(id);
+ }
+ else {
+ return null;
+ }
+ }
+
+ /**
+ * �L�����N�^�[�̐���Ԃ��܂��B
+ * @return
+ */
+ public int getNumberOfCharacters() {
+ return characterList.size();
+ }
+
+ @Override
+ protected void create() {
+ // TODO Auto-generated method stub
+ Character p = new Character(getData(MODEL_FILE_TAG));
+ //WeaponModel w = new WeaponModel(getData(WEAPON_FILE_TAG));
+ //p.setWeponModel(w);
+
+ // �L�����N�^��
+ p.setName(getData(NAME_TAG));
+
+ // �L�����N�^�̐���
+ p.setComment(getData(COMMENT_TAG));
+
+ // �A�j���[�V�����t�@�C��
+ if(getData(RIGHTMOVE_ANIMATION_FILE_TAG) != null) {
+ Animation3D animation = AnimationFactory.loadAnimation(getData(RIGHTMOVE_ANIMATION_FILE_TAG));
+ if(animation != null) {
+ p.rightMoveAnimation = animation;
+ }
+ }
+ if(getData(LEFTMOVE_ANIMATION_FILE_TAG) != null) {
+ Animation3D animation = AnimationFactory.loadAnimation(getData(LEFTMOVE_ANIMATION_FILE_TAG));
+ if(animation != null) {
+ p.leftMoveAnimation = animation;
+ }
+ }
+ if(getData(JUMP_ANIMATION_FILE_TAG) != null) {
+ Animation3D animation = AnimationFactory.loadAnimation(getData(JUMP_ANIMATION_FILE_TAG));
+ if(animation != null) {
+ p.jumpAnimation = animation;
+ }
+ }
+ if(hasData(JUMP_SOUND_FILE_TAG)) {
+ Sound3D sound = new Sound3D(getData(JUMP_SOUND_FILE_TAG));
+ if(sound != null) {
+ p.jumpSound = sound;
+ }
+ }
+ if(getData(DAMAGED_ANIMATION_FILE_TAG) != null) {
+ Animation3D animation = AnimationFactory.loadAnimation(getData(DAMAGED_ANIMATION_FILE_TAG));
+ if(animation != null) {
+ p.damagedAnimation = animation;
+ }
+ }
+ if(hasData(DAMAGED_SOUND_FILE_TAG)) {
+ Sound3D sound = new Sound3D(getData(DAMAGED_SOUND_FILE_TAG));
+ if(sound != null) {
+ p.damagedSound = sound;
+ }
+ }
+
+ // �p�����[�^
+ if(!hasData(RUN_SPEED_TAG)) System.out.println("Error!! No RunSpeed data.");
+ else p.setRunSpeed(Double.parseDouble(getData(RUN_SPEED_TAG)));
+ if(!hasData(POWER_TAG)) System.out.println("Error!! No Power data.");
+ else p.setPower(Integer.parseInt(getData(POWER_TAG)));
+ if(!hasData(JUMP_POWER_TAG)) System.out.println("Error!! No JumpPower data.");
+ else p.setJumpPower(Double.parseDouble(getData(JUMP_POWER_TAG)));
+ if(!hasData(JUMP_FREQUENCY_TAG)) System.out.println("Error!! No JumpFrequency data.");
+ else p.setJumpFrequency(Integer.parseInt(getData(JUMP_FREQUENCY_TAG)));
+ if(!hasData(DEFENSE_TAG)) System.out.println("Error!! No Defense data.");
+ else p.setDefense(Integer.parseInt(getData(DEFENSE_TAG)));
+ if(!hasData(SIZE_TAG)) System.out.println("Error!! No Size data.");
+ else p.setSize(Integer.parseInt(getData(SIZE_TAG)));
+
+ // �ʏ�̍U���i�����U���j
+ if(getData(ATTACK_ANIMATION_FILE_TAG) != null) {
+ Animation3D animation = AnimationFactory.loadAnimation(getData(ATTACK_ANIMATION_FILE_TAG));
+ if(animation != null) {
+ p.attackAnimation = animation;
+ }
+ }
+ if(hasData(ATTACK_SOUND_FILE_TAG)) {
+ Sound3D sound = new Sound3D(getData(ATTACK_SOUND_FILE_TAG));
+ if(sound != null) {
+ p.attackSound = sound;
+ }
+ }
+ if(hasData(ATTACKING_PART_NAME_TAG)) p.setAttackingPartName(getData(ATTACKING_PART_NAME_TAG));
+ if(hasData(ATTACK_TIME_LAG_TAG)) p.setAttackTimeLag(Long.parseLong(getData(ATTACK_TIME_LAG_TAG)));
+ if(hasData(WEAPON_FILE_TAG)) {
+ WeaponModel weapon = new WeaponModel(getData(WEAPON_FILE_TAG));
+ if(hasData(WEAPON_ANIMATION_FILE_TAG)) {
+ Animation3D animation = AnimationFactory.loadAnimation(getData(WEAPON_ANIMATION_FILE_TAG));
+ if(animation != null) {
+ weapon.weaponAnimation = animation;
+ }
+ }
+ p.setWeaponModel(weapon);
+ }
+ if(hasData(WEAPON_SPEED_TAG)) {
+ String vector = getData(WEAPON_SPEED_TAG);
+ String axis[] = vector.split(",");
+ p.setWeaponSpeed(Double.parseDouble(axis[0]),Double.parseDouble(axis[1]),Double.parseDouble(axis[2]));
+ }
+ //ATTACKING_PART_NAME��WEAPON_FILE�̃f�[�^���d������Ƃ��A�ǂ�����f�[�^���Ȃ��Ƃ��A�G���[�B
+ if((!hasData(ATTACKING_PART_NAME_TAG))&&(!hasData(WEAPON_FILE_TAG)))
+ System.out.println("Error!! No Weapon nor AttackingPart data.");
+ else if((hasData(ATTACKING_PART_NAME_TAG))&&(hasData(WEAPON_FILE_TAG)))
+ System.out.println("Error!! Weapon & AttackingPart are overlapping.");
+
+ // ������̍U���i��U���j
+ if(getData(UPPER_ATTACK_ANIMATION_FILE_TAG) != null) {
+ Animation3D animation = AnimationFactory.loadAnimation(getData(UPPER_ATTACK_ANIMATION_FILE_TAG));
+ if(animation != null) {
+ p.upperAttackAnimation = animation;
+ }
+ }
+ if(hasData(UPPER_ATTACK_SOUND_FILE_TAG)) {
+ Sound3D sound = new Sound3D(getData(UPPER_ATTACK_SOUND_FILE_TAG));
+ if(sound != null) {
+ p.upperAttackSound = sound;
+ }
+ }
+ if(hasData(UPPER_ATTACKING_PART_NAME_TAG)) p.setUpperAttackingPartName(getData(UPPER_ATTACKING_PART_NAME_TAG));
+ if(hasData(UPPER_ATTACK_TIME_LAG_TAG)) p.setUpperAttackTimeLag(Long.parseLong(getData(UPPER_ATTACK_TIME_LAG_TAG)));
+ if(hasData(UPPER_WEAPON_FILE_TAG)) {
+ WeaponModel upperWeapon = new WeaponModel(getData(UPPER_WEAPON_FILE_TAG));
+ if(hasData(UPPER_WEAPON_ANIMATION_FILE_TAG)) {
+ Animation3D animation = AnimationFactory.loadAnimation(getData(UPPER_WEAPON_ANIMATION_FILE_TAG));
+ if(animation != null) {
+ upperWeapon.weaponAnimation = animation;
+ }
+ }
+ p.setUpperWeaponModel(upperWeapon);
+ }
+ if(hasData(UPPER_WEAPON_SPEED_TAG)) {
+ String vector = getData(UPPER_WEAPON_SPEED_TAG);
+ String axis[] = vector.split(",");
+ p.setUpperWeaponSpeed(Double.parseDouble(axis[0]),Double.parseDouble(axis[1]),Double.parseDouble(axis[2]));
+ }
+ //UPPER_ATTACKING_PART_NAME��UPPER_WEAPON_FILE�̃f�[�^���d������Ƃ��A�G���[�B
+ if((hasData(UPPER_ATTACKING_PART_NAME_TAG))&&(hasData(UPPER_WEAPON_FILE_TAG)))
+ System.out.println("Error!! Weapon & AttackingPart are overlapping.");
+
+ // �������̍U���i�W�����v�U���j
+ if(getData(JUMP_ATTACK_ANIMATION_FILE_TAG) != null) {
+ Animation3D animation = AnimationFactory.loadAnimation(getData(JUMP_ATTACK_ANIMATION_FILE_TAG));
+ if(animation != null) {
+ p.jumpAttackAnimation = animation;
+ }
+ }
+ if(hasData(JUMP_ATTACK_SOUND_FILE_TAG)) {
+ Sound3D sound = new Sound3D(getData(JUMP_ATTACK_SOUND_FILE_TAG));
+ if(sound != null) {
+ p.jumpAttackSound = sound;
+ }
+ }
+ if(hasData(JUMP_ATTACKING_PART_NAME_TAG)) p.setJumpAttackingPartName(getData(JUMP_ATTACKING_PART_NAME_TAG));
+ if(hasData(JUMP_ATTACK_TIME_LAG_TAG)) p.setJumpAttackTimeLag(Long.parseLong(getData(JUMP_ATTACK_TIME_LAG_TAG)));
+ if(hasData(JUMP_WEAPON_FILE_TAG)) {
+ WeaponModel jumpWeapon = new WeaponModel(getData(JUMP_WEAPON_FILE_TAG));
+ if(hasData(JUMP_WEAPON_ANIMATION_FILE_TAG)) {
+ Animation3D animation = AnimationFactory.loadAnimation(getData(JUMP_WEAPON_ANIMATION_FILE_TAG));
+ if(animation != null) {
+ jumpWeapon.weaponAnimation = animation;
+ }
+ }
+ p.setJumpWeaponModel(jumpWeapon);
+ }
+ if(hasData(JUMP_WEAPON_SPEED_TAG)) {
+ String vector = getData(JUMP_WEAPON_SPEED_TAG);
+ String axis[] = vector.split(",");
+ p.setJumpWeaponSpeed(Double.parseDouble(axis[0]),Double.parseDouble(axis[1]),Double.parseDouble(axis[2]));
+ }
+ //JUMP_ATTACKING_PART_NAME��JUMP_WEAPON_FILE�̃f�[�^���d������Ƃ��A�G���[�B
+ if((hasData(JUMP_ATTACKING_PART_NAME_TAG))&&(hasData(JUMP_WEAPON_FILE_TAG)))
+ System.out.println("Error!! Weapon & AttackingPart are overlapping.");
+
+ characterList.add(p);
+ }
+}
diff --git a/src/main/java/fight3D/CharacterSelectContainer.java b/src/main/java/fight3D/CharacterSelectContainer.java
new file mode 100644
index 0000000..477e8f1
--- /dev/null
+++ b/src/main/java/fight3D/CharacterSelectContainer.java
@@ -0,0 +1,195 @@
+package fight3D;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.GraphicsConfiguration;
+import java.util.ArrayList;
+
+import framework.RWT.RWTContainer;
+import framework.RWT.RWTLabel;
+import framework.RWT.RWTLine;
+import framework.RWT.RWTSelectionCanvas3D;
+import framework.RWT.RWTVirtualController;
+import framework.RWT.RWTVirtualKey;
+import framework.model3D.BaseObject3D;
+
+public class CharacterSelectContainer extends RWTContainer {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 8354537837334374243L;
+
+ Game game;
+
+ static final int PLAYER_NUM = 2; // ���v���C���[��
+
+ private RWTSelectionCanvas3D objectCanvas;
+ private boolean flag = false; // �m�F��ʂ̃t���O
+ private ArrayList characters = new ArrayList();
+ private int pn = 0;
+ private int character[] = new int[PLAYER_NUM];
+ protected RWTLabel activatedLabel = new RWTLabel();
+ private RWTLabel s1 = new RWTLabel();
+ private RWTLabel s2 = new RWTLabel();
+ private RWTLabel m5 = new RWTLabel();
+ private RWTLabel m6 = new RWTLabel();
+ private RWTLine l1 = new RWTLine();
+ private RWTLine l2 = new RWTLine();
+
+ // �R���X�g���N�^
+ public CharacterSelectContainer(Game g) {
+ game = g;
+ }
+
+ // �t���[���ɒlj����ăT�C�Y���m�肵����ɒ��g���\�z����
+ public void build(GraphicsConfiguration gc) {
+ // ������
+ removeAll();
+ setBackground(Color.BLACK);
+
+ // �L�����N�^�[��`�悷�邽�߂̃L�����o�X(���ΓI�L�����o�X)��lj�
+ objectCanvas = new RWTSelectionCanvas3D();
+ objectCanvas.setRelativePosition(0.03f, 0.675f);
+ objectCanvas.setRelativeSize(0.25f, 0.3f);
+ addCanvas(objectCanvas);
+
+ //��ʃ^�C�g���A�߂�A�C�R���A���b�Z�[�W�G���A�E�P
+ s1.setRelativePosition(0.20f,0.10f);
+ s1.setString("�u�L�����N�^�[�I���v");
+ s1.setColor(Color.WHITE);
+ Font f1 = new Font("",Font.PLAIN,20);
+ s1.setFont(f1);
+ addWidget(s1);
+
+ s2.setRelativePosition(0.025f,0.05f);
+ s2.setString("�a�F�^�C�g����ʂ�");
+ s2.setColor(Color.WHITE);
+ Font f2 = new Font("",Font.PLAIN,8);
+ s2.setFont(f2);
+ addWidget(s2);
+
+ m5.setRelativePosition(0.60f,0.05f);
+ m5.setString((pn+1) + "�o�̓L�����N�^�[��I�����ĉ������B");
+ m5.setColor(Color.YELLOW);
+ addWidget(m5);
+ m6.setRelativePosition(0.60f,0.10f);
+ m6.setString("�`�F����");
+ m6.setColor(Color.YELLOW);
+ addWidget(m6);
+
+ //�S�L�����N�^�[�̐�
+ int n = CharacterManager.getInstance().getNumberOfCharacters(); //�L�����N�^�[�̑���
+ //�S�L�����N�^�[�̓o�^
+ for(int i=0;i playerList = new ArrayList();
+ ArrayList actorList = new ArrayList();
+ ArrayList attackableList = new ArrayList();
+ FightCalculation fightCalculation = new FightCalculation();
+
+ Universe universe;
+ Camera3D camera;
+ Ground stageGround = null;
+
+ FightListener fightListener;
+ private boolean isEnd = false;
+ int rank[];
+ int defeated[];
+ int defeat[];
+ private int tp[];
+ private long startTime = 0;
+ private long leftTime;
+
+ public Fight(RWTCanvas3D canvas, int stagenum, int[] selectedCharacterArray,
+ FightListener fightListener) {
+
+ this.universe = new Universe();
+ this.fightListener = fightListener;
+
+ // �J�����̐ݒ�
+ camera = new Camera3D(universe);
+ camera.setSideView();
+ canvas.attachCamera(camera);
+
+ // �����̐ݒ�
+ createLight(universe);
+
+ // �X�e�[�W�̓ǂݍ���
+ Stage s = StageManager.getInstance().getStage(stagenum);
+ Model3D model = s.getModel();
+ Object3D stageObj = model.createObject();
+ stageGround = new Ground(stageObj);
+ universe.placeAsAReceiver(stageGround);
+ RWTCanvas3D c = (RWTCanvas3D) fightListener;
+ s.setBackgroundSize(new Dimension(c.getWidth(), c.getHeight()));
+ universe.place(s.getBackground());
+
+ // �L�����N�^�̒lj��A����̒lj�
+ for (int i = 0; i < selectedCharacterArray.length; i++) {
+ Player player = createPlayer(selectedCharacterArray[i]);
+ player.setPosition(getPlayersPosition(i, selectedCharacterArray.length));
+ player.placeTo(universe);
+ getPlayerList().add(player);
+ actorList.add(player);
+ camera.addTarget(player.body);
+ player.setHp(fightCalculation.initialiseHP());
+ player.setGp(fightCalculation.initialiseGP());
+ player.setTp(fightCalculation.initialiseTP());
+
+ }
+
+ universe.compile();
+
+ leftTime = ENDTIME;
+ rank = new int[2];
+ }
+
+ void createLight(Universe universe){
+ //����
+ AmbientLight amblight = new AmbientLight(new Color3f(0.5f, 0.5f, 0.5f));
+
+ amblight.setInfluencingBounds(new BoundingSphere(new Point3d(), 10000.0));
+ universe.placeLight(amblight);
+
+ //���s����
+ DirectionalLight dirlight = new DirectionalLight(
+ true, //����ON/OFF
+ new Color3f(1.0f, 1.0f, 1.0f), //���̐F
+ new Vector3f(0.0f, -1.0f, -0.5f) //���̕����x�N�g��
+ );
+ dirlight.setInfluencingBounds(new BoundingSphere(new Point3d(), 10000.0));
+
+ universe.placeLight(dirlight);
+ }
+
+ public Player createPlayer(int id) {
+ Player player;
+ Character c = CharacterManager.getInstance().getCharacter(id);
+ player = new Player(c);
+
+ return player;
+ }
+
+ public void progress(RWTVirtualController controller, long interval) {
+ long curTime = System.currentTimeMillis();
+ if (startTime == 0) {
+ startTime = curTime;
+ }
+
+ // �o�ߎ��Ԃ̌v�Z
+// if (count < 2000) speed[count++] = interval;
+ if (interval > INTERVAL * 3) interval = INTERVAL * 3;
+ leftTime = (ENDTIME - (curTime - startTime));
+ fightListener.update(this);
+
+ // �T���o�߂�����
+ if (leftTime < 0) {
+ isEnd = true;
+ calculateRank();
+ calculateDefeated();
+ calculateDefeat();
+ calculateTP();
+ fightListener.update(this);
+// for (int i = 0; i < count; i++) {
+// System.out.println(speed[i]);
+// }
+ return;
+ }
+
+ // GP�̎��R��
+ for (int i = 0; i < getPlayerList().size(); i++) {
+ getPlayerList().get(i).recoverGp();
+ }
+
+ // �J������
+ camera.adjust(interval);
+
+ // �L�[���͂����������ǂ������L�^����
+ boolean[] flags = new boolean[playerList.size()];
+ for (int p = 0; p < flags.length; p++) {
+ flags[p] = false;
+ }
+ for (int playerNum = 0; playerNum < getPlayerList().size(); playerNum++) {
+ // keys��i�Ԗڂ̒��g�i�L�[���́j���L�����N�^�̂ǂ̓���ɓ��Ă͂܂邩
+ if (controller.isKeyDown(playerNum, RWTVirtualController.UP)) {
+ flags[playerNum] = true;
+ // �U���{�^�����ɉ����Ă��Ȃ��ꍇ�W�����v����
+ if (!controller.isKeyDown(playerNum, RWTVirtualController.BUTTON_A)) getPlayerList().get(playerNum).startJump();
+ }
+ if (controller.isKeyDown(playerNum, RWTVirtualController.RIGHT)) {
+ flags[playerNum] = true;
+ // �U���{�^�����ɉ����Ă��Ȃ��ꍇ�E�ɓ���
+ if (!controller.isKeyDown(playerNum, RWTVirtualController.BUTTON_A)) getPlayerList().get(playerNum).rightMove();
+ }
+ if (controller.isKeyDown(playerNum, RWTVirtualController.LEFT)) {
+ flags[playerNum] = true;
+ // �U���{�^�����ɉ����Ă��Ȃ��ꍇ���ɓ���
+ if (!controller.isKeyDown(playerNum, RWTVirtualController.BUTTON_A)) getPlayerList().get(playerNum).leftMove();
+ }
+ if (controller.isKeyDown(playerNum, RWTVirtualController.BUTTON_B)) {
+ flags[playerNum] = true;
+ // �U���{�^���������Ă��Ȃ��ꍇ�K�[�h�̃��\�b�h���Ă�
+ if (!controller.isKeyDown(playerNum, RWTVirtualController.BUTTON_A)) getPlayerList().get(playerNum).guard();
+ }
+ if (controller.isKeyDown(playerNum, RWTVirtualController.BUTTON_A)) {
+ flags[playerNum] = true;
+ // �U���̃��\�b�h���Ă�
+ Attackable a;
+ Player player = getPlayerList().get(playerNum);
+ if (!player.isOnGround()) {
+ if (player.getElapsedTimeInJumping() > 2L || player.getElapsedTimeInJumping() < 0L) {
+ // �ɂ���Ƃ��͊�{�I�ɃW�����v�U��
+ a = player.startJumpAttack();
+ } else {
+ // �W�����v���Ă����͑�U��������悤�ɂ���
+ // �i�������Ȃ��Ƒ�U�����o�����삪����Ȃ邽�߁j
+ a = player.startUpperAttack();
+ }
+ } else {
+ // �n�ʂɂ���Ƃ�
+ if (controller.isKeyDown(playerNum, RWTVirtualController.UP)) {
+ // ��U��
+ a = player.startUpperAttack();
+ } else {
+ // �ʏ�U��
+ a = player.startNormalAttack();
+ }
+ }
+ if (a != null) {
+ attackableList.add(a);
+ if (a instanceof Weapon) {
+ if (a.isMovable()) {
+ actorList.add((Weapon) a);
+ }
+ }
+ }
+ }
+ }
+ for (int i = 0; i < flags.length; i++) {
+ if (!flags[i]) {
+ getPlayerList().get(i).normal(false);
+ }
+ }
+
+ // �S�o�ꕨ����
+ for (int i = 0; i < actorList.size(); i++) {
+ Actor p = actorList.get(i);
+ // �ړ�
+ p.motion(interval, stageGround);
+ // �͈͊O�ɏo�����ǂ����̔���
+ Position3D pos = p.getPosition();
+ if (pos.getY() < DEFAULT_AREA_BOTTOM
+ || pos.getX() > DEFAULT_AREA_RIGHT
+ || pos.getX() < DEFAULT_AREA_LEFT) {
+ // �͈͊O�ɏo���Ƃ��̏���
+ outOfArea(i);
+ }
+ }
+
+ // �U���̓����蔻��
+ hitJudg();
+ }
+
+ /**
+ * �͈͊O�ɏo���Ƃ��̏���
+ * @param p �Ώە�
+ */
+ private void outOfArea(int index) {
+ Actor p = actorList.get(index);
+ if (p instanceof Player) {
+ playerDefeated(index);
+ } else if (p instanceof Weapon) {
+ ((Weapon)p).disappear();
+ }
+ }
+
+ /**
+ * �U���̓����蔻��ƁA���������Ƃ��̏���
+ */
+ private void hitJudg() {
+ // �����蔻��
+ for (int i = attackableList.size() - 1; i >= 0; i--) {
+
+ Attackable attack = attackableList.get(i);
+ if (attack.isAlive() && attack.isActivate()) {
+ // �U�������L���������ꍇ
+ for (int j = 0; j < getPlayerList().size(); j++) {
+ CollisionResult collisionResult = null;
+ Player attacker = attack.getOwner();
+ Player damagedCandidate = getPlayerList().get(j);
+
+ if (attacker != damagedCandidate) {
+ collisionResult = PhysicsUtility.checkCollision(attack.getBody(),
+ attack.getPartName(),
+ (Object3D) damagedCandidate.body,
+ null);
+ }
+ // �Փ˂��������ꍇ
+ if (collisionResult != null) {
+ // if (attacker != damagedCandidate) {
+
+ if (damagedCandidate.state.getClass() != StateGuard.class) {
+ // �_���[�W����B
+ if (damagedCandidate.state.getClass() == StateFlinch.class) {
+ damagedCandidate.normal(true);
+ damagedCandidate.setGp(100);
+ }
+ damagedCandidate.damaged(attacker.getPosition());
+ int afterHP = (int) fightCalculation.decreaseHP(attack
+ .getAP(), damagedCandidate.getHp(),
+ damagedCandidate.character.getDefense());
+ // �U���ɂ���ăL����������ł��Ȃ��ꍇ
+ if (fightCalculation.isDead(afterHP) != true) {
+ damagedCandidate.setHp(afterHP);
+ // damagedCandidate.changeState(new StateFlinch(),
+ // false);
+ }
+ // ���ꍇ
+ else {
+ // �L�������E�����L�����N�^�́u�|�����v���P���₷
+ attacker.setDefeat(attacker.getDefeat() + 1);
+
+ // �L�������|���ꂽ�Ƃ��̏���
+ playerDefeated(j);
+ }
+ // �U���ɂ��TP�̏㏸
+ int attackerAfterTP = fightCalculation.increaseTP(
+ attack.getAP(), damagedCandidate.getHp(),
+ damagedCandidate.character.getDefense(), attacker.getTp());
+ attacker.setTp(attackerAfterTP);
+ } else {
+ // �_���[�W���Ȃ��B
+ int afterGP = (int) fightCalculation.decreaseGP(attack
+ .getAP(), damagedCandidate.character.getDefense(), damagedCandidate.getGp());
+
+ if (!fightCalculation.isOver(afterGP)) {
+ // �U���ɂ����GP���O�ɂȂ�Ȃ������ꍇ
+ damagedCandidate.setGp(afterGP);
+ } else {
+ // �U���ɂ����GP���O�ɂȂ����ꍇ
+ damagedCandidate.flinch();
+ damagedCandidate.setGp(0);
+ }
+ }
+
+ // �U�������ɂ���
+ attack.disappear();
+ }
+ }
+ }
+ if (!attack.isAlive()) {
+ // �U�����������ɂȂ��Ă����ꍇ�A�U�������X�g����폜
+ attackableList.remove(i);
+ for (int j = 0; j < actorList.size(); j++) {
+ if (actorList.get(j) == attack) {
+ actorList.remove(j);
+ break;
+ }
+ }
+ continue;
+ }
+ }
+ }
+
+ /**
+ * �v���C���[���|���ꂽ�Ƃ��̏���
+ * @param index �|���ꂽ�v���C���[�̔ԍ�
+ */
+ private void playerDefeated(int index) {
+ Player damagedCandidate = getPlayerList().get(index);
+
+ // TP�����炷
+ int damagedAfterTP = fightCalculation
+ .decreaseTP(damagedCandidate.getTp());
+ damagedCandidate.setTp(damagedAfterTP);
+
+ // ���L�����N�^�́u���S�v���P���₷
+ damagedCandidate.setDefeated(damagedCandidate
+ .getDefeated() + 1);
+
+ // HP��GP�������l�ɖ߂�
+ damagedCandidate.setHp(fightCalculation
+ .initialiseHP());
+ damagedCandidate.setGp(fightCalculation
+ .initialiseGP());
+
+ // �o���ʒu�ɍēo�ꂳ����
+ damagedCandidate.setPosition(getPlayersPosition(index, getPlayerList().size()));
+ }
+
+ /**
+ *
+ * �v���C���[�̓o��i�ēo��j�ʒu��Ԃ�
+ * @param index�@�v���C���[�̔ԍ�
+ * @param numPlayer �S�v���C���[�̐�
+ * @return
+ */
+ private Position3D getPlayersPosition(int index, int numPlayer) {
+ return new Position3D((((double)index / (double)(numPlayer - 1)) - 0.5) * DEFAULT_STAGE_WIDTH, 0.0, 0.0);
+ }
+
+ private void calculateTP() {
+ // TODO Auto-generated method stub
+ tp = new int[playerList.size()];
+ for (int i = 0; i < playerList.size(); i++) {
+ tp[i] = playerList.get(i).getTp();
+ }
+ }
+
+ private void calculateDefeated() {
+ // TODO Auto-generated method stub
+ defeated = new int[playerList.size()];
+ for (int i = 0; i < playerList.size(); i++) {
+ defeated[i] = playerList.get(i).getDefeated();
+ }
+ }
+
+ private void calculateDefeat() {
+ // TODO Auto-generated method stub
+ defeat = new int[playerList.size()];
+ for (int i = 0; i < playerList.size(); i++) {
+ defeat[i] = playerList.get(i).getDefeat();
+ }
+ }
+
+ private void calculateRank() {
+ // TODO Auto-generated method stub
+
+ for (int i = 0; i < rank.length; i++) {
+ int max = 0;
+ int maxNum = 0;
+ int playerTp;
+ for (int j = 0; j < rank.length; j++) {
+ if (rank[j] == 0
+ && max <= (playerTp = getPlayerList().get(j).getTp())) {
+ max = playerTp;
+ maxNum = j;
+ }
+ }
+ rank[maxNum] = i + 1;
+ }
+ }
+
+ int getRemnantMinute() {
+ int time = (int) (leftTime / 1000) / 60;
+ if(time > 0) {
+ return time;
+ }
+ return 0;
+ }
+
+ int getRemnantSecond() {
+ int time = (int) (leftTime / 1000) % 60;
+ if (time > 0) {
+ return time;
+ }
+ return 0;
+ }
+
+ boolean checkEnd() {
+ return isEnd;
+ }
+
+ int[] getRank() {
+ return rank;
+ }
+
+ ArrayList getPlayerList() {
+ return playerList;
+ }
+
+ int[] getTp() {
+ return tp;
+ }
+
+ int[] getDefeated() {
+ return defeated;
+ }
+
+ int[] getDefeat() {
+ return defeat;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/fight3D/FightCalculation.java b/src/main/java/fight3D/FightCalculation.java
new file mode 100644
index 0000000..fe8850f
--- /dev/null
+++ b/src/main/java/fight3D/FightCalculation.java
@@ -0,0 +1,84 @@
+package fight3D;
+
+public class FightCalculation {
+ static final int MAX_HP = 100;
+ static final int MIN_HP = 0;
+ static final int MAX_TP = 999;
+ static final int MIN_TP = 0;
+ static final int MAX_GP = 100;
+ static final int MIN_GP = 0;
+
+ int initialiseHP(){
+ return MAX_HP;
+ }
+
+
+ int initialiseTP(){
+ return MIN_TP;
+ }
+
+
+ int initialiseGP(){
+ return MAX_GP;
+ }
+
+
+ int decreaseHP(int enemiesAP,int myHP,int myDP){
+ int afterHP = 0;
+ afterHP = myHP - (enemiesAP*2 - myDP);
+ if(afterHPMAX_TP){
+ afterTP = MAX_TP;
+ }
+ return afterTP;
+ }
+
+
+ int decreaseTP(int myTP){
+ return myTP/2;
+ }
+
+
+ int increaseGP(int myGP){
+ int afterGP = 0;
+ afterGP = myGP+1;
+ if(myGP>MAX_GP){
+ myGP =MAX_GP;
+ }
+ return afterGP;
+ }
+
+
+ int decreaseGP(int enemiesAP,int myDP,int myGP){
+ int afterGP = 0;
+ afterGP = myGP - (enemiesAP*2 - myDP);
+ if(afterGP getPosition().getX()) {
+ body.apply(new Quaternion3D(0.0, 1.0, 0.0, 0), false);
+ lastMoveState = stateRightMove;
+ } else {
+ body.apply(new Quaternion3D(0.0, 1.0, 0.0, Math.PI), false);
+ lastMoveState = stateLeftMove;
+ }
+ State s = stateDamaged;
+ changeState(s, false);
+ }
+
+ void setHp(int hp) {
+ this.hp = hp;
+ }
+
+ int getHp() {
+ return hp;
+ }
+
+ void setTp(int tp) {
+ this.tp = tp;
+ }
+
+ int getTp() {
+ return tp;
+ }
+
+ void setGp(int gp) {
+ this.gp = gp;
+ }
+
+ int getGp() {
+ return gp;
+ }
+
+ void recoverGp() {
+ if (state.getClass() == StateGuard.class) {
+ gpCounter = 0;
+ return;
+ }
+ gpCounter++;
+ if (gpCounter < 20) {
+ return;
+ }
+ gpCounter = 0;
+ if (FightCalculation.MIN_GP < gp && gp < FightCalculation.MAX_GP) {
+ this.gp += 1;
+ } else if (gp >= FightCalculation.MAX_GP) {
+ gp = FightCalculation.MAX_GP;
+ }
+ }
+
+ void setDefeat(int defeat) {
+ this.defeat = defeat;
+ }
+
+ int getDefeat() {
+ return defeat;
+ }
+
+ void setDefeated(int defeated) {
+ this.defeated = defeated;
+ }
+
+ int getDefeated() {
+ return defeated;
+ }
+
+ /**
+ * �W�����v���J�n���Ă���̌o�ߎ��ԁi���[�v�j��Ԃ��A
+ * �W�����v��ԂɂȂ��Ƃ��� -1 ��Ԃ�
+ * @return �o�ߎ���
+ */
+ public long getElapsedTimeInJumping() {
+ if (state instanceof StateJump) {
+// System.out.println(state.getCounter());
+ return state.getCounter();
+ }
+// System.out.println(-1);
+ return -1L;
+ }
+
+ private void setGuardVisible(double j) {
+ // TODO Auto-generated method stub
+ Transform3D t = new Transform3D();
+ t.setScale(j);
+ guardScale.setTransform(t);
+ }
+
+ private void setGuardInvisible() {
+ // TODO Auto-generated method stub
+ Transform3D t = new Transform3D();
+ t.setScale(0.01);
+ guardScale.setTransform(t);
+
+ }
+
+ private void setGuardScale(int i) {
+ double j = 0;
+ if (i > 0) {
+ j = 1.5 * (i / 100.0);
+ setGuardVisible(j);
+ } else {
+ setGuardInvisible();
+ }
+ }
+}
diff --git a/src/main/java/fight3D/Ranking1Container.java b/src/main/java/fight3D/Ranking1Container.java
new file mode 100644
index 0000000..09a9d21
--- /dev/null
+++ b/src/main/java/fight3D/Ranking1Container.java
@@ -0,0 +1,112 @@
+package fight3D;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.GraphicsConfiguration;
+
+import framework.RWT.RWTContainer;
+import framework.RWT.RWTLabel;
+import framework.RWT.RWTVirtualController;
+import framework.RWT.RWTVirtualKey;
+
+
+public class Ranking1Container extends RWTContainer {
+ private static final long serialVersionUID = 883828261190427156L;
+
+ private Game game;
+
+ public Ranking1Container(Game g) {
+ game = g;
+ }
+
+ public void build(GraphicsConfiguration gc) {
+ // ������
+ removeAll();
+
+ int character[] = game.getCharacter();
+ int rank[] = game.getRank();
+
+ //�P�ʕ\��
+ int i;
+ for(i=0 ; i effectList = new ArrayList();
+
+ private BufferedImage image;
+
+ //�R���X�g���N�^
+ public Stage(String fileName) {
+ super(fileName);
+ // TODO Auto-generated constructor stub
+ }
+
+ //�X�e�[�W��
+ public void setName(String n){
+ name = n;
+ }
+ public String getName(){
+ return name;
+ }
+
+ //�w�i
+ public void setBackground(String fileName){
+ try {
+ image = ImageIO.read(new File(fileName));
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ public void setBackgroundSize(Dimension size){
+ double scalew = (double)size.width/image.getWidth();
+ double scaleh = (double)size.height/image.getHeight();
+ AffineTransformOp atOp = new AffineTransformOp(AffineTransform.getScaleInstance(scalew, scaleh), AffineTransformOp.TYPE_BILINEAR);
+
+ BufferedImage img = new BufferedImage(size.width, size.height, image.getType());
+ atOp.filter(image, img);
+ image = img;
+ }
+
+ public Background getBackground() {
+ Background background = new Background();
+ ImageComponent2D imageCompornent = new ImageComponent2D(ImageComponent2D.FORMAT_RGB, image);
+ background.setImage(imageCompornent);
+ BoundingSphere bs = new BoundingSphere();
+ bs.setRadius(100);
+ background.setApplicationBounds(bs);
+
+ return background;
+ }
+
+ //�X�e�[�W�̐���
+ public void setComment(String comment) {
+ this.comment = comment;
+ }
+ public String getComment() {
+ return comment;
+ }
+
+ //�X�e�[�W�̓�Փx
+// public void setLevel(int level) {
+// this.level = level;
+// }
+// public int getLevel() {
+// return level;
+// }
+
+// //�X�e�[�W�̑傫��
+// public void setSize(int size) {
+// this.size = size;
+// }
+// public int getSize() {
+// return size;
+// }
+
+ //������ʂ����X�e�[�W��
+ public void addEffect(StageEffect effect){
+ effectList.add(effect);
+ }
+
+ public ArrayList getEffectList() {
+ return effectList;
+ }
+}
diff --git a/src/main/java/fight3D/StageEffect.java b/src/main/java/fight3D/StageEffect.java
new file mode 100644
index 0000000..3b49d10
--- /dev/null
+++ b/src/main/java/fight3D/StageEffect.java
@@ -0,0 +1,59 @@
+package fight3D;
+import javax.vecmath.Point3d;
+
+
+public class StageEffect {
+
+ private Point3d p1 = new Point3d();
+ private Point3d p2 = new Point3d();
+ private String effect;
+
+ //�X�e�[�W�́A������ʂ̂���ʒu
+ public void setPositions(Point3d p1, Point3d p2) {
+ this.p1 = p1;
+ this.p2 = p2;
+ }
+
+ public Point3d[] getPositions(){
+ Point3d[] p = {p1, p2};
+ return p;
+ }
+
+ //�X�e�[�W�̎��������
+ public void setEffect(String e){
+ effect = e;
+ }
+ public String getEffect(){
+ return effect;
+ }
+
+ /**
+ * ���̃|�C���g��effect�G���A�ɓ����Ă邩�ǂ����B
+ * @param p
+ * @return
+ */
+ public boolean isIncluded(Point3d p){
+ if(isIncluded(p.x, p1.x, p2.x) && isIncluded(p.y, p1.y, p2.y) && isIncluded(p.z, p1.z, p2.z)){
+ return true;
+ }
+ else{
+ return false;}
+ }
+
+ /**
+ * x��p1��p2�̊Ԃɓ����Ă邩�ǂ����B
+ * @param x
+ * @param p1
+ * @param p2
+ * @return
+ */
+ private boolean isIncluded(double x, double p1, double p2) {
+ if((x-p1)*(x-p2) <= 0) {
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+
+}
diff --git a/src/main/java/fight3D/StageManager.java b/src/main/java/fight3D/StageManager.java
new file mode 100644
index 0000000..697f8f2
--- /dev/null
+++ b/src/main/java/fight3D/StageManager.java
@@ -0,0 +1,121 @@
+package fight3D;
+
+import java.util.ArrayList;
+
+import javax.vecmath.Point3d;
+
+import framework.gameMain.AbstractManager;
+
+public class StageManager extends AbstractManager{
+ private String filename= "data";
+ private static StageManager theInstance = null;
+
+ private static String stageFile = "stage.def";
+
+ //�X�e�[�W�̃f�[�^�^�O
+ private static final String NAME_TAG = "Name";
+ private static final String MODELFILE_TAG = "ModelFile";
+ private static final String BACKGROUNDFILE_TAG = "BackgroundFile";
+ private static final String COMMENT_TAG = "Comment";
+ private static final String EFFECT_TAG = "Effect";
+ private ArrayList stageList = new ArrayList();
+
+ /**
+ *�R���X�g���N�^
+ */
+ private StageManager(){
+ addSeekFile(stageFile);
+ setTag(NAME_TAG);
+ setTag(MODELFILE_TAG);
+ setTag(BACKGROUNDFILE_TAG);
+ setTag(COMMENT_TAG);
+ setTag(EFFECT_TAG);
+ seek(filename);
+ }
+ public static StageManager getInstance(){
+ if(theInstance == null){
+ theInstance = new StageManager();
+ }
+ return theInstance;
+ }
+
+ /**
+ * Stage��ArrayList��Ԃ��܂�
+ * @return
+ */
+ public ArrayList getStageList(){
+ return stageList;
+ }
+
+ /**
+ * �w�肳�ꂽStage��Ԃ��܂��B
+ * @param id�@ Stage number
+ * @return
+ */
+ public Stage getStage(int id){
+ if(id stages;
+ private RWTLabel title = new RWTLabel();
+ private RWTLabel back = new RWTLabel();
+ private RWTLabel message1 = new RWTLabel();
+ private RWTLabel message2 = new RWTLabel();
+ private RWTLine line1 = new RWTLine();
+ private RWTLine line2 = new RWTLine();
+
+ public StageSelectContainer(Game g) {
+ game = g;
+ }
+
+ // �t���[���ɒlj����ăT�C�Y���m�肵����ɒ��g���\�z����
+ public void build(GraphicsConfiguration gc) {
+ // ������
+ removeAll();
+ setBackground(Color.BLACK);
+
+ // �I�������X�e�[�W��`�悷�邽�߂̃L�����o�X��lj�
+ objectCanvas = new RWTSelectionCanvas3D();
+ objectCanvas.setRelativePosition(0.03f, 0.675f);
+ objectCanvas.setRelativeSize(0.25f, 0.30f);
+ addCanvas(objectCanvas);
+
+ stages = StageManager.getInstance().getStageList();
+
+ // �^�C�g���E�߂�A�C�R���E���b�Z�[�W�G���A�̕`��
+ title.setString("��X�e�[�W�I��");
+ title.setColor(Color.white);
+ title.setFont(new Font("", Font.PLAIN, 20));
+ title.setRelativePosition(0.20f, 0.10f);
+ addWidget(title);
+
+ back.setString("B:�����I����ʂ�");
+ back.setColor(Color.white);
+ back.setFont(new Font("", Font.PLAIN, 8));
+ back.setRelativePosition(0.025f, 0.05f);
+ addWidget(back);
+
+ message1.setRelativePosition(0.60f, 0.05f);
+ message1.setString("�X�e�[�W��I�����ĉ������B");
+ message1.setColor(Color.YELLOW);
+ addWidget(message1);
+ message2.setRelativePosition(0.60f, 0.10f);
+ message2.setString("�`�F����");
+ message2.setColor(Color.YELLOW);
+ addWidget(message2);
+
+ // �X�e�[�W�̕`��
+ for (int i = 0; i < stages.size(); i++) {
+ String str = stages.get(i).getName() + RWTLabel.NEW_PARAGRAPH
+ + stages.get(i).getComment();
+ StageSelectImageButton stage = new StageSelectImageButton(str,
+ stages.get(i).getModel(), activatedLabel, i, this);
+ stage.setString(stages.get(i).getName());
+ stage.setColor(Color.white);
+ stage.setRelativePosition(0.10f + i % 3 * 0.3f, (i / 3 + 1) * 0.3f);
+ addSelectableWidget(stage, i % 3, i / 3);
+ }
+
+ // �I�����ꂽ�X�e�[�W�̐������̕`��
+ addWidget(activatedLabel);
+
+ // ��ʕ������C���̕`��
+ line1.setColor(Color.white);
+ line1.setRelativePosition(0.00f, 0.15f, 1.00f, 0.15f);
+ addWidget(line1);
+
+ line2.setColor(Color.white);
+ line2.setRelativePosition(0.00f, 0.65f, 1.00f, 0.65f);
+ addWidget(line2);
+
+ repaint();
+ }
+
+ public void updateObjectCanvas(BaseObject3D o) {
+ if (objectCanvas != null) objectCanvas.setObject(o);
+ }
+
+ @Override
+ public void keyPressed(RWTVirtualKey key) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void keyReleased(RWTVirtualKey key) {
+ // TODO Auto-generated method stub
+
+ if (key.getVirtualKey() == RWTVirtualController.BUTTON_A) {
+ // �m�F���
+ setConfirmMessage();
+ repaint();
+
+ if (goFight == true) {
+ // �I�����ꂽ�X�e�[�W�̓o�^
+ StageSelectImageButton activeWidget;
+ activeWidget = (StageSelectImageButton) getSelectedWidget();
+ game.setStage(activeWidget.number);
+
+ game.goNextGameState();
+ }
+ goFight = true;
+ }
+
+ if (key.getVirtualKey() == RWTVirtualController.BUTTON_B) {
+ if (goFight == true) {
+ initializeMessage();
+ repaint();
+ goFight = false;
+ } else {
+ game.goPrevGameState();
+ }
+ }
+
+ if (key.getVirtualKey() == RWTVirtualController.RIGHT) {
+ cursorMoveRight();
+
+ }
+ if (key.getVirtualKey() == RWTVirtualController.LEFT) {
+ cursorMoveLeft();
+ }
+ }
+
+ @Override
+ public void keyTyped(RWTVirtualKey key) {
+ // TODO Auto-generated method stub
+
+ }
+
+ // �X�e�[�W��I�ۂ̃��x���̏�����������
+ private void setConfirmMessage() {
+ back.setString("");
+ message1.setString("����ł�낵���ł����B");
+ message2.setString("�`�F����@�a�F�߂�");
+ }
+
+ // �X�e�[�W��I�тȂ������ۂ̃��x���̏�����������
+ private void initializeMessage() {
+ back.setString("B:�����I����ʂ�");
+ message1.setString("�X�e�[�W��I�����ĉ������B");
+ message2.setString("�`�F����");
+ }
+}
diff --git a/src/main/java/fight3D/StageSelectImageButton.java b/src/main/java/fight3D/StageSelectImageButton.java
new file mode 100644
index 0000000..4ba64cd
--- /dev/null
+++ b/src/main/java/fight3D/StageSelectImageButton.java
@@ -0,0 +1,59 @@
+package fight3D;
+
+import java.awt.Color;
+
+import framework.RWT.RWTLabel;
+import framework.RWT.RWTSelectableWidget;
+import framework.model3D.Model3D;
+
+public class StageSelectImageButton extends RWTLabel implements RWTSelectableWidget {
+ private RWTLabel label;
+ protected int number = 0;
+ private String comment;
+ StageSelectContainer container;
+ Model3D model;
+
+ public StageSelectImageButton(String str, Model3D m, RWTLabel activeLabel,
+ int i, StageSelectContainer c) {
+ comment = str;
+ model = m;
+ label = activeLabel;
+ number = i;
+ container = c;
+ }
+
+ @Override
+ public void selected() {
+ // �A�N�e�B�u�ȃL�����N�^�̖��O�������\��
+ label.setString(comment);
+ label.setColor(Color.WHITE);
+ label.setRelativePosition(0.35f, 0.75f);
+
+ // �A�N�e�B�u�ȃL�����N�^�̃I�u�W�F�N�g��ݒ�
+ container.updateObjectCanvas(model.createObject());
+ }
+
+ @Override
+ public void deselected() {
+ }
+
+ @Override
+ public int getAbsoluteHeight() {
+ return super.getAbsoluteHeight();
+ }
+
+ @Override
+ public int getAbsoluteWidth() {
+ return super.getAbsoluteWidth();
+ }
+
+ @Override
+ public int getAbsoluteX() {
+ return super.getAbsoluteX();
+ }
+
+ @Override
+ public int getAbsoluteY() {
+ return super.getAbsoluteY();
+ }
+}
diff --git a/src/main/java/fight3D/StageSelectState.java b/src/main/java/fight3D/StageSelectState.java
new file mode 100644
index 0000000..e390d06
--- /dev/null
+++ b/src/main/java/fight3D/StageSelectState.java
@@ -0,0 +1,28 @@
+package fight3D;
+
+import framework.RWT.RWTContainer;
+import framework.RWT.RWTVirtualController;
+import framework.gameMain.AbstractGameState;
+
+public class StageSelectState extends AbstractGameState {
+
+ Game game;
+
+ StageSelectState(Game g) {
+ this.game = g;
+ }
+
+ @Override
+ public RWTContainer createContainer() {
+ return new StageSelectContainer(game);
+ }
+
+ @Override
+ public void update(RWTVirtualController controller, long interval) {
+ }
+
+ @Override
+ public boolean useTimer() {
+ return false;
+ }
+}
diff --git a/src/main/java/fight3D/State.java b/src/main/java/fight3D/State.java
new file mode 100644
index 0000000..cce4521
--- /dev/null
+++ b/src/main/java/fight3D/State.java
@@ -0,0 +1,56 @@
+package fight3D;
+import framework.gameMain.Mode;
+import framework.physics.Velocity3D;
+
+
+public abstract class State {
+ protected long counter = 0; // ���̏�Ԃɐ�ւ���Ă��牽���[�v�ڂ��H
+
+ public void init() {
+ counter = 0;
+ }
+
+ public void countUp() {
+ counter++;
+ }
+
+ public long getCounter() {
+ return counter;
+ }
+
+ /**
+ * ���x��Ԃ�
+ * @param curVelocity ���݂̑��x
+ * @param mode ���݂̃��[�h
+ * @return ���̏u�Ԃ̑��x
+ */
+ public Velocity3D getVelocity(Velocity3D curVelocity, Mode mode) {
+ if (counter == 0) {
+ // �ŏ��̏u�Ԃ��������x��Ԃ�
+ return getInitialVelocity();
+ }
+ return null;
+ }
+
+ /**
+ * �������玟�̏�ԂɑJ�ډ\���ۂ���Ԃ�
+ * @param nextState ���̏��
+ * @param mode ���݂̃��[�h�i�ɑ؍݂��Ă��邩�n��ɂ��邩�j
+ * @return true --- �J�ډ\, false --- �J�ڕs�\
+ */
+ public abstract boolean canChange(State nextState, Mode mode);
+
+
+ /**
+ * �����i�p���j�\�ȏ�Ԃ�1�����Ō��ɖ߂��Ԃ�
+ * @return true --- �����i�p���j�\�ȏ��, false --- 1�����Ō��ɖ߂���
+ */
+ public abstract boolean isRepeatable();
+
+ /**
+ * �����x��Ԃ�
+ * @return �����x
+ */
+ public abstract Velocity3D getInitialVelocity();
+
+}
diff --git a/src/main/java/fight3D/StateAttack.java b/src/main/java/fight3D/StateAttack.java
new file mode 100644
index 0000000..849399a
--- /dev/null
+++ b/src/main/java/fight3D/StateAttack.java
@@ -0,0 +1,25 @@
+package fight3D;
+import framework.gameMain.Mode;
+import framework.physics.Velocity3D;
+
+//�U��
+public class StateAttack extends StateOnce {
+ static final Velocity3D initialVelocity = new Velocity3D(0.0, 0.0, 0.0);
+
+ public boolean canChange(State nextState, Mode mode) {
+ if (nextState instanceof StateAttack) return false;
+ if (nextState instanceof StateUpperAttack) return false;
+ if (nextState instanceof StateJumpAttack) return false;
+ if (nextState instanceof StateNormalLeft) return false;
+ if (nextState instanceof StateNormalRight) return false;
+
+ if(nextState instanceof StateFlinch) return true;
+ if(nextState instanceof StateDamaged) return true;
+
+ return false;
+ }
+
+ public Velocity3D getInitialVelocity() {
+ return initialVelocity;
+ }
+}
diff --git a/src/main/java/fight3D/StateBend.java b/src/main/java/fight3D/StateBend.java
new file mode 100644
index 0000000..7eeffff
--- /dev/null
+++ b/src/main/java/fight3D/StateBend.java
@@ -0,0 +1,31 @@
+package fight3D;
+import framework.gameMain.Mode;
+import framework.gameMain.ModeOnGround;
+import framework.physics.Velocity3D;
+
+//���Ⴊ��
+public class StateBend extends StateRepeatable {
+ static final Velocity3D initialVelocity = new Velocity3D(0.0, 0.0, 0.0);
+
+ public boolean canChange(State nextState, Mode mode) {
+
+ //�ʏ�
+ if(mode instanceof ModeOnGround) {
+ if(nextState instanceof StateAttack) return false;
+ if(nextState instanceof StateUpperAttack) return false;
+ if(nextState instanceof StateJumpAttack) return false;
+ if(nextState instanceof StateGuard) return false;
+ if(nextState instanceof StateJump) return false;
+ if(nextState instanceof StateLeftMove) return false;
+ if(nextState instanceof StateRightMove) return false;
+ }
+
+ //������
+ return true;
+ }
+
+ public Velocity3D getInitialVelocity() {
+ return initialVelocity;
+ }
+
+}
diff --git a/src/main/java/fight3D/StateDamaged.java b/src/main/java/fight3D/StateDamaged.java
new file mode 100644
index 0000000..1c49d8c
--- /dev/null
+++ b/src/main/java/fight3D/StateDamaged.java
@@ -0,0 +1,19 @@
+package fight3D;
+import framework.gameMain.Mode;
+import framework.physics.Velocity3D;
+
+
+public class StateDamaged extends StateOnce {
+ static final Velocity3D initialVelocity = new Velocity3D(0.0, 0.0, 0.0);
+
+ @Override
+ public boolean canChange(State nextState, Mode mode) {
+ return false;
+ }
+
+ @Override
+ public Velocity3D getInitialVelocity() {
+ return initialVelocity;
+ }
+
+}
diff --git a/src/main/java/fight3D/StateFlinch.java b/src/main/java/fight3D/StateFlinch.java
new file mode 100644
index 0000000..cb301d8
--- /dev/null
+++ b/src/main/java/fight3D/StateFlinch.java
@@ -0,0 +1,33 @@
+package fight3D;
+import framework.gameMain.Mode;
+import framework.gameMain.ModeFreeFall;
+import framework.gameMain.ModeOnGround;
+import framework.physics.Velocity3D;
+
+//�Ђ��
+public class StateFlinch extends StateOnce {
+ static final Velocity3D initialVelocity = new Velocity3D(0.0, 0.0, 0.0);
+
+ @Override
+ public boolean canChange(State nextState, Mode mode) {
+ // TODO Auto-generated method stub
+ if (nextState instanceof StateDamaged) return true;
+
+ //�ʏ�
+ if(mode instanceof ModeOnGround) {
+
+ }
+
+ //������
+ if(mode instanceof ModeFreeFall) {
+
+ }
+
+ return false;
+ }
+
+ public Velocity3D getInitialVelocity() {
+ return initialVelocity;
+ }
+
+}
diff --git a/src/main/java/fight3D/StateGuard.java b/src/main/java/fight3D/StateGuard.java
new file mode 100644
index 0000000..b5813bf
--- /dev/null
+++ b/src/main/java/fight3D/StateGuard.java
@@ -0,0 +1,27 @@
+package fight3D;
+import framework.gameMain.Mode;
+import framework.physics.Velocity3D;
+
+
+public class StateGuard extends StateRepeatable {
+ static final Velocity3D initialVelocity = new Velocity3D(0.0, 0.0, 0.0);
+
+ public boolean canChange(State nextState, Mode mode) {
+
+ if(nextState instanceof StateAttack) return false;
+ if(nextState instanceof StateUpperAttack) return false;
+ if(nextState instanceof StateJumpAttack) return false;
+ if(nextState instanceof StateBend) return false;
+ // if(nextState instanceof StateFlinch) return false;
+ if(nextState instanceof StateJump) return false;
+ if(nextState instanceof StateLeftMove) return false;
+ if(nextState instanceof StateRightMove) return false;
+
+ return true;
+ }
+
+ public Velocity3D getInitialVelocity() {
+ return initialVelocity;
+ }
+
+}
diff --git a/src/main/java/fight3D/StateJump.java b/src/main/java/fight3D/StateJump.java
new file mode 100644
index 0000000..5ce3133
--- /dev/null
+++ b/src/main/java/fight3D/StateJump.java
@@ -0,0 +1,37 @@
+package fight3D;
+import framework.gameMain.Mode;
+import framework.gameMain.ModeFreeFall;
+import framework.gameMain.ModeOnGround;
+import framework.physics.Velocity3D;
+
+
+public class StateJump extends StateOnce {
+ private Velocity3D initialVelocity = new Velocity3D(0.0, 10.0, 0.0);
+
+ void setSpeed(double speed) {
+ initialVelocity.setY(speed);
+ }
+
+ public boolean canChange(State nextState, Mode mode) {
+ if(mode instanceof ModeOnGround) {
+ if(nextState instanceof StateNormalRight) return true;
+ else if(nextState instanceof StateNormalLeft) return true;
+ }
+ if(mode instanceof ModeFreeFall) {
+ //������
+ if(nextState instanceof StateJumpAttack) return true;
+ if(nextState instanceof StateUpperAttack) return true; // �W�����v��������͑�U�����ł���i���쐫��̗��R�j
+ if(nextState instanceof StateFlinch) return true;
+ if(nextState instanceof StateLeftMove) return true;
+ if(nextState instanceof StateRightMove) return true;
+ if(nextState instanceof StateGuard) return true;
+ if(nextState instanceof StateNormalRight) return true;
+ if(nextState instanceof StateNormalLeft) return true;
+ }
+ return false;
+ }
+
+ public Velocity3D getInitialVelocity() {
+ return initialVelocity;
+ }
+}
diff --git a/src/main/java/fight3D/StateJumpAttack.java b/src/main/java/fight3D/StateJumpAttack.java
new file mode 100644
index 0000000..ed7e1c4
--- /dev/null
+++ b/src/main/java/fight3D/StateJumpAttack.java
@@ -0,0 +1,28 @@
+package fight3D;
+import framework.gameMain.Mode;
+import framework.physics.Velocity3D;
+
+
+public class StateJumpAttack extends StateOnce {
+
+ @Override
+ public boolean canChange(State nextState, Mode mode) {
+ if (nextState instanceof StateAttack) return false;
+ if (nextState instanceof StateUpperAttack) return false;
+ if (nextState instanceof StateJumpAttack) return false;
+ if (nextState instanceof StateNormalLeft) return false;
+ if (nextState instanceof StateNormalRight) return false;
+
+ if(nextState instanceof StateFlinch) return true;
+ if(nextState instanceof StateDamaged) return true;
+
+ return false;
+ }
+
+ @Override
+ public Velocity3D getInitialVelocity() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+}
diff --git a/src/main/java/fight3D/StateLeftMove.java b/src/main/java/fight3D/StateLeftMove.java
new file mode 100644
index 0000000..f7df430
--- /dev/null
+++ b/src/main/java/fight3D/StateLeftMove.java
@@ -0,0 +1,56 @@
+package fight3D;
+
+import javax.vecmath.Vector3d;
+
+import framework.gameMain.Mode;
+import framework.gameMain.ModeFreeFall;
+import framework.gameMain.ModeOnGround;
+import framework.physics.PhysicsUtility;
+import framework.physics.Velocity3D;
+
+
+public class StateLeftMove extends StateRepeatable {
+ private Velocity3D initialVelocity = new Velocity3D(-5.0, 0.0, 0.0);
+
+ void setSpeed(double speed) {
+ initialVelocity.setX(-speed);
+ }
+
+ public boolean canChange(State nextState, Mode mode) {
+ if(mode instanceof ModeFreeFall) {
+ //������
+ if(nextState instanceof StateBend) return false;
+ if(nextState instanceof StateGuard) return false;
+ if(nextState instanceof StateJump) return false;
+ }
+ return true;
+ }
+
+ public Velocity3D getInitialVelocity() {
+ return initialVelocity;
+ }
+
+ public Velocity3D getVelocity(Velocity3D curVelocity, Mode mode) {
+ if (mode instanceof ModeOnGround) {
+ // �n�ʂ̌����ɉ����悤�ɑ��x�x�N�g���̌�����ς���
+ // �i�n�������Ă���Ƃ��̓A�j���[�V�����Ȃǂ̉e���ő��x���ς��\��������̂ŁA��ԕω����Ȃ��Ă��������x��ݒ肵������j
+ ModeOnGround modeOnGround = (ModeOnGround)mode;
+ Vector3d v = getInitialVelocity().getVector3d();
+ double d = v.dot(modeOnGround.getNormal());
+ v.scaleAdd(-d, modeOnGround.getNormal(), v);
+ return new Velocity3D(v);
+ }
+ // �ɑ؍݂��Ă���ꍇ�͐��������̑��x���������ύX����i���R�����ɂ͉e����^���Ȃ��悤�Ɂj
+ if (counter == 0) {
+ // �̏ꍇ�A���������ɉ��������邱�Ƃ͂Ȃ��̂ŁA���x��ݒ肷��̂͏���݂̂ł���
+ Vector3d v0 = curVelocity.getVector3d();
+ Vector3d v1 = getInitialVelocity().getVector3d();
+ v0.add(v1);
+ double d0 = v0.dot(PhysicsUtility.horizon);
+ double d1 = v1.dot(PhysicsUtility.horizon);
+ v0.scaleAdd(d1 - d0, PhysicsUtility.horizon, v0);
+ return new Velocity3D(v0);
+ }
+ return null;
+ }
+}
diff --git a/src/main/java/fight3D/StateNormalLeft.java b/src/main/java/fight3D/StateNormalLeft.java
new file mode 100644
index 0000000..916a0ba
--- /dev/null
+++ b/src/main/java/fight3D/StateNormalLeft.java
@@ -0,0 +1,50 @@
+package fight3D;
+
+import javax.vecmath.Vector3d;
+
+import framework.gameMain.Mode;
+import framework.gameMain.ModeFreeFall;
+import framework.gameMain.ModeOnGround;
+import framework.model3D.GeometryUtility;
+import framework.physics.PhysicsUtility;
+import framework.physics.Velocity3D;
+
+
+public class StateNormalLeft extends StateRepeatable {
+ static final Velocity3D initialVelocity = new Velocity3D(0.0, 0.0, 0.0);
+
+ public boolean canChange(State nextState, Mode mode) {
+ if(mode instanceof ModeFreeFall){
+ //������
+ if(nextState instanceof StateBend) return false;
+ if(nextState instanceof StateGuard) return false;
+ if(nextState instanceof StateJump) return false;
+ }
+ return true;
+ }
+
+ public Velocity3D getInitialVelocity() {
+ return initialVelocity;
+ }
+
+ public Velocity3D getVelocity(Velocity3D curVelocity, Mode mode) {
+ if (mode instanceof ModeOnGround) {
+ if (curVelocity.getVector3d().length() <= GeometryUtility.TOLERANCE) return null;
+ // �������Ă��ĎΖʂɏՓ˂�����A�Ζʂ����ׂ��Ă����Ȃ��悤�Ɏ~�߂�
+ return getInitialVelocity();
+ }
+ // �ɑ؍݂��Ă���ꍇ�͐��������̑��x���������ύX����i���R�����ɂ͉e����^���Ȃ��悤�Ɂj
+ if (counter == 0) {
+ // ���̏�Ԃɕς�����u��
+ Vector3d v0 = curVelocity.getVector3d();
+ Vector3d v1 = getInitialVelocity().getVector3d();
+ v0.add(v1);
+ double d0 = v0.dot(PhysicsUtility.horizon);
+ double d1 = v1.dot(PhysicsUtility.horizon);
+ v0.scaleAdd(d1 - d0, PhysicsUtility.horizon, v0);
+ if (v0.y >= 0.0) v0.y = 0.0; // �������㏸���͗������u�Ԃɗ������J�n����
+ return new Velocity3D(v0);
+ }
+ return null;
+ }
+}
diff --git a/src/main/java/fight3D/StateNormalRight.java b/src/main/java/fight3D/StateNormalRight.java
new file mode 100644
index 0000000..c1b3cac
--- /dev/null
+++ b/src/main/java/fight3D/StateNormalRight.java
@@ -0,0 +1,50 @@
+package fight3D;
+
+import javax.vecmath.Vector3d;
+
+import framework.gameMain.Mode;
+import framework.gameMain.ModeFreeFall;
+import framework.gameMain.ModeOnGround;
+import framework.model3D.GeometryUtility;
+import framework.physics.PhysicsUtility;
+import framework.physics.Velocity3D;
+
+
+public class StateNormalRight extends StateRepeatable {
+ static final Velocity3D initialVelocity = new Velocity3D(0.0, 0.0, 0.0);
+
+ public boolean canChange(State nextState, Mode mode) {
+ if(mode instanceof ModeFreeFall){
+ //������
+ if(nextState instanceof StateBend) return false;
+ if(nextState instanceof StateGuard) return false;
+ if(nextState instanceof StateJump) return false;
+ }
+ return true;
+ }
+
+ public Velocity3D getInitialVelocity() {
+ return initialVelocity;
+ }
+
+ public Velocity3D getVelocity(Velocity3D curVelocity, Mode mode) {
+ if (mode instanceof ModeOnGround) {
+ if (curVelocity.getVector3d().length() <= GeometryUtility.TOLERANCE) return null;
+ // �������Ă��ĎΖʂɏՓ˂�����A�Ζʂ����ׂ��Ă����Ȃ��悤�Ɏ~�߂�
+ return getInitialVelocity();
+ }
+ // �ɑ؍݂��Ă���ꍇ�͐��������̑��x���������ύX����i���R�����ɂ͉e����^���Ȃ��悤�Ɂj
+ if (counter == 0) {
+ // ���̏�Ԃɕς�����u��
+ Vector3d v0 = curVelocity.getVector3d();
+ Vector3d v1 = getInitialVelocity().getVector3d();
+ v0.add(v1);
+ double d0 = v0.dot(PhysicsUtility.horizon);
+ double d1 = v1.dot(PhysicsUtility.horizon);
+ v0.scaleAdd(d1 - d0, PhysicsUtility.horizon, v0);
+ if (v0.y >= 0.0) v0.y = 0.0; // �������㏸���͗������u�Ԃɗ������J�n����
+ return new Velocity3D(v0);
+ }
+ return null;
+ }
+}
diff --git a/src/main/java/fight3D/StateOnce.java b/src/main/java/fight3D/StateOnce.java
new file mode 100644
index 0000000..1b7c55d
--- /dev/null
+++ b/src/main/java/fight3D/StateOnce.java
@@ -0,0 +1,10 @@
+package fight3D;
+
+public abstract class StateOnce extends State {
+
+ public boolean isRepeatable() {
+
+ return false;
+ }
+
+}
diff --git a/src/main/java/fight3D/StateRepeatable.java b/src/main/java/fight3D/StateRepeatable.java
new file mode 100644
index 0000000..750509c
--- /dev/null
+++ b/src/main/java/fight3D/StateRepeatable.java
@@ -0,0 +1,10 @@
+package fight3D;
+
+public abstract class StateRepeatable extends State {
+
+ public boolean isRepeatable() {
+
+ return true;
+ }
+
+}
diff --git a/src/main/java/fight3D/StateRightMove.java b/src/main/java/fight3D/StateRightMove.java
new file mode 100644
index 0000000..b9e9333
--- /dev/null
+++ b/src/main/java/fight3D/StateRightMove.java
@@ -0,0 +1,56 @@
+package fight3D;
+
+import javax.vecmath.Vector3d;
+
+import framework.gameMain.Mode;
+import framework.gameMain.ModeFreeFall;
+import framework.gameMain.ModeOnGround;
+import framework.physics.PhysicsUtility;
+import framework.physics.Velocity3D;
+
+
+public class StateRightMove extends StateRepeatable {
+ private Velocity3D initialVelocity = new Velocity3D(5.0, 0.0, 0.0);
+
+ void setSpeed(double speed) {
+ initialVelocity.setX(speed);
+ }
+
+ public boolean canChange(State nextState, Mode mode) {
+ if(mode instanceof ModeFreeFall) {
+ //������
+ if(nextState instanceof StateBend) return false;
+ if(nextState instanceof StateGuard) return false;
+ if(nextState instanceof StateJump) return false;
+ }
+ return true;
+ }
+
+ public Velocity3D getInitialVelocity() {
+ return initialVelocity;
+ }
+
+ public Velocity3D getVelocity(Velocity3D curVelocity, Mode mode) {
+ if (mode instanceof ModeOnGround) {
+ // �n�ʂ̌����ɉ����悤�ɑ��x�x�N�g���̌�����ς���
+ // �i�n�������Ă���Ƃ��̓A�j���[�V�����Ȃǂ̉e���ő��x���ς��\��������̂ŁA��ԕω����Ȃ��Ă��������x��ݒ肵������j
+ ModeOnGround modeOnGround = (ModeOnGround)mode;
+ Vector3d v = getInitialVelocity().getVector3d();
+ double d = v.dot(modeOnGround.getNormal());
+ v.scaleAdd(-d, modeOnGround.getNormal(), v);
+ return new Velocity3D(v);
+ }
+ // �ɑ؍݂��Ă���ꍇ�͐��������̑��x���������ύX����i���R�����ɂ͉e����^���Ȃ��悤�Ɂj
+ if (counter == 0) {
+ // �̏ꍇ�A���������ɉ��������邱�Ƃ͂Ȃ��̂ŁA���x��ݒ肷��̂͏���݂̂ł���
+ Vector3d v0 = curVelocity.getVector3d();
+ Vector3d v1 = getInitialVelocity().getVector3d();
+ v0.add(v1);
+ double d0 = v0.dot(PhysicsUtility.horizon);
+ double d1 = v1.dot(PhysicsUtility.horizon);
+ v0.scaleAdd(d1 - d0, PhysicsUtility.horizon, v0);
+ return new Velocity3D(v0);
+ }
+ return null;
+ }
+}
diff --git a/src/main/java/fight3D/StateUpperAttack.java b/src/main/java/fight3D/StateUpperAttack.java
new file mode 100644
index 0000000..4d7f069
--- /dev/null
+++ b/src/main/java/fight3D/StateUpperAttack.java
@@ -0,0 +1,29 @@
+package fight3D;
+import framework.gameMain.Mode;
+import framework.physics.Velocity3D;
+
+
+public class StateUpperAttack extends StateOnce {
+ static final Velocity3D initialVelocity = new Velocity3D(0.0, 0.0, 0.0);
+
+ @Override
+ public boolean canChange(State nextState, Mode mode) {
+ if (nextState instanceof StateAttack) return false;
+ if (nextState instanceof StateUpperAttack) return false;
+ if (nextState instanceof StateJumpAttack) return false;
+ if (nextState instanceof StateNormalLeft) return false;
+ if (nextState instanceof StateNormalRight) return false;
+
+ if(nextState instanceof StateFlinch) return true;
+ if(nextState instanceof StateDamaged) return true;
+
+ return false;
+ }
+
+ @Override
+ public Velocity3D getInitialVelocity() {
+ // �W�����v�J�n����͑�U�����ł���̂ŁA���̏ꍇ�̓W�����v�𒆒f����i����������j
+ return initialVelocity;
+ }
+
+}
diff --git a/src/main/java/fight3D/Weapon.java b/src/main/java/fight3D/Weapon.java
new file mode 100644
index 0000000..24268e0
--- /dev/null
+++ b/src/main/java/fight3D/Weapon.java
@@ -0,0 +1,132 @@
+package fight3D;
+
+import framework.gameMain.Actor;
+import framework.model3D.CollisionResult;
+import framework.model3D.Object3D;
+import framework.physics.Force3D;
+import framework.physics.Ground;
+import framework.physics.PhysicsUtility;
+import framework.physics.Solid3D;
+
+
+/**
+ * ��ѓ���A�e
+ * @author �V�c����
+ *
+ */
+public class Weapon extends Actor implements Attackable {
+ private Player owner;
+ private boolean fCalculatePhysics = false;
+ boolean fActive = true;
+ long lifetime;
+ private long timeLag = 0; // �U���������n�߂�܂ł̎��ԁi�������ԁj
+
+ public Weapon(WeaponModel m, Player owner, long t) {
+ super(m);
+ this.owner = owner;
+ lifetime = 10000;
+ timeLag = t;
+ disappear();
+ }
+
+ public void motion(long interval, Ground ground){
+
+ if(doesCalculatePhysics()){
+ lifetime = lifetime -interval;
+ if(lifetime <= 0){
+ disappear();
+ }
+ }
+ super.motion(interval, ground);
+ }
+
+ public void appear(){
+ fActive = true;
+ setVisible();
+ }
+
+ public void disappear() {
+ fActive = false;
+ setInvisible();
+ }
+
+ //�������U���̒����^��������̂������^��������̂���
+ public boolean doesCalculatePhysics(){
+
+ return fCalculatePhysics;
+ }
+
+ public boolean isAlive(){
+ return fActive;
+ }
+
+ //�U���͂�������
+ public int getAP() {
+ // TODO Auto-generated method stub
+ return owner.character.getPower();
+ }
+
+ //2�̕��̂�������Ƃ��̂R�����̌`����������
+ public Object3D getBody() {
+ // TODO Auto-generated method stub
+ return body;
+ }
+
+ @Override
+ public String getPartName() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ //�N��Weapon�����������̂����肷��
+ public Player getOwner() {
+ // TODO Auto-generated method stub
+ return owner;
+ }
+
+ //Player�ƓƗ���������������̂��ǂ�������iWeapon�ł͓Ɨ�����������������j
+ public boolean isMovable() {
+ // TODO Auto-generated method stub
+ return true;
+ }
+
+ public void onEndAnimation() {
+ }
+
+ public void onEndFall(){
+ }
+
+ //Weapon���n�ʂɓ��������Ƃ��ɂǂ��������������邩
+ public void onIntersect(CollisionResult cr, long interval) {
+ // TODO Auto-generated method stub
+ if(doesCalculatePhysics()){
+ Force3D f = PhysicsUtility.calcForce(interval, cr.normal, (Solid3D)body);
+ ((Solid3D)body).move(interval, f, cr.collisionPoint);
+ }
+ else{
+ disappear();
+ }
+ }
+
+ public Force3D getGravity() {
+ if (doesCalculatePhysics()) {
+ return super.getGravity();
+ }
+ return Force3D.ZERO;
+ }
+
+ private void setVisible(){
+ animation.reset();
+ body.scale(1.0);
+ }
+
+ private void setInvisible(){
+ body.apply(owner.getPosition(), false);
+ body.scale(0.01);
+ }
+
+ @Override
+ public boolean isActivate() {
+ return (animation.time >= timeLag);
+ }
+}
diff --git a/src/main/java/fight3D/WeaponModel.java b/src/main/java/fight3D/WeaponModel.java
new file mode 100644
index 0000000..9ab83e2
--- /dev/null
+++ b/src/main/java/fight3D/WeaponModel.java
@@ -0,0 +1,17 @@
+package fight3D;
+import framework.animation.Animation3D;
+import framework.gameMain.ActorModel;
+
+
+public class WeaponModel extends ActorModel {
+ public Animation3D weaponAnimation = new Animation3D();
+
+ public WeaponModel(String fileName) {
+ super(fileName);
+ // TODO Auto-generated constructor stub
+ }
+
+ public Animation3D getAnimation() {
+ return new Animation3D(weaponAnimation);
+ }
+}
diff --git a/src/main/java/framework/AI/AStar.java b/src/main/java/framework/AI/AStar.java
new file mode 100644
index 0000000..4934a6a
--- /dev/null
+++ b/src/main/java/framework/AI/AStar.java
@@ -0,0 +1,91 @@
+package framework.AI;
+
+import java.util.*;
+
+/**
+ * A*�N���X�B
+ */
+public class AStar {
+ private LinkedList locationOpenList = new LinkedList();
+ private LinkedList locationClosedList = new LinkedList();
+
+ /**
+ * �ŒZ�o�H�T���B �ŒZ�o�H�̃��X�g��Ԃ����A������Ȃ��ꍇnull��Ԃ��B
+ * start = goal�̏ꍇ��null��Ԃ��B
+ * �߂�l�ɂ�goal����start�̂P�O�܂Ōo�H�������̂ڂ������̂������Ă���Bstart�͓����Ă��Ȃ��B
+ */
+ public Plan getPath(Location startLocation,
+ Location goalLocation) {
+
+ //�o���n�_�ƖړI�n�_�������Ȃ�null��Ԃ�
+ if (startLocation.equals(goalLocation)) {
+ return null;
+ }
+
+ // ������
+ locationOpenList = new LinkedList();
+ locationClosedList = new LinkedList();
+
+ // �o���n�_��LocationOpenList�ɒlj�����
+ locationOpenList.add(startLocation);
+ while (!locationOpenList.isEmpty()) {
+ // LocationOpenList�̍ŏ��X�R�A�̒n�_��curLocation�Ƃ��Ď��o��
+ Collections.sort(locationOpenList, new CostComparator());
+ Location curLocation = locationOpenList.removeFirst();
+
+ // ���݂̒n�_���ړI�n�_�Ȃ�ΒT������
+ if (curLocation.equals(goalLocation)) {
+ LinkedList locationPath = new LinkedList();
+
+ // �o���n�_�܂Œʂ����n�_��H��
+ curLocation = goalLocation;
+ while (!curLocation.equals(startLocation)) {
+ locationPath.add(curLocation);
+ curLocation = (Location) curLocation.getParent();
+ }
+ return new Plan(locationPath);
+ }
+
+ // ���݂̒n�_���ړI�n�_�łȂ��Ȃ�A���݂̒n�_��LocationClosedList�Ɉڂ�
+ locationClosedList.add(curLocation);
+
+ // �אڂ���n�_�ׂ�
+ ArrayList neighbors = curLocation.getSuccessors();
+
+ // �אڂ���n�_�̐������A���[�v
+ for (int i = 0; i < neighbors.size(); i++) {
+ // �ʉ߂ł��A�e���X�g�ɓ����ĂȂ��Ȃ�R�X�g�����炢�A
+ if (!locationOpenList.contains(neighbors.get(i))
+ && !locationClosedList.contains(neighbors.get(i))) {
+ //�n�_�R�X�g�����߂�
+ //agent.getLocationCost((Location)neighbors.get(i), null, null, null);
+
+ //�p�X�R�X�g�����߂�
+ ((Location)neighbors.get(i)).calculatesCosts(curLocation, goalLocation);
+
+ // LocationOpenList�Ɉڂ�
+ locationOpenList.add((Location) neighbors.get(i));
+ }
+ }
+
+ // -------------------------------------------------------------------------------------------------------------------------------------------
+
+ }
+ return null;
+ }
+
+ // -------------------------------------------------------------------------------------------------------------------------------------------
+ // �R�X�g�̏����\�[�g�̂��߂̃N���X����낤
+
+ /**
+ * �\�[�g�������N���X�B
+ */
+ class CostComparator implements Comparator {
+ public int compare(Location n1, Location n2) {
+ return n1.getScore() - n2.getScore();
+ }
+ }
+
+ // -------------------------------------------------------------------------------------------------------------------------------------------
+
+}
diff --git a/src/main/java/framework/AI/GeometryGraph.java b/src/main/java/framework/AI/GeometryGraph.java
new file mode 100644
index 0000000..86381da
--- /dev/null
+++ b/src/main/java/framework/AI/GeometryGraph.java
@@ -0,0 +1,169 @@
+package framework.AI;
+
+import java.util.ArrayList;
+
+import javax.media.j3d.Geometry;
+import javax.media.j3d.IndexedTriangleArray;
+import javax.vecmath.Point3d;
+
+import framework.model3D.Position3D;
+
+public class GeometryGraph extends StateMachine {
+ // �R���X�g���N�^
+ public GeometryGraph(Geometry g) {
+ if (g instanceof IndexedTriangleArray) {
+
+ IndexedTriangleArray ita = (IndexedTriangleArray) g;
+
+ // ita����states�Ƀf�[�^����������
+ for (int i = 0; i < ita.getIndexCount() / 3; i++) {// �ʂ̐��������[�v
+ Location e = new Location(i, ita);
+ if (e.getNormal() != null) {
+ states.add(e);
+ }
+ }
+
+ // �֘A�t��
+ for (int i = 0; i < states.size(); i++) {
+ setSuccessors(i, ita);
+ }
+ }
+ }
+
+
+ // �A���������֘A�t��
+ public void setSuccessors(int index, IndexedTriangleArray ita) {
+ Location e = (Location)states.get(index);
+
+ // �T��
+ int[] List = new int[ita.getIndexCount()];
+
+ for (int i = 0; i < ita.getIndexCount(); i++) {
+ List[i] = ita.getCoordinateIndex(i);
+ }
+
+ // -1�ŏ�����
+ for (int i = 0; i < 3; i++) {
+ e.successorIndex[i] = -1;
+ e.IndexOfSharedEdge[i] = -1;
+ }
+
+ int j = 0;
+
+ for (int i = 0; i < states.size() * 3; i++) {
+ // System.out.println("indexList[0] ��List["+i+"] �̏ƍ�");
+ // //////id�łk��������u�������ă��\�b�h�Ăяo�������Ȃ�?
+ // int id = ita.getCoordinateIndex(i);
+ if (e.indexList[0] == List[i]) {
+ if (i % 3 == 0) {
+ if (e.indexList[1] == List[i + 2]) {
+ e.successorIndex[j] = i / 3;
+ e.IndexOfSharedEdge[0] = e.indexList[0];
+ e.IndexOfSharedEdge[1] = e.indexList[1];
+ e.addSuccessor(states.get(i / 3));
+ j++;
+ } else if (e.indexList[2] == List[i + 1]) {
+ e.successorIndex[j] = i / 3;
+ e.IndexOfSharedEdge[0] = e.indexList[0];
+ e.IndexOfSharedEdge[2] = e.indexList[2];
+ e.addSuccessor(states.get(i / 3));
+ j++;
+ }
+ } else if (i % 3 == 1) {
+ if (e.indexList[1] == List[i - 1]) {
+ e.successorIndex[j] = i / 3;
+ e.IndexOfSharedEdge[0] = e.indexList[0];
+ e.IndexOfSharedEdge[1] = e.indexList[1];
+ e.addSuccessor(states.get(i / 3));
+ j++;
+ } else if (e.indexList[2] == List[i + 1]) {
+ e.successorIndex[j] = i / 3;
+ e.IndexOfSharedEdge[0] = e.indexList[0];
+ e.IndexOfSharedEdge[2] = e.indexList[2];
+ e.addSuccessor(states.get(i / 3));
+ j++;
+ }
+ } else if (i % 3 == 2) {
+ if (e.indexList[1] == List[i - 1]) {
+ e.successorIndex[j] = i / 3;
+ e.IndexOfSharedEdge[0] = e.indexList[0];
+ e.IndexOfSharedEdge[1] = e.indexList[1];
+ e.addSuccessor(states.get(i / 3));
+ j++;
+ } else if (e.indexList[2] == List[i - 2]) {
+ e.successorIndex[j] = i / 3;
+ e.IndexOfSharedEdge[0] = e.indexList[0];
+ e.IndexOfSharedEdge[2] = e.indexList[2];
+ e.addSuccessor(states.get(i / 3));
+ j++;
+ }
+ }
+
+ }
+ }
+
+ for (int i = 0; i < states.size() * 3; i++) {
+ // System.out.println("indexList[1] ��List["+i+"] �̏ƍ�");
+ if (e.indexList[1] == List[i]) {
+ if (i % 3 == 0) {
+ if (e.indexList[2] == List[i + 2]) {
+ e.successorIndex[j] = i / 3;
+ e.IndexOfSharedEdge[1] = e.indexList[1];
+ e.IndexOfSharedEdge[2] = e.indexList[2];
+ e.addSuccessor(states.get(i / 3));
+ j++;
+ }
+ } else if (i % 3 == 1) {
+ if (e.indexList[2] == List[i - 1]) {
+ e.successorIndex[j] = i / 3;
+ e.IndexOfSharedEdge[1] = e.indexList[1];
+ e.IndexOfSharedEdge[2] = e.indexList[2];
+ e.addSuccessor(states.get(i / 3));
+ j++;
+ }
+ } else if (i % 3 == 2) {
+ if (e.indexList[2] == List[i - 2]) {
+ e.successorIndex[j] = i / 3;
+ e.IndexOfSharedEdge[1] = e.indexList[1];
+ e.IndexOfSharedEdge[2] = e.indexList[2];
+ e.addSuccessor(states.get(i / 3));
+ j++;
+ }
+ }
+ }
+ }
+
+ // System.out.println("1�ڂ�successor**"+successorIndex[0]+"***");
+ // System.out.println("2�ڂ�successor**"+successorIndex[1]+"***");
+ // System.out.println("3�ڂ�successor**"+successorIndex[2]+"***");
+
+ return;
+ }
+
+
+ // �A�N�Z�b�T
+ public ArrayList getStates() {
+ return states;
+ }
+
+ public Location getNearestLocation(Position3D pos) {
+ Location nearest = null;
+ double distance = 0.0;
+ for (int n = 0; n < states.size(); n++) {
+ Location loc = (Location)states.get(n);
+ if (nearest == null) {
+ nearest = loc;
+ distance = nearest.getCenter().distance(
+ new Point3d(pos.getVector3d()));
+ } else {
+ double d = loc.getCenter().distance(
+ new Point3d(pos.getVector3d()));
+ if (d < distance) {
+ nearest = loc;
+ distance = d;
+ }
+ }
+ }
+ return nearest;
+ }
+}
diff --git a/src/main/java/framework/AI/IState.java b/src/main/java/framework/AI/IState.java
new file mode 100644
index 0000000..bef6db0
--- /dev/null
+++ b/src/main/java/framework/AI/IState.java
@@ -0,0 +1,16 @@
+package framework.AI;
+
+import java.util.ArrayList;
+
+public interface IState {
+
+ abstract ArrayList getSuccessors();
+
+ abstract void addSuccessor(IState s);
+ /**
+ * �T�����̃m�[�h�擾�B
+ * @return
+ * �T�����̃m�[�h��Ԃ��B
+ */
+ abstract IState getParent();
+}
diff --git a/src/main/java/framework/AI/Location.java b/src/main/java/framework/AI/Location.java
new file mode 100644
index 0000000..d0db4cf
--- /dev/null
+++ b/src/main/java/framework/AI/Location.java
@@ -0,0 +1,139 @@
+package framework.AI;
+
+import java.awt.Point;
+import java.util.ArrayList;
+
+import javax.media.j3d.IndexedTriangleArray;
+import javax.vecmath.Point3d;
+import javax.vecmath.Vector3d;
+
+import framework.model3D.GeometryUtility;
+
+public class Location implements IState {
+ public int planeIndex;
+ public int[] indexList = new int[3];
+ public int[] successorIndex = new int[100];
+ public int numberOfSharedEdge;// ���L�ӂ̖{��
+ public int[] IndexOfSharedEdge = new int[3];// ���L�ӂ̒��_�C���f�b�N�X
+ private Point3d center;
+ private Vector3d normal;
+
+ private double cost = 0;
+ private double heuristicCost = 0;
+ private Location parentNode = null;
+ private ArrayList successors = new ArrayList();
+
+ // �e�X�g�p�̋�̃R���X�g���N�^
+ public Location(Point3d center) {
+ this.center = center;
+ normal = new Vector3d(0.0, 1.0, 0.0);
+ }
+
+ // �R���X�g���N�^
+ public Location(int index, IndexedTriangleArray ita) {
+ planeIndex = index;
+
+ indexList[0] = ita.getCoordinateIndex(index * 3);
+ indexList[1] = ita.getCoordinateIndex(index * 3 + 1);
+ indexList[2] = ita.getCoordinateIndex(index * 3 + 2);
+
+ Point3d p1 = new Point3d();
+ Point3d p2 = new Point3d();
+ Point3d p3 = new Point3d();
+
+ ita.getCoordinate(indexList[0], p1);
+ ita.getCoordinate(indexList[1], p2);
+ ita.getCoordinate(indexList[2], p3);
+
+ // ���S���W�̌v�Z
+ center = new Point3d((p1.getX() + p2.getX() + p3.getX()) / 3.0, (p1
+ .getY()
+ + p2.getY() + p3.getY()) / 3.0, (p1.getZ() + p2.getZ() + p3
+ .getZ()) / 3.0);
+
+ // �@���x�N�g���̌v�Z
+ p2.sub(p1);
+ p3.sub(p1);
+ Vector3d v2 = new Vector3d(p2);
+ Vector3d v3 = new Vector3d(p3);
+ v2.cross(v2, v3);
+ if (v2.length() < GeometryUtility.TOLERANCE) {
+ v2 = null;
+ } else {
+ v2.normalize();
+ }
+ normal = v2;
+ }
+
+ public void addSuccessor(IState s) {
+ successors.add(s);
+ }
+
+ @Override
+ public ArrayList getSuccessors() {
+ // TODO Auto-generated method stub
+ return (ArrayList) successors;
+ }
+
+ @Override
+ public IState getParent() {
+ // TODO Auto-generated method stub
+ return parentNode;
+ }
+
+ /**
+ * �X�R�A�̎擾�B
+ *
+ * @return �X�R�A��Ԃ��B
+ */
+ public int getScore() {
+ // ��r�ɏ����_�����f������ׁA1000���|���Ă���
+ return (int) ((cost + heuristicCost) * 1000);
+ }
+
+ /**
+ * �R�X�g�v�Z�ƒT�����m�[�h��ݒ�B
+ *
+ * @param parentNode
+ * �T�����̃m�[�h�B
+ * @param goalNode
+ * �ړI�n�̃m�[�h�B
+ */
+ public void calculatesCosts(Location parentNode, Location goalNode) {
+ // �R�X�g�����Z
+ cost = parentNode.cost + 1; // agent.getPathCost(parentNode, this, null,
+ // null, null, null, null, null);
+
+ // //�q���[���X�e�B�b�N�R�X�g���v�Z
+ // disX = point.x - goalNode.point.x;
+ // disY = point.y - goalNode.point.y;
+ // �q���[���X�e�B�b�N�R�X�g�̐M�����������ׁA3����1�ɂ��Ă���
+ heuristicCost = 0;
+
+ // �T�����m�[�h���L�^
+ this.parentNode = parentNode;
+ }
+
+ // /////////
+ // �A�N�Z�b�T//
+ // /////////
+ public int getPlaneIndex() {
+ return planeIndex;
+ }
+
+ public int getIndexList(int index) {
+ return indexList[index];
+ }
+
+ public int getSuccessorIndex(int index) {
+ return successorIndex[index];
+ }
+
+ public Point3d getCenter() {
+ return center;
+ }
+
+ public Vector3d getNormal() {
+ return normal;
+ }
+}
diff --git a/src/main/java/framework/AI/Plan.java b/src/main/java/framework/AI/Plan.java
new file mode 100644
index 0000000..512f55b
--- /dev/null
+++ b/src/main/java/framework/AI/Plan.java
@@ -0,0 +1,75 @@
+package framework.AI;
+
+import java.util.LinkedList;
+
+import javax.vecmath.Point3d;
+import javax.vecmath.Vector3d;
+
+import framework.model3D.Position3D;
+
+public class Plan {
+ private LinkedList path; // �v����e��\���p�X
+ private int currentLoc = 0; // �p�X��̌��݂� Location
+
+ /**
+ * �����̒ʉߓ_�����v��
+ * @param locationPath
+ */
+ public Plan(LinkedList locationPath) {
+ path = locationPath;
+ currentLoc = locationPath.size() - 1;
+ }
+
+ /**
+ * �X�^�[�g�ƃS�[�����_�C���N�g�Ɍ��Ԍv��
+ * @param start
+ * @param goal
+ */
+ public Plan(Location start, Location goal) {
+ path = new LinkedList();
+ path.add(goal);
+ path.add(start);
+ currentLoc = 1;
+ }
+
+ /**
+ * ���݂� Location ���擾����
+ * @return�@���݂� Location, ���łɃS�[���ɒ����Ă���Ƃ��� null ��Ԃ�
+ */
+ public Location getCurrentLocation() {
+ if (currentLoc <= 0) return null;
+ return path.get(currentLoc);
+ }
+
+ /**
+ * ���� Location ���擾����
+ * @return�@���� Location, ���łɃS�[���ɒ����Ă���Ƃ��� null ��Ԃ�
+ */
+ public Location getNextLocation() {
+ if (currentLoc <= 0) return null;
+ return path.get(currentLoc - 1);
+ }
+
+ /**
+ * ���݂̍��W�l�����ɁA���݂� Location ���X�V����
+ * @param position�@���݂̍��W�l
+ * @return�@�X�V���� --- true, �ȑO�̂܂� --- false
+ */
+ public boolean updateCurrentLocation(Position3D position) {
+ Vector3d toCurrentPosition = position.getVector3d();
+ Location curLocation = getCurrentLocation();
+ if (curLocation == null) return true;
+ toCurrentPosition.sub(curLocation.getCenter());
+ double distanceToCurrentPosition = toCurrentPosition.length();
+ Vector3d toNextLocation = new Vector3d(getNextLocation().getCenter());
+ toNextLocation.sub(curLocation.getCenter());
+ double distanceToNextLocation = toNextLocation.length();
+ if (distanceToCurrentPosition >= distanceToNextLocation) {
+ // ���� Location ��ʂ�߂����ꍇ
+ currentLoc--;
+ return true;
+ }
+ return false;
+ }
+
+}
diff --git a/src/main/java/framework/AI/StateMachine.java b/src/main/java/framework/AI/StateMachine.java
new file mode 100644
index 0000000..c1b7e21
--- /dev/null
+++ b/src/main/java/framework/AI/StateMachine.java
@@ -0,0 +1,9 @@
+package framework.AI;
+
+import java.util.ArrayList;
+
+public abstract class StateMachine {
+ protected ArrayList states = new ArrayList();
+ protected IState curState;
+
+}
diff --git a/src/main/java/framework/RWT/DefaultSelector.java b/src/main/java/framework/RWT/DefaultSelector.java
new file mode 100644
index 0000000..058728b
--- /dev/null
+++ b/src/main/java/framework/RWT/DefaultSelector.java
@@ -0,0 +1,12 @@
+package framework.RWT;
+import java.awt.Color;
+import java.awt.Graphics;
+
+
+public class DefaultSelector extends RWTSelector {
+ @Override
+ public void paint(Graphics g) {
+ g.setColor(new Color(0.0f, 0.5f, 1.0f, 0.3f));
+ g.fill3DRect(widget.getAbsoluteX() - 5, widget.getAbsoluteY() - 5, widget.getAbsoluteWidth() + 10, widget.getAbsoluteHeight() + 10, true);
+ }
+}
diff --git a/src/main/java/framework/RWT/RWTBoard.java b/src/main/java/framework/RWT/RWTBoard.java
new file mode 100644
index 0000000..5aaec12
--- /dev/null
+++ b/src/main/java/framework/RWT/RWTBoard.java
@@ -0,0 +1,62 @@
+package framework.RWT;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Graphics;
+
+public class RWTBoard extends RWTWidget {
+ protected float relativeX = 0.0f;
+ protected float relativeY = 0.0f;
+ protected float relativeWidth = 0.0f;
+ protected float relativeHeight = 0.0f;
+ private int x = 0;
+ private int y = 0;
+ private int width = 0;
+ private int height = 0;
+
+ public RWTBoard(float x, float y, float w, float h, Color c) {
+ setRelativePosition(x, y);
+ setRelativeSize(w, h);
+ setColor(c);
+ }
+
+ /**
+ * ���Έʒu���w�肷��B
+ * @param x x���W�l(0.0f�`1.0f)
+ * @param y y���W�l(0.0f�`1.0f)
+ */
+ public void setRelativePosition(float x, float y) {
+ relativeX = x;
+ relativeY = y;
+ }
+ /**
+ * ���T�C�Y�����肷��B
+ * @param w ��(0.0f�`1.0f)
+ * @param h ����(0.0f�`1.0f)
+ */
+ public void setRelativeSize(float w, float h) {
+ relativeWidth = w;
+ relativeHeight = h;
+ }
+
+ @Override
+ public void adjust(Component parent) {
+ int sx = parent.getWidth();
+ int sy = parent.getHeight();
+ x = (int) (sx * relativeX);
+ y = (int) (sy * relativeY);
+ width = (int) (sx * relativeWidth);
+ height = (int) (sy * relativeHeight);
+ }
+
+ @Override
+ public void paint(Graphics g) {
+ g.setColor(new Color(0.0f, 0.0f, 0.0f, 0.3f));
+ g.fillRoundRect(x + 5, y + 5, width, height, 10, 10);
+ g.setColor(color);
+ g.fillRoundRect(x, y, width, height, 10, 10);
+ g.setColor(new Color(color.getRed(), color.getGreen(), color.getBlue()));
+ g.drawRoundRect(x, y, width, height, 10, 10);
+ }
+
+}
diff --git a/src/main/java/framework/RWT/RWTButton.java b/src/main/java/framework/RWT/RWTButton.java
new file mode 100644
index 0000000..9b1978a
--- /dev/null
+++ b/src/main/java/framework/RWT/RWTButton.java
@@ -0,0 +1,36 @@
+package framework.RWT;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Point;
+
+/**
+ * �{�^���ł��B
+ * @author Wataru
+ *
+ */
+public abstract class RWTButton extends RWTLabel implements RWTSelectableWidget {
+ private float relativeX = 0.0f;
+ private float relativeY = 0.0f;
+ private float relativeWidth = 0.0f;
+ private float relativeHeight = 0.0f;
+ private int x = 0;
+ private int y = 0;
+ private int width = 0;
+ private int height = 0;
+
+ @Override
+ public void adjust(Component parent) {
+ int sx = parent.getWidth();
+ int sy = parent.getHeight();
+ x = (int) (sx * relativeX);
+ y = (int) (sy * relativeY);
+ width = (int) (sx * relativeWidth);
+ height = (int) (sy * relativeHeight);
+ }
+
+ @Override
+ public void paint(Graphics g) {
+ // ������
+ }
+}
diff --git a/src/main/java/framework/RWT/RWTCanvas3D.java b/src/main/java/framework/RWT/RWTCanvas3D.java
new file mode 100644
index 0000000..1b78a45
--- /dev/null
+++ b/src/main/java/framework/RWT/RWTCanvas3D.java
@@ -0,0 +1,241 @@
+package framework.RWT;
+import java.awt.AWTEvent;
+import java.awt.Canvas;
+import java.awt.Container;
+import java.awt.Graphics;
+import java.awt.GraphicsConfiguration;
+import java.awt.event.KeyListener;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
+import java.awt.image.BufferedImage;
+import java.util.ArrayList;
+
+import javax.media.j3d.Canvas3D;
+import javax.media.j3d.ImageComponent2D;
+import javax.media.j3d.View;
+import javax.swing.event.MouseInputListener;
+
+import com.sun.j3d.utils.universe.SimpleUniverse;
+
+import framework.model3D.IViewer3D;
+import framework.model3D.Universe;
+import framework.schedule.ScheduleManager;
+import framework.schedule.TaskController;
+import framework.view3D.Camera3D;
+import framework.view3D.Viewer3D;
+
+/**
+ * GUI���i�iRWTWidget�j��z�u�\��Canvas3D�A�e�R���e�i�ɑ��đ����W�Ŕz�u�ł���
+ * @author �V�c����
+ *
+ */
+@SuppressWarnings("serial")
+public class RWTCanvas3D extends Canvas3D {
+ private ArrayList widgetList = new ArrayList();
+ private float relativeX = 0.0f;
+ private float relativeY = 0.0f;
+ private float relativeWidth = 0.0f;
+ private float relativeHeight = 0.0f;
+ private int x = 0;
+ private int y = 0;
+ private int width = 0;
+ private int height = 0;
+
+ private Camera3D camera = null;
+ private IViewer3D viewer = null;
+
+ private DisplayCanvas displayCanvas = null;
+ private BufferedImage image = null;
+ private static TaskController renderingController = ScheduleManager.getInstance().registerTask("rendering");
+
+ public RWTCanvas3D() {
+ this(SimpleUniverse.getPreferredConfiguration());
+ }
+
+ public RWTCanvas3D(GraphicsConfiguration gc) {
+ this(gc, false);
+ }
+
+ public RWTCanvas3D(boolean offScreen) {
+ this(SimpleUniverse.getPreferredConfiguration(), offScreen);
+ }
+
+ public RWTCanvas3D(GraphicsConfiguration gc, boolean offScreen) {
+ super(gc, offScreen);
+ setFocusable(false);
+ if (offScreen) {
+ displayCanvas = new DisplayCanvas();
+ } else {
+ enableEvents(AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK);
+ }
+ renderingController.deactivate();
+ }
+
+ public Canvas getDisplayCanvas() {
+ if (isOffScreen()) {
+ return displayCanvas;
+ }
+ return this;
+ }
+
+ public void attachCamera(Camera3D camera) {
+ viewer = new Viewer3D(camera);
+ View oldView = this.getView();
+ if (oldView != null) oldView.removeCanvas3D(this);
+ camera.getView().addCanvas3D(this);
+ this.camera = camera;
+ }
+
+ /**
+ * Widget��z�u����B
+ * @param widget
+ */
+ public void addWidget(RWTWidget widget) {
+ widgetList.add(widget);
+ }
+
+ /**
+ * RWTCanvas3D�̑��Έʒu�����肷��B
+ * @param x x���W�l(0.0f�`1.0f)
+ * @param y y���W�l(0.0f�`1.0f)
+ */
+ public void setRelativePosition(float x, float y) {
+ relativeX = x;
+ relativeY = y;
+ }
+
+ /**
+ * RWTCanvas3D�̑��T�C�Y�����肷��B
+ * @param w ��(0.0f�`1.0f)
+ * @param h ����(0.0f�`1.0f)
+ */
+ public void setRelativeSize(float w, float h) {
+ relativeWidth = w;
+ relativeHeight = h;
+ }
+
+ /**
+ * �e�̃R���e�i�ɉ����Ĉʒu�ƃT�C�Y�����킹��B
+ * @param parent �e�R���e�i
+ */
+ public void adjust(Container parent) {
+ int sx = parent.getWidth();
+ int sy = parent.getHeight();
+ x = (int) (sx * relativeX);
+ y = (int) (sy * relativeY);
+ width = (int) (sx * relativeWidth);
+ height = (int) (sy * relativeHeight);
+ if (isOffScreen()) {
+ image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
+ ImageComponent2D ic = new ImageComponent2D(ImageComponent2D.FORMAT_RGBA, image, true, false);
+ ic.setCapability(ImageComponent2D.ALLOW_IMAGE_READ);
+ ic.setCapability(ImageComponent2D.ALLOW_IMAGE_WRITE);
+ setOffScreenBuffer(ic);
+ displayCanvas.setBounds(x, y, width, height);
+ getScreen3D().setSize(width, height);
+ getScreen3D().setPhysicalScreenWidth(0.0254/90.0 * (double)width);
+ getScreen3D().setPhysicalScreenHeight(0.0254/90.0 * (double)height);
+ } else {
+ setBounds(x, y, width, height);
+ }
+ }
+
+ @Override
+ public void preRender() {
+ if (viewer == null || camera == null) return;
+ viewer.setGraphicsContext3D(this.getGraphicsContext3D());
+ camera.getUniverse().preRender(viewer);
+ }
+
+ @Override
+ public void renderField(int fieldDesc) {
+ if (viewer == null || camera == null) return;
+ viewer.setGraphicsContext3D(this.getGraphicsContext3D());
+ camera.getUniverse().renderField(viewer);
+ }
+
+ @Override
+ public void postRender() {
+ if (viewer == null || camera == null) return;
+ viewer.setGraphicsContext3D(this.getGraphicsContext3D());
+ camera.getUniverse().postRender(viewer);
+ if (isOffScreen()) {
+ //�@�I�t�X�N���[���o�b�t�@��̉摜�擾
+ ImageComponent2D ic = getOffScreenBuffer();
+ image = ic.getImage();
+ Graphics src = image.getGraphics();
+ //�@�L�����o�X��́@Widget ������
+ drawWidgets(src);
+ src.dispose();
+ //�@�f�B�X�v���C�o�b�t�@�ɕ`��
+ Graphics dst = displayCanvas.getGraphics();
+ dst.drawImage(image, 0, 0, null);
+ dst.dispose();
+ }
+ }
+
+ @Override
+ public void postSwap() {
+ super.postSwap();
+
+ if (!isOffScreen()) {
+ //�@�L�����o�X��́@Widget �̕`��
+ Graphics g = getGraphics();
+ drawWidgets(g);
+ g.dispose();
+ }
+ renderingController.deactivate();
+ }
+
+ /**
+ * �I�t�X�N���[���̏ꍇ�̂݁A�����_�����O���I�ɃX�P�W���[�����O����
+ */
+ public void doRender() {
+ if (isOffScreen()) {
+ if (renderingController.activate()) {
+ // �O��̃����_�����O���I�����Ă����ꍇ
+ renderOffScreenBuffer();
+ }
+ }
+ }
+
+ private void drawWidgets(Graphics g) {
+ for(int i = 0; i < widgetList.size(); i++) {
+ RWTWidget widget = widgetList.get(i);
+ if(widget.isVisible()) {
+ widget.adjust(this);
+ widget.paint(g);
+ }
+ }
+ }
+
+ public void processEvent(AWTEvent e) {
+ // �C�x���g���R���e�i���ɕԂ�
+ Container c = this.getParent();
+ if (c != null) c.dispatchEvent(e);
+ }
+
+ private class DisplayCanvas extends Canvas {
+
+ public DisplayCanvas() {
+ setFocusable(false);
+ enableEvents(AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK);
+ }
+
+ public void paint(Graphics g) {
+ super.paint(g);
+ if (image != null) {
+ synchronized (image) {
+ g.drawImage(image, 0, 0, null);
+ }
+ }
+ }
+
+ public void processEvent(AWTEvent e) {
+ // �C�x���g���R���e�i���ɕԂ�
+ Container c = this.getParent();
+ if (c != null) c.dispatchEvent(e);
+ }
+ }
+}
diff --git a/src/main/java/framework/RWT/RWTContainer.java b/src/main/java/framework/RWT/RWTContainer.java
new file mode 100644
index 0000000..6d58f92
--- /dev/null
+++ b/src/main/java/framework/RWT/RWTContainer.java
@@ -0,0 +1,180 @@
+package framework.RWT;
+
+import java.awt.AWTEvent;
+import java.awt.Container;
+import java.awt.Graphics;
+import java.awt.GraphicsConfiguration;
+import java.awt.event.MouseEvent;
+import java.util.ArrayList;
+
+import javax.swing.event.MouseInputListener;
+
+
+import framework.model3D.Universe;
+
+
+/**
+ * GUI���i�iRWTWidget�j��z�u�\�ȃR���e�i�AGUI���i�̃A�N�e�B�x�[�V�������Ǘ��ł���
+ *
+ * @author �V�c����
+ *
+ */
+@SuppressWarnings("serial")
+public abstract class RWTContainer extends Container {
+ private ArrayList canvases = null;
+
+ private ArrayList widgetList = new ArrayList();
+ private RWTSelectionManager active = new RWTSelectionManager();
+
+ public abstract void build(GraphicsConfiguration gc);
+
+ public abstract void keyPressed(RWTVirtualKey key);
+
+ public abstract void keyReleased(RWTVirtualKey key);
+
+ public abstract void keyTyped(RWTVirtualKey key);
+
+ public RWTContainer() {
+ setLayout(null);
+ setFocusable(false);
+ widgetList.add(active.getSelector());
+ enableEvents(AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK);
+ }
+
+ public void addCanvas(RWTCanvas3D cavas) {
+ if (canvases == null) canvases = new ArrayList();
+ canvases.add(cavas);
+ cavas.adjust(this);
+ add(cavas.getDisplayCanvas());
+ }
+
+ public void paint(Graphics g) {
+ super.paint(g);
+
+ if (canvases != null) {
+ for (int i = 0; i < canvases.size(); i++) {
+ canvases.get(i).adjust(this);
+ canvases.get(i).getDisplayCanvas().paint(g);
+ }
+ }
+
+ for (int i = 0; i < widgetList.size(); i++) {
+ RWTWidget widget = widgetList.get(i);
+ if (widget.isVisible()) {
+ widget.adjust(this);
+ widget.paint(g);
+ }
+ }
+ }
+
+ public RWTCanvas3D getPrimaryRWTCanvas3D() {
+ if (canvases == null) return null;
+ return canvases.get(0);
+ }
+
+ public int getNumberOfRWTCanvas3D() {
+ if (canvases == null) return 0;
+ return canvases.size();
+ }
+
+ public RWTCanvas3D getRWTCanvas3D(int index) {
+ return canvases.get(index);
+ }
+
+ /**
+ * �J�[�\���őI�ׂȂ�Widget�������܂��B
+ *
+ * @param widget
+ */
+ public void addWidget(RWTWidget widget) {
+ widgetList.add(widget);
+ }
+
+ /**
+ * �J�[�\���őI�ׂȂ�Widget�������܂��B
+ *
+ * @param widget
+ */
+ public void addWidgetOnBack(RWTWidget widget) {
+ widgetList.add(0, widget);
+ }
+
+ /**
+ * �@�A�N�e�B�x�[�V�����𑀍삷��}�l�[�W���[��ݒ肷��B
+ *
+ * @param manager
+ */
+ public void setActiveManager(RWTSelectionManager manager) {
+ active = manager;
+ }
+
+ /**
+ * �J�[�\���őI�ׂ�Widget�������܂��B
+ *
+ * @param w
+ * @param n
+ * @param m
+ */
+ public void addSelectableWidget(RWTSelectableWidget r, int n, int m) {
+ active.add(r, n, m);
+ widgetList.add(0, (RWTWidget) r);
+ }
+
+ /**
+ * �J�[�\���őI�ׂ�Widget��O�ʂɉ����܂��B
+ *
+ * @param w
+ * @param n
+ * @param m
+ */
+ public void addSelectableWidgetOnFront(RWTSelectableWidget r, int n, int m) {
+ active.add(r, n, m);
+ widgetList.add((RWTWidget) r);
+ }
+
+ /**
+ * �J�[�\�����ЂƂ�ɓ������܂��B
+ */
+ public void cursorMoveUp() {
+ active.up();
+ repaint();
+ }
+
+ /**
+ * �J�[�\�����ЂƂ��ɓ������܂��B
+ */
+ public void cursorMoveDown() {
+ active.down();
+ repaint();
+ }
+
+ /**
+ * �J�[�\�����ЂƂ��ɓ������܂��B
+ */
+ public void cursorMoveLeft() {
+ active.left();
+ repaint();
+ }
+
+ /**
+ * �J�[�\�����ЂƂE�ɓ������܂��B
+ */
+ public void cursorMoveRight() {
+ active.right();
+ repaint();
+ }
+
+ public RWTWidget getSelectedWidget() {
+ return active.getSelectedWidget();
+ }
+
+ public void processEvent(AWTEvent e) {
+ // �C�x���g�� RWTFrame3D �ɕԂ�
+ Container c = this.getParent();
+ while (c != null && !(c instanceof RWTFrame3D)) {
+ c = c.getParent();
+ }
+ if (c != null) ((RWTFrame3D)c).processEvent(e);
+ super.processEvent(e);
+ }
+}
diff --git a/src/main/java/framework/RWT/RWTFrame3D.java b/src/main/java/framework/RWT/RWTFrame3D.java
new file mode 100644
index 0000000..6c90f99
--- /dev/null
+++ b/src/main/java/framework/RWT/RWTFrame3D.java
@@ -0,0 +1,172 @@
+package framework.RWT;
+import java.awt.AWTEvent;
+import java.awt.AWTException;
+import java.awt.DisplayMode;
+import java.awt.Frame;
+import java.awt.GraphicsDevice;
+import java.awt.GraphicsEnvironment;
+import java.awt.Robot;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+import java.awt.event.MouseEvent;
+
+import javax.swing.JFrame;
+import javax.swing.event.MouseInputListener;
+
+
+public class RWTFrame3D extends JFrame implements KeyListener, MouseInputListener {
+
+ private static final long serialVersionUID = 1L;
+ private RWTVirtualController virtualController = new RWTVirtualController();
+ private RWTContainer container;
+ private Robot robot = null;
+ private boolean bShadowCasting = false;
+ private boolean bMouseCapture = false;
+
+ public RWTFrame3D() {
+ setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+// GraphicsDevice screen = GraphicsEnvironment.
+// getLocalGraphicsEnvironment().getDefaultScreenDevice();
+// setUndecorated(true);
+// screen.setFullScreenWindow(this);
+// screen.setDisplayMode(new DisplayMode(800, 600, 32,
+// DisplayMode.REFRESH_RATE_UNKNOWN));
+ addKeyListener(this);
+ addMouseListener(this);
+ addMouseMotionListener(this);
+ try {
+ robot = new Robot();
+ } catch (AWTException e) {
+ }
+ requestFocus();
+ }
+
+ public void setContentPane(RWTContainer contentPane) {
+ container = contentPane;
+ super.setContentPane(contentPane);
+ setVisible(true);
+ contentPane.repaint();
+ requestFocus();
+ }
+
+ /**
+ * �����_�����O�̊J�n�i�I�t�X�N���[�����[�h�̏ꍇ�̂ݗL���j
+ */
+ public void doRender() {
+ if (container == null) return;
+ for (int n = 0; n < container.getNumberOfRWTCanvas3D(); n++) {
+ container.getRWTCanvas3D(n).doRender();
+ }
+ }
+
+ public void keyPressed(KeyEvent e) {
+ // TODO Auto-generated method stub
+ if (0 <= e.getKeyCode() && e.getKeyCode() < 256) {
+ if (e.getKeyCode() == KeyEvent.VK_ESCAPE) System.exit(0);
+ virtualController.setKeyDown(e.getKeyCode(), true);
+ if (virtualController.getVirtualKey(e.getKeyCode()) != null) {
+ if (container != null) container.keyPressed(virtualController.getVirtualKey(e.getKeyCode()));
+ }
+ }
+ }
+
+ public void keyReleased(KeyEvent e) {
+ // TODO Auto-generated method stub
+ if (0 <= e.getKeyCode() && e.getKeyCode() < 256) {
+ virtualController.setKeyDown(e.getKeyCode(), false);
+ if (virtualController.getVirtualKey(e.getKeyCode()) != null) {
+ if (container != null)container.keyReleased(virtualController.getVirtualKey(e.getKeyCode()));
+ }
+ }
+ }
+
+ public void keyTyped(KeyEvent e) {
+ // TODO Auto-generated method stub
+ }
+
+ public RWTVirtualController getVirtualController() {
+ return virtualController;
+ }
+
+ public void setShadowCasting(boolean b) {
+ bShadowCasting = b;
+ }
+
+ public boolean isShadowCasting() {
+ return bShadowCasting;
+ }
+
+ public void setMouseCapture(boolean b) {
+ bMouseCapture = b;
+ }
+
+ public void processEvent(AWTEvent e) {
+ super.processEvent(e);
+ }
+
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ }
+
+ @Override
+ public void mouseEntered(MouseEvent e) {
+ }
+
+ @Override
+ public void mouseExited(MouseEvent e) {
+ }
+
+ @Override
+ public void mousePressed(MouseEvent e) {
+ switch (e.getButton()) {
+ case MouseEvent.BUTTON1:
+ virtualController.setMouseButtonDown(0, true);
+ break;
+ case MouseEvent.BUTTON2:
+ virtualController.setMouseButtonDown(1, true);
+ break;
+ case MouseEvent.BUTTON3:
+ virtualController.setMouseButtonDown(2, true);
+ break;
+ }
+ }
+
+ @Override
+ public void mouseReleased(MouseEvent e) {
+ switch (e.getButton()) {
+ case MouseEvent.BUTTON1:
+ virtualController.setMouseButtonDown(0, false);
+ break;
+ case MouseEvent.BUTTON2:
+ virtualController.setMouseButtonDown(1, false);
+ break;
+ case MouseEvent.BUTTON3:
+ virtualController.setMouseButtonDown(2, false);
+ break;
+ }
+ }
+
+ @Override
+ public void mouseDragged(MouseEvent e) {
+ if (bMouseCapture ) {
+ int cx = getWidth() / 2;
+ int cy = getHeight() / 2;
+ robot.mouseMove(cx, cy);
+ virtualController.moveMousePosition((double)(e.getXOnScreen()- cx) / (double)getWidth(), (double)(e.getYOnScreen() - cy) / (double)getHeight());
+ } else {
+ virtualController.setMousePosition((double)e.getXOnScreen() / (double)getWidth(), (double)e.getYOnScreen() / (double)getHeight());
+ }
+ }
+
+ @Override
+ public void mouseMoved(MouseEvent e) {
+ if (bMouseCapture) {
+ int cx = getWidth() / 2;
+ int cy = getHeight() / 2;
+ robot.mouseMove(cx, cy);
+ virtualController.moveMousePosition((double)(e.getXOnScreen() - cx) / (double)getWidth(), (double)(e.getYOnScreen() - cy) / (double)getHeight());
+ } else {
+ virtualController.setMousePosition((double)e.getXOnScreen() / (double)getWidth(), (double)e.getYOnScreen() / (double)getHeight());
+ }
+ }
+}
diff --git a/src/main/java/framework/RWT/RWTImage.java b/src/main/java/framework/RWT/RWTImage.java
new file mode 100644
index 0000000..599f468
--- /dev/null
+++ b/src/main/java/framework/RWT/RWTImage.java
@@ -0,0 +1,95 @@
+package framework.RWT;
+import java.awt.Component;
+import java.awt.Graphics;
+import java.awt.Point;
+import java.awt.image.BufferedImage;
+import java.awt.image.ImageObserver;
+import java.io.File;
+import java.util.ArrayList;
+
+import javax.imageio.ImageIO;
+import javax.vecmath.Point2f;
+
+/**
+ * �摜�ł��B
+ * @author Wataru
+ *
+ */
+public class RWTImage extends RWTWidget {
+ protected float relativeX = 0.0f;
+ protected float relativeY = 0.0f;
+ protected float relativeWidth = 0.0f;
+ protected float relativeHeight = 0.0f;
+ protected int x = 0;
+ protected int y = 0;
+ protected int width = 0;
+ protected int height = 0;
+
+ private BufferedImage image = null;
+ private ImageObserver observer;
+
+ private int imageWidth = 0;
+ private int imageHeight = 0;
+
+ public RWTImage(String fileName) {
+ try {
+ image = ImageIO.read(new File(fileName));
+ setSize(image.getWidth(), image.getHeight());
+ } catch (Exception e) {
+ e.printStackTrace();
+ image = null;
+ }
+ }
+
+ /**
+ * �摜�̑��Έʒu���w�肷��B
+ * @param x x���W�l(0.0f�`1.0f)
+ * @param y y���W�l(0.0f�`1.0f)
+ */
+ public void setRelativePosition(float x, float y) {
+ relativeX = x;
+ relativeY = y;
+ }
+
+ /**
+ * �摜��ݒ肵�܂��B
+ * @param fileName
+ */
+ public void setImage(String fileName) {
+ try {
+ image = ImageIO.read(new File(fileName));
+ setSize(image.getWidth(), image.getHeight());
+ } catch (Exception e) {
+ e.printStackTrace();
+ image = null;
+ }
+ }
+
+ /**
+ * �摜�̃T�C�Y��ݒ肵�܂��B
+ * ���Βl�ł͂���܂���B
+ * @param x
+ * @param y
+ */
+ public void setSize(int x, int y) {
+ imageWidth = image.getWidth();
+ imageHeight = image.getHeight();
+ }
+
+ public void setObserver(ImageObserver o) {
+ observer = o;
+ }
+
+ @Override
+ public void adjust(Component parent) {
+ int sx = parent.getWidth();
+ int sy = parent.getHeight();
+ x = (int) (sx * relativeX);
+ y = (int) (sy * relativeY);
+ }
+
+ @Override
+ public void paint(Graphics g) {
+ g.drawImage(image, x, y, imageWidth, imageHeight, observer);
+ }
+}
diff --git a/src/main/java/framework/RWT/RWTImageButton.java b/src/main/java/framework/RWT/RWTImageButton.java
new file mode 100644
index 0000000..cd56f28
--- /dev/null
+++ b/src/main/java/framework/RWT/RWTImageButton.java
@@ -0,0 +1,44 @@
+package framework.RWT;
+/**
+ * �摜�̃{�^���ł��B
+ * @author Wataru
+ *
+ */
+public class RWTImageButton extends RWTImage implements RWTSelectableWidget {
+
+ public RWTImageButton(String fileName) {
+ super(fileName);
+ }
+
+ public void selected() {
+ }
+
+ public void buttonDown() {
+ }
+
+ public void buttonUp() {
+ }
+
+ public void deselected() {
+ }
+
+ @Override
+ public int getAbsoluteHeight() {
+ return height;
+ }
+
+ @Override
+ public int getAbsoluteWidth() {
+ return width;
+ }
+
+ @Override
+ public int getAbsoluteX() {
+ return x;
+ }
+
+ @Override
+ public int getAbsoluteY() {
+ return y;
+ }
+}
diff --git a/src/main/java/framework/RWT/RWTLabel.java b/src/main/java/framework/RWT/RWTLabel.java
new file mode 100644
index 0000000..81daf40
--- /dev/null
+++ b/src/main/java/framework/RWT/RWTLabel.java
@@ -0,0 +1,148 @@
+package framework.RWT;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Point;
+import java.util.ArrayList;
+
+import javax.vecmath.Point2f;
+
+/**
+ * �������\��������̂ł��B
+ * @author Wataru
+ *
+ */
+public class RWTLabel extends RWTWidget {
+ private float relativeBaselineX = 0.0f;
+ private float relativeBaselineY = 0.0f;
+ private float relativeWidth = 0.0f;
+ private float relativeHeight = 0.0f;
+ private Font relativeFont = new Font("", Font.PLAIN, 12);
+
+ private int baselineX = 0;
+ private int baselineY = 0;
+ private int y = 0;
+ private int width = 0;
+ private int height = 0;
+ protected Font font = new Font("", Font.PLAIN, 12);
+
+ protected String[] strings;
+ protected int drawMode = DRAW_RIGHT;
+
+ public static final int DEFAULT_PARENT_WIDTH_IN_POINT = 500;
+
+ public static final int DRAW_CENTER = 0;
+ public static final int DRAW_RIGHT = 1;
+ public static final int DRAW_LEFT = 2;
+
+ public static final String NEW_PARAGRAPH = "#";
+
+ public RWTLabel() {
+ strings = new String[1];
+ strings[0] = "";
+ }
+
+ public RWTLabel(float x, float y, String s, Color c, Font f) {
+ setRelativePosition(x, y);
+ setString(s);
+ setColor(c);
+ setFont(f);
+ }
+
+ /**
+ * ���Έʒu���w�肷��B
+ * @param x x���W�l(0.0f�`1.0f)
+ * @param y y���W�l(0.0f�`1.0f)
+ */
+ public void setRelativePosition(float x, float y) {
+ relativeBaselineX = x;
+ relativeBaselineY = y;
+ }
+
+ /**
+ * ���Έʒu���w�肷��B
+ * @param x x���W�l(0.0f�`1.0f)
+ * @param y y���W�l(0.0f�`1.0f)
+ * @param m �\�����@
+ */
+ public void setRelativePosition(float x, float y, int m) {
+ setRelativePosition(x, y);
+ drawMode = m;
+ }
+
+ /**
+ * �\�����镶�����ݒ肷��B
+ * @param s
+ */
+ public void setString(String s) {
+ if(s != null) {
+ strings = s.split(NEW_PARAGRAPH);
+ }
+ }
+
+ /**
+ * �\�����镶����̃t�H���g��ݒ肷��B�������A�t�H���g�̃T�C�Y�̓L�����o�X�̕���500pt�ł���Ƃ��̂��̂Ƃ���B
+ * @param f
+ */
+ public void setFont(Font f) {
+ relativeFont = f;
+ }
+
+ public int getAbsoluteHeight() {
+ return height;
+ }
+
+ public int getAbsoluteWidth() {
+ return width;
+ }
+
+ public int getAbsoluteX() {
+ return baselineX;
+ }
+
+ public int getAbsoluteY() {
+ return y;
+ }
+
+ @Override
+ public void adjust(Component parent) {
+ int sx = parent.getWidth();
+ int sy = parent.getHeight();
+ baselineX = (int) (sx * relativeBaselineX);
+ baselineY = (int) (sy * relativeBaselineY);
+ font = new Font(relativeFont.getName(),
+ relativeFont.getStyle(),
+ (int)(relativeFont.getSize() * sx / DEFAULT_PARENT_WIDTH_IN_POINT));
+
+ FontMetrics fm = parent.getFontMetrics(font);
+ y = baselineY - fm.getAscent() + (int)(fm.getDescent() * 1.1);
+ width = fm.stringWidth(strings[0]); // ��ԏ�̍s�̕��i���{���͍ő啝�ɂ��ׂ��j
+ height = fm.getAscent();
+ }
+
+ @Override
+ public void paint(Graphics g) {
+ FontMetrics fm = g.getFontMetrics(font);
+ g.setColor(color);
+ g.setFont(font);
+ int height = fm.getHeight();
+ int h = 0;
+ for(int i = 0; i < strings.length; i++){
+ int top = 0;
+ if(drawMode == DRAW_CENTER) {
+ top = fm.stringWidth(strings[i]) / 2;
+ }
+ else if(drawMode == DRAW_LEFT) {
+ top = fm.stringWidth(strings[i]);
+ }
+
+ if (strings[i] != null && strings[i].length() > 0) {
+ g.drawString(strings[i], baselineX - top, baselineY + h);
+ }
+
+ h += height;
+ }
+ }
+}
diff --git a/src/main/java/framework/RWT/RWTLine.java b/src/main/java/framework/RWT/RWTLine.java
new file mode 100644
index 0000000..50046ca
--- /dev/null
+++ b/src/main/java/framework/RWT/RWTLine.java
@@ -0,0 +1,59 @@
+package framework.RWT;
+import java.awt.Component;
+import java.awt.Graphics;
+import java.awt.Point;
+import java.util.ArrayList;
+
+import javax.vecmath.Point2f;
+
+/**
+ * ���C���ł��B
+ * @author Wataru
+ *
+ */
+public class RWTLine extends RWTWidget {
+ private float relativeX1 = 0.0f;
+ private float relativeY1 = 0.0f;
+ private float relativeX2 = 0.0f;
+ private float relativeY2 = 0.0f;
+ private int x1 = 0;
+ private int y1 = 0;
+ private int x2 = 0;
+ private int y2 = 0;
+
+ /**
+ * �ꏊ��ݒ肵�܂��B�l�͑��Βl�ł��B
+ * @param w
+ * @param h
+ */
+ public void setRelativePosition(float x1, float y1, float x2, float y2) {
+ relativeX1 = x1;
+ relativeY1 = y1;
+ relativeX2 = x2;
+ relativeY2 = y2;
+ }
+
+ @Override
+ public void adjust(Component parent) {
+ int sx = parent.getWidth();
+ int sy = parent.getHeight();
+ x1 = (int) (sx * relativeX1);
+ y1 = (int) (sy * relativeY1);
+ x2 = (int) (sx * relativeX2);
+ y2 = (int) (sy * relativeY2);
+ }
+
+ @Override
+ public void paint(Graphics g) {
+ g.setColor(color);
+ g.drawLine(x1, y1, x2, y2);
+ }
+
+// @Override
+// public void paint(Graphics g, ArrayList list, double scale) {
+// // TODO Auto-generated method stub
+// g.setColor(color);
+// g.drawLine(list.get(0).x, list.get(0).y, list.get(1).x, list.get(1).y);
+// }
+
+}
diff --git a/src/main/java/framework/RWT/RWTSelectableWidget.java b/src/main/java/framework/RWT/RWTSelectableWidget.java
new file mode 100644
index 0000000..1bd7b8d
--- /dev/null
+++ b/src/main/java/framework/RWT/RWTSelectableWidget.java
@@ -0,0 +1,23 @@
+package framework.RWT;
+import java.awt.Dimension;
+import java.awt.Point;
+
+/**
+ * �A�N�e�B�u�ɂȂ邽�߂ɕK�v�Ȃ��̂ł��B
+ * @author Wataru
+ *
+ */
+public interface RWTSelectableWidget {
+
+ public abstract void selected();
+
+ public abstract void deselected();
+
+ public abstract int getAbsoluteX();
+
+ public abstract int getAbsoluteY();
+
+ public abstract int getAbsoluteWidth();
+
+ public abstract int getAbsoluteHeight();
+}
diff --git a/src/main/java/framework/RWT/RWTSelectionCanvas3D.java b/src/main/java/framework/RWT/RWTSelectionCanvas3D.java
new file mode 100644
index 0000000..3f864b5
--- /dev/null
+++ b/src/main/java/framework/RWT/RWTSelectionCanvas3D.java
@@ -0,0 +1,73 @@
+package framework.RWT;
+
+import java.util.Enumeration;
+
+import javax.media.j3d.AmbientLight;
+import javax.media.j3d.BoundingSphere;
+import javax.media.j3d.BranchGroup;
+import javax.media.j3d.DirectionalLight;
+import javax.media.j3d.Transform3D;
+import javax.media.j3d.TransformGroup;
+import javax.vecmath.Color3f;
+import javax.vecmath.Point3d;
+import javax.vecmath.Vector3d;
+import javax.vecmath.Vector3f;
+
+import framework.model3D.BaseObject3D;
+import framework.model3D.Position3D;
+import framework.model3D.Universe;
+import framework.view3D.Camera3D;
+
+public class RWTSelectionCanvas3D extends RWTCanvas3D {
+ Universe universe = null;
+ BranchGroup objRoot = null;
+
+ public RWTSelectionCanvas3D() {
+ this(0.0, 0.0, 12.0);
+ }
+
+ public RWTSelectionCanvas3D(double cameraX, double cameraY, double cameraZ) {
+ universe = new Universe();
+ objRoot = new BranchGroup();
+ objRoot.setCapability(BranchGroup.ALLOW_DETACH);
+ objRoot.setCapability(BranchGroup.ALLOW_CHILDREN_EXTEND);
+ objRoot.setCapability(BranchGroup.ALLOW_CHILDREN_READ);
+ objRoot.setCapability(BranchGroup.ALLOW_CHILDREN_WRITE);
+ universe.getRoot().addChild(objRoot);
+ createLight(universe);
+ setCamera(universe, cameraX, cameraY, cameraZ);
+ universe.compile();
+ }
+
+ private void setCamera(Universe universe, double cameraX, double cameraY, double cameraZ) {
+ Camera3D camera = new Camera3D(universe);
+ camera.setViewPoint(new Position3D(cameraX, cameraY, cameraZ));
+ camera.addTarget(new Position3D(0.0, 0.0, 0.0));
+ camera.adjust(0L);
+ attachCamera(camera);
+ }
+
+ void createLight(Universe universe) {
+ // ����
+ AmbientLight amblight = new AmbientLight(new Color3f(0.5f, 0.5f, 0.5f));
+ amblight
+ .setInfluencingBounds(new BoundingSphere(new Point3d(), 10000.0));
+ universe.placeLight(amblight);
+ // ���s����
+ DirectionalLight dirlight = new DirectionalLight(true, // ����ON/OFF
+ new Color3f(1.0f, 1.0f, 1.0f), // ���̐F
+ new Vector3f(0.0f, -1.0f, -0.5f) // ���̕����x�N�g��
+ );
+ dirlight
+ .setInfluencingBounds(new BoundingSphere(new Point3d(), 10000.0));
+ universe.placeLight(dirlight);
+ }
+
+ public void setObject(BaseObject3D obj) {
+ BranchGroup newObj = new BranchGroup();
+ newObj.setCapability(BranchGroup.ALLOW_DETACH);
+ newObj.addChild(obj.getTransformGroupToPlace());
+ objRoot.removeAllChildren();
+ objRoot.addChild(newObj);
+ }
+}
diff --git a/src/main/java/framework/RWT/RWTSelectionManager.java b/src/main/java/framework/RWT/RWTSelectionManager.java
new file mode 100644
index 0000000..7d82515
--- /dev/null
+++ b/src/main/java/framework/RWT/RWTSelectionManager.java
@@ -0,0 +1,266 @@
+package framework.RWT;
+
+
+public class RWTSelectionManager {
+
+ private int size = 0;
+
+ private WidgetHolder selectedHolder = new WidgetHolder(null, 0, 0);
+
+ private WidgetHolder upMostHolder;
+ private WidgetHolder leftMostHolder;
+
+ private RWTSelector selector = new DefaultSelector();
+
+ public void add(RWTSelectableWidget widget, int m, int n) {
+ WidgetHolder holder = new WidgetHolder(widget, m, n);
+ if(size == 0) {
+ widget.selected();
+ selectedHolder = holder;
+ upMostHolder = holder;
+ leftMostHolder = holder;
+ selector.setSelectableWidget(selectedHolder.getSelectableWidget());
+ }
+ else {
+ //�ǂꂭ�炢����
+ connectY(holder);
+
+ //�ǂꂭ�炢�E��
+ connectX(holder);
+ }
+ size++;
+ }
+
+ public void up() {
+ if(selectedHolder.hasUp()) {
+ selectedHolder.getSelectableWidget().deselected();
+ selectedHolder = selectedHolder.getUp();
+ selectedHolder.getSelectableWidget().selected();
+ selector.setSelectableWidget(selectedHolder.getSelectableWidget());
+ }
+ }
+
+ public void down() {
+ if(selectedHolder.hasDown()) {
+ selectedHolder.getSelectableWidget().deselected();
+ selectedHolder = selectedHolder.getDown();
+ selectedHolder.getSelectableWidget().selected();
+ selector.setSelectableWidget(selectedHolder.getSelectableWidget());
+ }
+ }
+
+ public void right() {
+ if(selectedHolder.hasRight()) {
+ selectedHolder.getSelectableWidget().deselected();
+ selectedHolder = selectedHolder.getRight();
+ selectedHolder.getSelectableWidget().selected();
+ selector.setSelectableWidget(selectedHolder.getSelectableWidget());
+ }
+ }
+
+ public void left() {
+ if(selectedHolder.hasLeft()) {
+ selectedHolder.getSelectableWidget().deselected();
+ selectedHolder = selectedHolder.getLeft();
+ selectedHolder.getSelectableWidget().selected();
+ selector.setSelectableWidget(selectedHolder.getSelectableWidget());
+ }
+ }
+
+ public RWTWidget getSelectedWidget() {
+ if(selectedHolder != null) {
+ return selectedHolder.getWidget();
+ }
+ else {
+ return null;
+ }
+ }
+
+ public void setSelector(RWTSelector c) {
+ selector = c;
+ }
+
+ public RWTSelector getSelector() {
+ return selector;
+ }
+
+ /**
+ * ���E���Ȃ���
+ * @param newHolder
+ */
+ private void connectX(WidgetHolder newHolder) {
+ WidgetHolder holder = leftMostHolder;
+ while(true) {
+ if(newHolder.getY() < holder.getY()) {
+ //holder�̂ق�����
+ if(holder.getLeft() != null) {
+ holder.getLeft().setRight(newHolder);
+ }
+ newHolder.setLeft(holder.getLeft());
+
+ holder.setLeft(newHolder);
+ newHolder.setRight(holder);
+ return;
+ }
+ else if(newHolder.getY() == holder.getY()) {
+ if(newHolder.getX() < holder.getX()) {
+ //holder�̂ق�����
+ if(holder.getLeft() != null) {
+ holder.getLeft().setRight(newHolder);
+ }
+ newHolder.setLeft(holder.getLeft());
+
+ holder.setLeft(newHolder);
+ newHolder.setRight(holder);
+ return;
+ }
+ }
+ //�܂��E�̂�͂���H
+ if(holder.hasRight()) {
+ holder = holder.getRight();
+ }
+ //�����E�̂�͂��Ȃ�
+ else {
+ holder.setRight(newHolder);
+ newHolder.setLeft(holder);
+ return;
+ }
+ }
+ }
+
+ /**
+ * �㉺���Ȃ���
+ * @param newHolder
+ */
+ private void connectY(WidgetHolder newHolder) {
+ WidgetHolder holder = upMostHolder;
+ while(true) {
+ if(newHolder.getX() < holder.getX()) {
+ //holder�̂ق�����
+ if(holder.getUp() != null) {
+ holder.getUp().setDown(newHolder);
+ }
+ newHolder.setUp(holder.getUp());
+
+ holder.setUp(newHolder);
+ newHolder.setDown(holder);
+ return;
+ }
+ else if(newHolder.getX() == holder.getX()) {
+ if(newHolder.getY() < holder.getY()) {
+ //holder�̂ق�����
+ if(holder.getUp() != null) {
+ holder.getUp().setDown(newHolder);
+ }
+ newHolder.setUp(holder.getUp());
+
+ holder.setUp(newHolder);
+ newHolder.setDown(holder);
+ return;
+ }
+ }
+ //�܂����̂�͂���H
+ if(holder.hasDown()) {
+ holder = holder.getDown();
+ }
+ //�������̂�͂��Ȃ�
+ else {
+ holder.setDown(newHolder);
+ newHolder.setUp(holder);
+ return;
+ }
+ }
+ }
+
+ private class WidgetHolder {
+ private RWTSelectableWidget widget;
+
+ //�s
+ private int x;
+ //��
+ private int y;
+
+ private WidgetHolder up = null;
+ private WidgetHolder down = null;
+ private WidgetHolder right = null;
+ private WidgetHolder left = null;
+
+ public WidgetHolder(RWTSelectableWidget r, int m, int n) {
+ widget = r;
+ x = m;
+ y = n;
+ }
+
+ //getter
+ public RWTWidget getWidget() {
+ return (RWTWidget) widget;
+ }
+
+ public RWTSelectableWidget getSelectableWidget() {
+ return widget;
+ }
+
+ public int getX() {
+ return x;
+ }
+
+ public int getY() {
+ return y;
+ }
+
+ public WidgetHolder getUp() {
+ return up;
+ }
+ public WidgetHolder getDown() {
+ return down;
+ }
+ public WidgetHolder getRight() {
+ return right;
+ }
+ public WidgetHolder getLeft() {
+ return left;
+ }
+
+ //setter
+ public void setUp(WidgetHolder d) {
+ up = d;
+ }
+ public void setDown(WidgetHolder d) {
+ down = d;
+ }
+ public void setRight(WidgetHolder d) {
+ right = d;
+ }
+ public void setLeft(WidgetHolder d) {
+ left = d;
+ }
+
+ public boolean hasUp() {
+ if(up == null) {
+ return false;
+ }
+ return true;
+ }
+
+ public boolean hasDown() {
+ if(down == null) {
+ return false;
+ }
+ return true;
+ }
+
+ public boolean hasRight() {
+ if(right == null) {
+ return false;
+ }
+ return true;
+ }
+
+ public boolean hasLeft() {
+ if(left == null) {
+ return false;
+ }
+ return true;
+ }
+ }
+}
diff --git a/src/main/java/framework/RWT/RWTSelector.java b/src/main/java/framework/RWT/RWTSelector.java
new file mode 100644
index 0000000..33c38e6
--- /dev/null
+++ b/src/main/java/framework/RWT/RWTSelector.java
@@ -0,0 +1,49 @@
+package framework.RWT;
+import java.awt.Component;
+import java.util.ArrayList;
+
+import javax.vecmath.Point2f;
+
+public abstract class RWTSelector extends RWTWidget {
+ protected float relativeX = 0.0f;
+ protected float relativeY = 0.0f;
+ protected float relativeWidth = 0.0f;
+ protected float relativeHeight = 0.0f;
+ protected int x = 0;
+ protected int y = 0;
+ protected int width = 0;
+ protected int height = 0;
+
+ protected RWTSelectableWidget widget = null;
+
+ public void setSelectableWidget(RWTSelectableWidget w) {
+ widget = w;
+ }
+
+ public boolean hasWidget() {
+ if(widget == null) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public void adjust(Component parent) {
+ x = widget.getAbsoluteX();
+ y = widget.getAbsoluteY();
+ width = widget.getAbsoluteWidth();
+ height = widget.getAbsoluteHeight();
+ }
+
+ @Override
+ public boolean isVisible() {
+ if(hasWidget()) {
+ x = widget.getAbsoluteX();
+ y = widget.getAbsoluteY();
+ width = widget.getAbsoluteWidth();
+ height = widget.getAbsoluteHeight();
+ return visible;
+ }
+ return false;
+ }
+}
diff --git a/src/main/java/framework/RWT/RWTVirtualController.java b/src/main/java/framework/RWT/RWTVirtualController.java
new file mode 100644
index 0000000..661f069
--- /dev/null
+++ b/src/main/java/framework/RWT/RWTVirtualController.java
@@ -0,0 +1,116 @@
+package framework.RWT;
+
+import java.awt.event.KeyEvent;
+
+
+public class RWTVirtualController {
+
+ private boolean bKeyDown[][] = {
+ {false, false, false, false, false, false, false, false},
+ {false, false, false, false, false, false, false, false}};
+ private boolean rawKeyDown[] = new boolean[256];
+ private boolean mouseButtonDown1 = false;
+ private boolean mouseButtonDown2 = false;
+ private boolean mouseButtonDown3 = false;
+ private double mouseX = 0;
+ private double mouseY = 0;
+ private static RWTVirtualKey keyMap[] = new RWTVirtualKey[256];
+
+ public static final int UP = 0;
+ public static final int DOWN = 1;
+ public static final int RIGHT = 2;
+ public static final int LEFT = 3;
+ public static final int BUTTON_A = 4;
+ public static final int BUTTON_B = 5;
+ public static final int BUTTON_C = 6;
+ public static final int BUTTON_D = 7;
+
+ public RWTVirtualController() {
+ // player1�p��keyBind�̏�����
+ RWTVirtualController.keyBind(KeyEvent.VK_W, 0, RWTVirtualController.UP); // w
+ RWTVirtualController.keyBind(KeyEvent.VK_D, 0, RWTVirtualController.RIGHT); //d
+ RWTVirtualController.keyBind(KeyEvent.VK_A, 0, RWTVirtualController.LEFT); // a
+ RWTVirtualController.keyBind(KeyEvent.VK_S, 0, RWTVirtualController.DOWN); // s
+ RWTVirtualController.keyBind(KeyEvent.VK_V, 0, RWTVirtualController.BUTTON_B); // v
+ RWTVirtualController.keyBind(KeyEvent.VK_B, 0, RWTVirtualController.BUTTON_A); // b
+ RWTVirtualController.keyBind(KeyEvent.VK_SPACE, 0, RWTVirtualController.BUTTON_C); // space
+ RWTVirtualController.keyBind(KeyEvent.VK_E, 0, RWTVirtualController.BUTTON_D); // e
+
+ // player2�p��keyBind�̏�����
+ RWTVirtualController.keyBind(KeyEvent.VK_O, 1, RWTVirtualController.UP); // o
+ RWTVirtualController.keyBind(KeyEvent.VK_SEMICOLON, 1, RWTVirtualController.RIGHT); //;
+ RWTVirtualController.keyBind(KeyEvent.VK_K, 1, RWTVirtualController.LEFT); // k
+ RWTVirtualController.keyBind(KeyEvent.VK_L, 1, RWTVirtualController.DOWN); // l
+ RWTVirtualController.keyBind(KeyEvent.VK_BACK_SLASH, 1, RWTVirtualController.BUTTON_B); // \
+ RWTVirtualController.keyBind(KeyEvent.VK_SHIFT, 1, RWTVirtualController.BUTTON_A); // shift
+ RWTVirtualController.keyBind(KeyEvent.VK_CONTROL, 1, RWTVirtualController.BUTTON_C); // ctrl
+ RWTVirtualController.keyBind(KeyEvent.VK_P, 1, RWTVirtualController.BUTTON_D); // p
+ }
+
+ static public void keyBind(int keyCode, int playerNo, int buttonNo) {
+ keyMap[keyCode] = new RWTVirtualKey(playerNo, keyCode, buttonNo);
+ }
+
+ public boolean isKeyDown(int player, int keyNo) {
+ return bKeyDown[player][keyNo];
+ }
+
+ public boolean isKeyDown(int keyCode) {
+ return rawKeyDown[keyCode];
+ }
+
+ public void setKeyDown(int keyCode, boolean b) {
+ if (keyMap[keyCode] != null) {
+ bKeyDown[keyMap[keyCode].getPlayer()][keyMap[keyCode].getVirtualKey()] = b;
+ }
+ rawKeyDown[keyCode] = b;
+ }
+
+ public RWTVirtualKey getVirtualKey(int keyCode) {
+ return keyMap[keyCode];
+ }
+
+ public boolean isMouseButtonDown(int buttonNo) {
+ switch (buttonNo) {
+ case 0:
+ return mouseButtonDown1;
+ case 1:
+ return mouseButtonDown2;
+ case 2:
+ return mouseButtonDown3;
+ }
+ return false;
+ }
+
+ public void setMouseButtonDown(int buttonNo, boolean b) {
+ switch (buttonNo) {
+ case 0:
+ mouseButtonDown1 = b;
+ break;
+ case 1:
+ mouseButtonDown2 = b;
+ break;
+ case 2:
+ mouseButtonDown3 = b;
+ break;
+ }
+ }
+
+ public double getMouseX() {
+ return mouseX;
+ }
+
+ public double getMouseY() {
+ return mouseY;
+ }
+
+ public void setMousePosition(double x, double y) {
+ mouseX = x;
+ mouseY = y;
+ }
+
+ public void moveMousePosition(double dx, double dy) {
+ mouseX += dx;
+ mouseY += dy;
+ }
+}
diff --git a/src/main/java/framework/RWT/RWTVirtualKey.java b/src/main/java/framework/RWT/RWTVirtualKey.java
new file mode 100644
index 0000000..9c9640e
--- /dev/null
+++ b/src/main/java/framework/RWT/RWTVirtualKey.java
@@ -0,0 +1,43 @@
+package framework.RWT;
+
+
+public class RWTVirtualKey {
+
+ private int player;
+ private int physicalKey;
+ private int virtualKey;
+
+ public RWTVirtualKey(int player, int physicalKey, int virtualKey){
+ setPlayer(player);
+ setPhysicalKey(physicalKey);
+ setVirtualKey(virtualKey);
+ }
+
+ public void setPlayer(int player) {
+ this.player = player;
+ }
+
+ public int getPlayer() {
+ return player;
+ }
+
+ public void setPhysicalKey(int physicalKey) {
+ this.physicalKey = physicalKey;
+ }
+
+ public int getPhysicalKey() {
+ return physicalKey;
+ }
+
+ public void setVirtualKey(int virtualKey) {
+ this.virtualKey = virtualKey;
+ }
+
+ public int getVirtualKey() {
+ return virtualKey;
+ }
+
+ public void assignPlayer(int playernum) {
+
+ }
+}
diff --git a/src/main/java/framework/RWT/RWTWidget.java b/src/main/java/framework/RWT/RWTWidget.java
new file mode 100644
index 0000000..5c99cc4
--- /dev/null
+++ b/src/main/java/framework/RWT/RWTWidget.java
@@ -0,0 +1,43 @@
+package framework.RWT;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Point;
+import java.util.ArrayList;
+
+import javax.vecmath.Point2f;
+
+/**
+ * �e�R���e�i�ɑ��đ����W�Ŕz�u�ł���GUI���i
+ * @author Wataru
+ *
+ */
+public abstract class RWTWidget {
+ protected Color color = Color.BLACK;
+
+ protected boolean visible = true;
+
+ /**
+ * �e�R���e�i�i�L�����o�X�̏ꍇ������j�̑傫���ɍ��킹�Ĉʒu�ƃT�C�Y������
+ * @param parent
+ */
+ public abstract void adjust(Component parent);
+ public abstract void paint(Graphics g);
+
+ /**
+ * �F��ݒ肷��
+ * @param c
+ */
+ public void setColor(Color c) {
+ color = c;
+ }
+
+ public void setVisible(boolean b) {
+ visible = b;
+ }
+
+ public boolean isVisible() {
+ return visible;
+ }
+}
diff --git a/src/main/java/framework/animation/Animation3D.java b/src/main/java/framework/animation/Animation3D.java
new file mode 100644
index 0000000..45de74e
--- /dev/null
+++ b/src/main/java/framework/animation/Animation3D.java
@@ -0,0 +1,137 @@
+package framework.animation;
+
+import java.util.ArrayList;
+
+import framework.model3D.Position3D;
+import framework.model3D.Quaternion3D;
+
+/**
+ * �K�w�����ꂽ�I�u�W�F�N�g�ɑ���A�j���[�V��������ێ�����i���i�P�ʂňʒu�A�����A�e�N�X�`�����A�j���[�V�����\�j
+ * @author �V�c����
+ *
+ */
+public class Animation3D {
+ public long time = 0;
+
+ private ArrayList partList = new ArrayList();
+ private long maxKey = getMaxKey();
+
+ public Animation3D() {
+ time = 0;
+ }
+
+ public Animation3D(Animation3D a) {
+ time = 0;
+ partList = a.partList;
+ maxKey = a.maxKey;
+ }
+
+ public boolean equals(Animation3D a) {
+ return (partList == a.partList && maxKey == a.maxKey);
+ }
+
+ public void reset() {
+ time = 0;
+ }
+
+ public boolean progress(long interval) {
+ if (maxKey == 0)
+ return true; // ��̃A�j���[�V�����̏ꍇ�������Ȃ�
+ time += interval;
+ // System.out.println(time + "/" + maxKey);
+ if (time > maxKey) {
+ time = time % maxKey; // time���Ō�̗v�f��key�̒l�i�A�j���[�V�����̍Ō��key)���Ă���ꍇ�At���Ō��key�̒l�imaxKey)�Ŋ������]��Ƃ��Đݒ肷��
+ return false;
+ } else
+ return true;
+ }
+
+ public Pose3D getPose() {
+ if (maxKey == 0 || partList.size() == 0)
+ return new DefaultPose3D();
+
+ KeyFrame[] aroundKey = new KeyFrame[2];
+ Quaternion3D q;
+ Position3D p;
+ Quaternion3D tq;
+ Position3D tp;
+ Pose3D pose = new Pose3D();
+ for (int i = 0; i < partList.size(); i++) {
+ aroundKey = partList.get(i).getKey(time);
+
+ // �R�s�[�R���X�g���N�^�̍쐬
+ q = null;
+ p = null;
+ tq = null;
+ tp = null;
+ if (aroundKey[0].getPosition() != null) {
+ p = new Position3D(aroundKey[0].getPosition()); // getPosition()���Q�Ƃ�Ԃ��̂ŃR�s�[���Ă���ύX
+ }
+ if (aroundKey[0].getQuaternion() != null) {
+ q = new Quaternion3D(aroundKey[0].getQuaternion()); // getQuaternion()���A�h���X�i�Q�Ɓj��Ԃ��̂ŁA�R�s�[�i�����j���쐬���Ă������ύX���Ă���B
+ }
+ if (aroundKey[0].getTexturePosition() != null) {
+ tp = new Position3D(aroundKey[0].getTexturePosition()); // getPosition()���Q�Ƃ�Ԃ��̂ŃR�s�[���Ă���ύX
+ }
+ if (aroundKey[0].getTextureQuaternion() != null) {
+ tq = new Quaternion3D(aroundKey[0].getTextureQuaternion()); // getQuaternion()���A�h���X�i�Q�Ɓj��Ԃ��̂ŁA�R�s�[�i�����j���쐬���Ă������ύX���Ă���B
+ }
+
+ // time��key���̂��̂������ꍇ�i��Ԃ̌v�Z���s�v�ȏꍇ�j
+ if (aroundKey[1] != null) {
+ // t1 ��t�̑O��key�iaroundKey[0]�j�̃X�J���[�{
+ double t1 = aroundKey[1].key - time;
+ // t2 ��t�̌��key�iaroundKey[1]�j�̃X�J���[�{
+ double t2 = time - aroundKey[0].key;
+ double t3 = aroundKey[1].key - aroundKey[0].key;
+ double timealpha = t2 / t3;
+
+ // time�ɑ���Quaternion��Position�̌v�Z
+ if (p != null) {
+ Position3D p2 = new Position3D(aroundKey[1].getPosition());
+ p.mul(t1 / t3).add(p2.mul(t2 / t3));
+ }
+ if (q != null) {
+ Quaternion3D q2 = new Quaternion3D(aroundKey[1].getQuaternion());
+ q.getInterpolate(q2, timealpha);
+ }
+ if (tp != null) {
+ Position3D tp2 = new Position3D(aroundKey[1].getTexturePosition());
+ tp.mul(t1 / t3).add(tp2.mul(t2 / t3));
+ }
+ if (tq != null) {
+ Quaternion3D tq2 = new Quaternion3D(aroundKey[1].getTextureQuaternion());
+ tq.getInterpolate(tq2, timealpha);
+ }
+ }
+ pose.addPose(partList.get(i).getName(), p, q, aroundKey[0].getTexture(), tp, tq, partList.get(i).getTextureUnit());
+ }
+
+ return pose;
+ }
+
+ public Animation3D merge(Animation3D a) {
+ this.partList.addAll(a.partList);
+ maxKey = getMaxKey();
+ return this;
+ }
+
+ public void addPartAnimation(PartAnimation pa) {
+ partList.add(pa);
+ maxKey = getMaxKey();
+ }
+
+ // �A�j���[�V�������I���������肷�邽�߂�key�̍ő�l��T�����ĕԂ����\�b�h
+ private long getMaxKey() {
+ long maxKey = 0;
+ int i;
+
+ for (i = 0; i < partList.size(); i++) {
+ if (maxKey < partList.get(i).getLastKey()) {
+ maxKey = partList.get(i).getLastKey();
+ } else
+ continue;
+ }
+ return maxKey;
+ }
+}
diff --git a/src/main/java/framework/animation/AnimationFactory.java b/src/main/java/framework/animation/AnimationFactory.java
new file mode 100644
index 0000000..ca36a75
--- /dev/null
+++ b/src/main/java/framework/animation/AnimationFactory.java
@@ -0,0 +1,138 @@
+package framework.animation;
+
+import java.awt.GraphicsConfiguration;
+import java.util.ArrayList;
+
+import javax.media.j3d.Canvas3D;
+import javax.media.j3d.View;
+
+import com.sun.j3d.utils.universe.SimpleUniverse;
+
+import cv97.SceneGraph;
+import cv97.field.MFFloat;
+import cv97.field.MFVec3f;
+import cv97.j3d.AppearanceNodeObject;
+import cv97.j3d.IndexedFaceSetNodeObject;
+import cv97.j3d.SceneGraphJ3dObject;
+import cv97.node.AppearanceNode;
+import cv97.node.BackgroundNode;
+import cv97.node.IndexedFaceSetNode;
+import cv97.node.Node;
+import cv97.node.NodeObject;
+import cv97.node.OrientationInterpolatorNode;
+import cv97.node.PositionInterpolatorNode;
+import cv97.node.ShapeNode;
+import cv97.node.SpotLightNode;
+import cv97.node.TransformNode;
+import cv97.util.LinkedListNode;
+import framework.model3D.Position3D;
+import framework.model3D.Quaternion3D;
+import framework.schedule.ScheduleManager;
+import framework.schedule.TaskController;
+
+public class AnimationFactory {
+ private static Canvas3D canvas = new Canvas3D(SimpleUniverse.getPreferredConfiguration());
+
+ public static Animation3D loadAnimation(String fileName){
+
+ SceneGraph sg = new SceneGraph(SceneGraph.NORMAL_GENERATION);
+
+ // �t�@�C���ǂݍ��ݎ��Ƀ����_�����O���s����̂ŁA�I�t�X�N���[�������_�����O���֎~����
+ TaskController renderingController = ScheduleManager.getInstance().getController("rendering");
+ renderingController.waitForActivation();
+ renderingController.activate();
+
+ // �t�@�C���ǂݍ���
+ View view = canvas.getView();
+ if (view != null) view.removeCanvas3D(canvas);
+ SceneGraphJ3dObject sgObject = new SceneGraphJ3dObject(canvas, sg);
+ sg.setObject(sgObject);
+ sg.load(fileName);
+
+ // �I�t�X�N���[�������_�����O�̋���
+ renderingController.deactivate();
+
+ // Animation3D�ւ̕ϊ�
+ Animation3D animation= loadAnimation(sg);
+
+ return animation;
+ }
+
+ private static Animation3D loadAnimation(LinkedListNode node){
+ Animation3D mergedAnimation = null;
+ System.out.println(node.getClass());
+
+ if( ! (node instanceof PositionInterpolatorNode || node instanceof OrientationInterpolatorNode) ){
+ Node childNodes;
+ String name = "";
+ if (node instanceof SceneGraph) {
+ childNodes = ((SceneGraph)node).getNodes();
+ } else {
+ childNodes = ((Node)node).getChildNodes();
+ name = ((Node)node).getName();
+ }
+ if(childNodes != null){
+
+ for(Node n = childNodes;n != null;n = n.next()){
+ Animation3D animation;
+ if((animation = loadAnimation(n)) != null){
+ if (mergedAnimation != null) {
+ mergedAnimation.merge(animation);
+ } else {
+ mergedAnimation = animation;
+ }
+ }
+
+ //�Z��Ŗ������[�v�ɂȂ�Ȃ��悤�ɂ��鏈��
+ Node dummy = n;
+ dummy = dummy.next();
+ if(n == dummy){
+ break;
+ }
+ }
+
+// System.out.println("�q���̐���"+ list.size());
+
+ if(mergedAnimation != null){
+ return mergedAnimation;
+ }
+ }
+ return null;
+ } else if (node instanceof PositionInterpolatorNode) {
+
+ String name = ((PositionInterpolatorNode)node).getName();
+ PositionInterpolatorNode pi = (PositionInterpolatorNode)node;
+
+ //�A�j���[�V�����f�[�^�̎擾
+ int i=0;
+ PartAnimation pa = new PartAnimation(name);
+ for(i=0;i keyList = new ArrayList();
+ public static final int SINGLE_TEXTURE = -1;
+
+ public PartAnimation(String name) {
+ this.name = name;
+ textureUnit = SINGLE_TEXTURE;
+ }
+
+ public PartAnimation(String name, int textureUnit) {
+ this.name = name;
+ this.textureUnit = textureUnit;
+ }
+
+ String getName() {
+ return name;
+ }
+
+ int getTextureUnit() {
+ return textureUnit;
+ }
+
+ //�A�j���[�V�����̌o�ߎ��Ԃ̑O���key��KeyFrame�^�̔z��Ŏ擾���郁�\�b�h
+ KeyFrame[] getKey(long t){
+ int i;
+ KeyFrame[] aroundKey = new KeyFrame[2];
+
+ for(i=1;i partPoseList = new ArrayList();
+
+ public Pose3D() {
+ }
+
+ public Pose3D(Pose3D p) {
+ partPoseList = new ArrayList(p.partPoseList);
+ }
+
+ public void applyTo(Object3D obj) {
+ // obj.rotate(part, vx, vy, vz, a);
+ int n = partPoseList.size();
+ for (int i = 0; i < n; i++) {
+ final PartPose partpose = (PartPose) partPoseList.get(i);
+ Object3D partObj = obj.getPart(partpose.name);
+ if (partObj != null) {
+ // �ʒu
+ if (partpose.position != null)
+ partObj.apply(partpose.position, false);
+ // ����
+ if (partpose.quaternion != null)
+ partObj.apply(partpose.quaternion, false);
+ // �e�N�X�`��
+ if (partpose.texture != null
+ || partpose.texturePosition != null
+ || partpose.textureQuaternion != null) {
+ ObjectVisitor v = new ObjectVisitor() {
+ @Override
+ public void postVisit(Object3D obj) {
+ Appearance appearance = null;
+ Node node = obj.getPrimitiveNode();
+ if (node != null && node instanceof Shape3D) {
+ appearance = ((Shape3D)node).getAppearance();
+ } else if (node != null && node instanceof Primitive) {
+ appearance = ((Primitive)node).getAppearance();
+ }
+ if (appearance != null) {
+ TextureUnitState tu = null;
+ if (partpose.texture != null) {
+ if (partpose.textureUnit == PartAnimation.SINGLE_TEXTURE) {
+ appearance.setTexture(partpose.texture);
+ } else {
+ tu = appearance.getTextureUnitState(partpose.textureUnit);
+ tu.setTexture(partpose.texture);
+ appearance.setTextureUnitState(partpose.textureUnit, tu);
+ }
+ }
+ if ((partpose.texturePosition != null || partpose.textureQuaternion != null)
+ && obj.hasAppearancePrepared()) { // Appearance ������̃����_�����O�̒��O�ōX�V�����\�������邽��
+ TextureAttributes ta;
+ if (partpose.textureUnit == PartAnimation.SINGLE_TEXTURE) {
+ ta = appearance.getTextureAttributes();
+ } else {
+ tu = appearance.getTextureUnitState(partpose.textureUnit);
+ ta = tu.getTextureAttributes();
+ }
+ if (ta == null) {
+ ta = new TextureAttributes();
+ ta.setCapability(TextureAttributes.ALLOW_TRANSFORM_READ);
+ ta.setCapability(TextureAttributes.ALLOW_TRANSFORM_WRITE);
+ }
+ Transform3D t = new Transform3D();
+ if (partpose.texturePosition != null) {
+ t.set(new Vector3d(partpose.texturePosition.getVector3d()));
+ }
+ if (partpose.textureQuaternion != null) {
+ Transform3D t2 = new Transform3D();
+ t2.set(partpose.textureQuaternion.getQuat());
+ t.mul(t2);
+ }
+// shape.getAppearance().getTextureAttributes().setTextureTransform(t);
+ ta.setTextureTransform(t);
+ if (partpose.textureUnit == PartAnimation.SINGLE_TEXTURE) {
+ appearance.setTextureAttributes(ta);
+ } else {
+ tu.setTextureAttributes(ta);
+ appearance.setTextureUnitState(partpose.textureUnit, tu);
+ }
+ }
+ }
+ }
+ @Override
+ public void preVisit(Object3D obj) {
+ }
+ };
+ partObj.accept(v);
+ }
+ }
+ }
+ }
+
+ public void addPose(String name, Position3D p, Quaternion3D q, Texture texture, Position3D tp, Quaternion3D tq, int textureUnit) {
+ PartPose partpose = new PartPose(name, p, q, texture, tp, tq, textureUnit);
+ partPoseList.add(partpose);
+ }
+
+ @Override
+ public Property3D clone() {
+ // TODO Auto-generated method stub
+ return new Pose3D(this);
+ }
+}
diff --git a/src/main/java/framework/audio/BGM3D.java b/src/main/java/framework/audio/BGM3D.java
new file mode 100644
index 0000000..6d0dd55
--- /dev/null
+++ b/src/main/java/framework/audio/BGM3D.java
@@ -0,0 +1,15 @@
+package framework.audio;
+
+public class BGM3D {
+ private static Sound3D currentBGM = null;
+
+ public static Sound3D registerBGM(String fileName) {
+ return new Sound3D(fileName);
+ }
+
+ public static void playBGM(Sound3D newBGM) {
+ if (currentBGM != null) currentBGM.stop();
+ newBGM.loopPlay();
+ currentBGM = newBGM;
+ }
+}
diff --git a/src/main/java/framework/audio/Sound3D.java b/src/main/java/framework/audio/Sound3D.java
new file mode 100644
index 0000000..9ba50f2
--- /dev/null
+++ b/src/main/java/framework/audio/Sound3D.java
@@ -0,0 +1,60 @@
+package framework.audio;
+import java.io.File;
+import java.io.IOException;
+
+import javax.sound.sampled.AudioInputStream;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.Clip;
+import javax.sound.sampled.Control;
+import javax.sound.sampled.DataLine;
+import javax.sound.sampled.FloatControl;
+import javax.sound.sampled.LineUnavailableException;
+import javax.sound.sampled.UnsupportedAudioFileException;
+
+
+public class Sound3D {
+ private Clip clip = null;
+
+ public Sound3D(String fileName) {
+ Clip clip = null;
+ AudioInputStream aistream;
+ try {
+ File file = new File(fileName);
+ aistream = AudioSystem.getAudioInputStream(file);
+ DataLine.Info info = new DataLine.Info(Clip.class, aistream.getFormat());
+ clip = (Clip)AudioSystem.getLine(info);
+ clip.open(aistream);
+ } catch (UnsupportedAudioFileException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (LineUnavailableException e) {
+ e.printStackTrace();
+ }
+ this.clip = clip;
+ }
+
+ public void play() {
+ clip.stop();
+ clip.setFramePosition(0);
+ clip.start();
+ }
+
+ public void play(double vol) {
+ FloatControl control = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
+ control.setValue((float)Math.log10(vol) * 20);
+ clip.stop();
+ clip.setFramePosition(0);
+ clip.start();
+ }
+
+ public void loopPlay() {
+ clip.stop();
+ clip.setFramePosition(0);
+ clip.loop(Clip.LOOP_CONTINUOUSLY);
+ }
+
+ public void stop() {
+ clip.stop();
+ }
+}
diff --git a/src/main/java/framework/gameMain/AbstractGame.java b/src/main/java/framework/gameMain/AbstractGame.java
new file mode 100644
index 0000000..2cf83ae
--- /dev/null
+++ b/src/main/java/framework/gameMain/AbstractGame.java
@@ -0,0 +1,95 @@
+package framework.gameMain;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+import framework.RWT.RWTFrame3D;
+import framework.schedule.ScheduleManager;
+
+/**
+ * �Q�[���̊�{�N���X
+ * @author �V�c����
+ *
+ */
+public abstract class AbstractGame implements Runnable {
+ protected RWTFrame3D mainFrame;
+ private ScheduledExecutorService t;
+ private long minimumFrameTime = 5;
+ private long maximumFrameTime = 15;
+ private boolean bWaitForRender = true;
+ private long prevTime = 0L;
+
+ public abstract RWTFrame3D createFrame3D();
+ protected abstract IGameState getCurrentGameState();
+
+ public AbstractGame() {
+ mainFrame = createFrame3D();
+ }
+
+ public void start() {
+ if (getCurrentGameState() != null) {
+ activateState(getCurrentGameState());
+ }
+ }
+
+ public void stop() {
+ if (getCurrentGameState() != null) {
+ deactivateState(getCurrentGameState());
+ }
+ }
+
+ public void setFramePolicy(long minimumFrameTime, boolean bWaitForRender) {
+ this.minimumFrameTime = minimumFrameTime;
+ this.bWaitForRender = bWaitForRender;
+ }
+
+ public void setFramePolicy(long minimumFrameTime, long maximumFrameTime, boolean bWaitForRender) {
+ this.minimumFrameTime = minimumFrameTime;
+ this.maximumFrameTime = maximumFrameTime;
+ this.bWaitForRender = bWaitForRender;
+ }
+
+ public void run() {
+ if (bWaitForRender) {
+ // �����_�����O�̏I���Ɠ������ăQ�[����i�߂�
+ ScheduleManager.getInstance().getController("rendering").waitForActivation();
+ }
+ mainFrame.doRender();
+ long curTime = System.currentTimeMillis();
+ long interval;
+ if (prevTime == 0L) {
+ interval = minimumFrameTime;
+ } else {
+ interval = curTime - prevTime;
+ if (interval > maximumFrameTime) {
+ interval = maximumFrameTime;
+ }
+ }
+ prevTime = curTime;
+ // ���̃Q�[����Ԃ�update���ĂԁB
+ getCurrentGameState().update(mainFrame.getVirtualController(), interval);
+ }
+
+ protected void activateState(IGameState s) {
+ s.init(mainFrame);
+ if(s.useTimer()){
+ timerRun();
+ }
+ }
+
+ protected void deactivateState(IGameState s) {
+ if(s.useTimer()){
+ timerCancel();
+ }
+ }
+
+ private void timerCancel() {
+ if (t != null) t.shutdownNow();
+ }
+
+ private void timerRun() {
+ t = new ScheduledThreadPoolExecutor(1);
+ // scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit)
+ t.scheduleWithFixedDelay(this, minimumFrameTime, minimumFrameTime, TimeUnit.MILLISECONDS);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/framework/gameMain/AbstractGameState.java b/src/main/java/framework/gameMain/AbstractGameState.java
new file mode 100644
index 0000000..f41976b
--- /dev/null
+++ b/src/main/java/framework/gameMain/AbstractGameState.java
@@ -0,0 +1,55 @@
+package framework.gameMain;
+
+import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsDevice;
+import java.awt.GraphicsEnvironment;
+import java.util.ArrayList;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import javax.media.j3d.GraphicsConfigTemplate3D;
+
+import com.sun.j3d.utils.universe.SimpleUniverse;
+
+import framework.RWT.RWTFrame3D;
+import framework.RWT.RWTCanvas3D;
+import framework.RWT.RWTContainer;
+import framework.RWT.RWTVirtualController;
+import framework.model3D.Universe;
+
+public abstract class AbstractGameState implements IGameState {
+ protected RWTContainer container;
+
+ public void init(RWTFrame3D frame) {
+ if (container == null) {
+ container = createContainer();
+ }
+ frame.setContentPane(container);
+ GraphicsConfiguration gc = null;
+ if (frame.isShadowCasting()) {
+ // �e��t����ꍇ
+ // �X�e���V���o�b�t�@���g�p���� GraphicsConfiguration �̐���
+ GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
+ GraphicsDevice gd = ge.getDefaultScreenDevice();
+ GraphicsConfigTemplate3D gct3D = new GraphicsConfigTemplate3D();
+ gct3D.setStencilSize(8);
+ gc = gd.getBestConfiguration(gct3D);
+ }
+ container.build(gc);
+ }
+
+ public abstract RWTContainer createContainer();
+ /* (non-Javadoc)
+ * @see IGameState#useTimer()
+ */
+ public abstract boolean useTimer();
+ /* (non-Javadoc)
+ * @see IGameState#progress(RWTVirtualController)
+ */
+ public abstract void update(RWTVirtualController virtualController, long interval);
+
+ public RWTCanvas3D getRWTCanvas3D() {
+ if (container == null) return null;
+ return container.getPrimaryRWTCanvas3D();
+ }
+}
diff --git a/src/main/java/framework/gameMain/AbstractManager.java b/src/main/java/framework/gameMain/AbstractManager.java
new file mode 100644
index 0000000..ca9a1d3
--- /dev/null
+++ b/src/main/java/framework/gameMain/AbstractManager.java
@@ -0,0 +1,208 @@
+package framework.gameMain;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.ArrayList;
+
+public abstract class AbstractManager {
+
+ private DataBox data = new DataBox();
+ private BufferedReader reader = null;
+ private String seekFilename;
+
+ protected void addSeekFile(String filename) {
+ seekFilename = filename;
+ }
+
+ protected void seek(String d) {
+ File file = new File(d);
+ //�f�B���N�g���̂Ƃ�
+ if(file.isDirectory()) {
+ openDirectory(file.listFiles());
+ }
+ //�t�@�C���̂Ƃ�
+ else {
+ openFile(file);
+ }
+ }
+
+ //�f�B���N�g����������
+ private void openDirectory(File[] fileList) {
+ File file;
+ for(int i = 0; i < fileList.length; i++) {
+ file = fileList[i];
+ //�f�B���N�g���̂Ƃ�
+ if(file.isDirectory()) {
+ openDirectory(file.listFiles());
+ }
+ //�t�@�C���̂Ƃ�
+ else {
+ openFile(file);
+ }
+ }
+ }
+ //�t�@�C����������
+ private void openFile(File file) {
+ if(file.getName().equals(seekFilename)) {
+ data.removeAll();
+
+ try {
+ reader = new BufferedReader(new FileReader(file));
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ }
+
+ findFile(file);
+
+ try {
+ reader.close();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * setBufferedReader(File file)�����邱��
+ */
+ protected String readLine() {
+ if(reader != null) {
+ try {
+ return reader.readLine();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ return null;
+ }
+
+ protected void setTags(ArrayList tags) {
+ for(int i = 0; i < tags.size(); i++) {
+ data.setTag(tags.get(i));
+ }
+ }
+ protected void setTag(String tag) {
+ data.setTag(tag);
+ }
+
+ protected void findFile(File file) {
+ String str;
+ while(true) {
+ str = readLine();
+ if(str == null) {
+ break;
+ }
+ String[] strings = str.split(":");
+ if(strings.length >= 2) {
+ data.setData(strings[0], strings[1]);
+ }
+ }
+ create();
+ }
+
+ protected String getData(String tag) {
+ return data.getData(tag);
+ }
+
+ public boolean hasData(String tag){
+ if(data.getData(tag) == null)
+ return false;
+ else if(data.getData(tag) == "")
+ return false;
+ else return true;
+ }
+
+ abstract protected void create();
+
+ private class DataBox {
+ private ArrayList dataList = new ArrayList();
+
+ public void setTag(String tag) {
+ dataList.add(new Data(tag));
+ }
+
+ public void setData(String tag, String data) {
+ for(int i = 0; i < dataList.size(); i++) {
+ if(dataList.get(i).getTag().equals(tag)) {
+ dataList.get(i).addData(data);
+ }
+ }
+ }
+
+ /**
+ * ����key�̃f�[�^��Ԃ��B
+ * @param key �^�O��
+ * @return
+ */
+ public String getData(String tag) {
+ for(int i = 0; i < dataList.size(); i++) {
+ if(dataList.get(i).getTag().equals(tag)) {
+ if(dataList.get(i).getData().size() > 0) {
+ return dataList.get(i).getData().get(0);
+ }
+ else {
+ break;
+ }
+ }
+ }
+ return "";
+ }
+
+ public ArrayList getDatas(String tag) {
+ for(int i = 0; i < dataList.size(); i++) {
+ if(dataList.get(i).getTag().equals(tag)) {
+ return dataList.get(i).getData();
+ }
+ }
+ return new ArrayList();
+ }
+
+ /**
+ * ���̃^�O�����݂��邩�B
+ * @param tag
+ * @return
+ */
+ public boolean isExist(String tag) {
+ for(int i = 0; i < dataList.size(); i++) {
+ if(dataList.get(i).getTag().equals(tag)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void removeAll() {
+ for(int i = 0; i < dataList.size(); i++) {
+ dataList.get(i).removeData();
+ }
+ }
+ }
+
+ private class Data {
+ private String tag;
+ private ArrayList data = new ArrayList();
+
+ public Data(String tag) {
+ this.tag = tag;
+ }
+
+ public String getTag() {
+ return tag;
+ }
+
+ public void addData(String d) {
+ data.add(d);
+ }
+
+ public ArrayList getData() {
+ return data;
+ }
+
+ public void removeData() {
+ data = new ArrayList();
+ }
+ }
+}
diff --git a/src/main/java/framework/gameMain/Actor.java b/src/main/java/framework/gameMain/Actor.java
new file mode 100644
index 0000000..ff0cf29
--- /dev/null
+++ b/src/main/java/framework/gameMain/Actor.java
@@ -0,0 +1,348 @@
+package framework.gameMain;
+
+
+import java.util.ArrayList;
+
+import javax.media.j3d.Transform3D;
+import javax.vecmath.AxisAngle4d;
+import javax.vecmath.Vector3d;
+
+import framework.animation.Animation3D;
+import framework.model3D.CollisionResult;
+import framework.model3D.GeometryUtility;
+import framework.model3D.Object3D;
+import framework.model3D.Position3D;
+import framework.model3D.Quaternion3D;
+import framework.physics.Force3D;
+import framework.physics.Ground;
+import framework.physics.PhysicsUtility;
+import framework.physics.Solid3D;
+import framework.physics.Velocity3D;
+
+/**
+ * �Q�[�����̓o�ꕨ�S��
+ * @author �V�c����
+ *
+ */
+public abstract class Actor extends Animatable {
+ protected Vector3d direction = new Vector3d(1.0, 0.0, 0.0);
+ protected Mode mode;
+ // �ȉ��ȃ��������̂��ߗ\�߃C���X�^���X��
+ protected Mode modeFreeFall = new ModeFreeFall();
+ protected Mode modeOnGround = new ModeOnGround();
+
+ public Actor(Object3D body, Animation3D animation) {
+ super(new Solid3D(body), animation);
+ mode = modeOnGround;
+ }
+
+ public Actor(Solid3D body, Animation3D animation) {
+ super(body, animation);
+ mode = modeOnGround;
+ }
+
+ public Actor(ActorModel model) {
+ super(model.createBody(), model.getAnimation());
+ mode = modeOnGround;
+ }
+
+ /**
+ * �P�ʎ��Ԃ��Ƃ̓���i�Փ˔��菈���͍s��Ȃ��j
+ * @param interval --- �O��Ăяo���ꂽ�Ƃ�����̌o�ߎ��ԁi�~���b�P�ʁj
+ */
+ public void motion(long interval){
+ // 1. �ʒu����
+ ((Solid3D)body).move(interval, getGravity(), getGravityCenter());
+ super.motion(interval);
+ }
+
+ /**
+ * �P�ʎ��Ԃ��Ƃ̓���i�Փ˔��菈�����s���j
+ * @param interval --- �O��Ăяo���ꂽ�Ƃ�����̌o�ߎ��ԁi�~���b�P�ʁj
+ * @param ground --- �n�ʁi�\�����j
+ */
+ public void motion(long interval, Ground ground) {
+
+ // 1. �ʒu����
+ ((Solid3D)body).move(interval, getGravity(), getGravityCenter());
+
+ if (animation != null) {
+ // 2. �A�j���[�V���������s
+ if (animation.progress(interval) == false) {
+ onEndAnimation();
+ }
+
+ // 3. �p�����
+ body.apply(animation.getPose(), false);
+ }
+
+ // 4. �Փ˔���
+ CollisionResult cr = PhysicsUtility.doesIntersect((Solid3D)body, ground);
+
+ // 5. �Փˉ���
+ if (cr != null) {
+ // �\�����ɂԂ������A�܂��͐ڐG���Ă��鎞
+ if (cr.normal.dot(PhysicsUtility.vertical) > GeometryUtility.TOLERANCE) {
+ // ������̖ʁi���n�ʁj�ɂԂ������A�܂��͐ڐG���Ă��鎞
+ if (cr.length <= GeometryUtility.TOLERANCE) {
+ // �n�ʂɏ���Ă���
+ if (!(mode instanceof ModeOnGround)) {
+ // �����Ă��Ē��x�����
+ mode = modeOnGround;
+ ((ModeOnGround)mode).setNormal(cr.normal);
+ onEndFall();
+ }
+ } else {
+ // �n�ʂɂ߂荞��
+ // 5.1. �����߂�
+ onIntersect(cr, interval);
+ if (!(mode instanceof ModeOnGround)) {
+ // �����Ă��Ă߂荞��
+ // 6. �n�ʃ��[�h�ɂ���
+ mode = modeOnGround;
+ ((ModeOnGround)mode).setNormal(cr.normal);
+ onEndFall();
+ } else {
+ // �����Ă���r���ŁA�A�j���[�V�����̊W�ň�u�����߂荞��
+ // �܂��́A�����Ă���r���ŎΖʂɍ����|������
+ ((ModeOnGround)mode).setNormal(cr.normal);
+ }
+ }
+ } else if (cr.normal.dot(PhysicsUtility.vertical) >= -GeometryUtility.TOLERANCE) {
+ // �����ǂɂ߂荞��
+ // 5.1. �����߂�
+ onIntersect(cr, interval);
+ } else {
+ // ������Ԃ������A�܂��͐ڐG����(�����Ԃ���)
+ if (cr.length > GeometryUtility.TOLERANCE) {
+ // 5.1. �����߂�
+ onIntersect(cr, interval);
+ }
+ }
+ cr = null;
+ } else {
+ // �n�ʂƂԂ����Ă��ڐG���Ă����Ȃ���
+ // 6. �������[�h�ɂ���
+ mode = modeFreeFall;
+ }
+ }
+
+ public void motion(long interval, Ground ground,ArrayList forces,
+ ArrayList appPoints) {
+
+ forces.add(getGravity());
+ appPoints.add(getGravityCenter());
+
+ // 1. �ʒu����
+ ((Solid3D)body).move(interval, forces, appPoints);
+
+ if (animation != null) {
+ // 2. �A�j���[�V���������s
+ if (animation.progress(interval) == false) {
+ onEndAnimation();
+ }
+
+ // 3. �p�����
+ body.apply(animation.getPose(), false);
+ }
+
+ // 4. �Փ˔���
+ CollisionResult cr = PhysicsUtility.doesIntersect((Solid3D)body, ground);
+
+ // 5. �Փˉ���
+ if (cr != null) {
+ // �\�����ɂԂ������A�܂��͐ڐG���Ă��鎞
+ if (cr.normal.dot(PhysicsUtility.vertical) > GeometryUtility.TOLERANCE) {
+ // ������̖ʁi���n�ʁj�ɂԂ������A�܂��͐ڐG���Ă��鎞
+ if (cr.length <= GeometryUtility.TOLERANCE) {
+ // �n�ʂɏ���Ă���
+ if (!(mode instanceof ModeOnGround)) {
+ // �����Ă��Ē��x�����
+ mode = modeOnGround;
+ ((ModeOnGround)mode).setNormal(cr.normal);
+ onEndFall();
+ }
+ } else {
+ // �n�ʂɂ߂荞��
+ // 5.1. �����߂�
+ onIntersect(cr, interval);
+ if (!(mode instanceof ModeOnGround)) {
+ // �����Ă��Ă߂荞��
+ // 6. �n�ʃ��[�h�ɂ���
+ mode = modeOnGround;
+ ((ModeOnGround)mode).setNormal(cr.normal);
+ onEndFall();
+ } else {
+ // �����Ă���r���ŁA�A�j���[�V�����̊W�ň�u�����߂荞��
+ // �܂��́A�����Ă���r���ŎΖʂɍ����|������
+ ((ModeOnGround)mode).setNormal(cr.normal);
+ }
+ }
+ } else if (cr.normal.dot(PhysicsUtility.vertical) >= -GeometryUtility.TOLERANCE) {
+ // �����ǂɂ߂荞��
+ // 5.1. �����߂�
+ onIntersect(cr, interval);
+ } else {
+ // ������Ԃ������A�܂��͐ڐG����(�����Ԃ���)
+ if (cr.length > GeometryUtility.TOLERANCE) {
+ // 5.1. �����߂�
+ onIntersect(cr, interval);
+ }
+ }
+ cr = null;
+ } else {
+ // �n�ʂƂԂ����Ă��ڐG���Ă����Ȃ���
+ // 6. �������[�h�ɂ���
+ mode = modeFreeFall;
+ }
+ }
+
+ public void setInitialDirection(Vector3d dir) {
+ direction = dir;
+ }
+
+ public Vector3d getInitialDirection() {
+ return direction;
+ }
+
+ /**
+ * �w�肵�������Ɍ�������
+ * @param vec �V��������
+ */
+ public void setDirection(Vector3d vec) {
+ Vector3d v1 = new Vector3d();
+ Vector3d v2 = new Vector3d();
+ v1.cross(direction, GeometryUtility.Y_AXIS);
+ v2.cross(vec, GeometryUtility.Y_AXIS);
+ if (v2.length() < GeometryUtility.TOLERANCE) return;
+ v1.normalize();
+ v2.normalize();
+ double cos = v1.dot(v2);
+ v1.cross(v1, v2);
+ double sin = v1.dot(GeometryUtility.Y_AXIS);
+ double angle = Math.atan2(sin, cos);
+ AxisAngle4d axisAngle = new AxisAngle4d(GeometryUtility.Y_AXIS, angle);
+ Quaternion3D quat = new Quaternion3D(axisAngle);
+ ((Solid3D)body).apply(quat, false);
+ }
+
+ /**
+ * �w�肵�������Ɍ�������
+ * @param vec �V��������
+ */
+ public void setDirection3D(Vector3d vec) {
+ Vector3d v1 = new Vector3d();
+ Vector3d v2 = new Vector3d();
+ v1.cross(direction, GeometryUtility.Y_AXIS);
+ double angle = Math.PI / 2.0 - Math.acos(vec.dot(GeometryUtility.Y_AXIS));
+ AxisAngle4d axisAngle2 = new AxisAngle4d(v1, angle);
+ v2.cross(vec, GeometryUtility.Y_AXIS);
+ if (v2.length() < GeometryUtility.TOLERANCE) return;
+ v1.normalize();
+ v2.normalize();
+ double cos = v1.dot(v2);
+ v1.cross(v1, v2);
+ double sin = v1.dot(GeometryUtility.Y_AXIS);
+ angle = Math.atan2(sin, cos);
+ AxisAngle4d axisAngle = new AxisAngle4d(GeometryUtility.Y_AXIS, angle);
+ Quaternion3D quat = new Quaternion3D(axisAngle);
+ Quaternion3D quat2 = new Quaternion3D(axisAngle2);
+ quat.mul(quat2);
+ ((Solid3D)body).apply(quat, false);
+ }
+
+ /**
+ * �������Ă���������擾����
+ * @return ���݂̌���
+ */
+ public Vector3d getDirection() {
+ Vector3d dir = new Vector3d(direction);
+ Transform3D trans = new Transform3D();
+ trans.set(((Solid3D)body).getQuaternion().getAxisAngle());
+ trans.transform(dir);
+ return dir;
+ }
+
+ /**
+ * �ړ����x�x�N�g����ݒ肷��
+ * @param vel �V�����ړ����x�x�N�g��
+ */
+ public void setVelocity(Velocity3D vel) {
+ ((Solid3D)body).apply(vel, false);
+ }
+
+ /**
+ * �ړ����x�x�N�g�����擾����
+ * @return ���݂̈ړ����x�x�N�g��
+ */
+ public Velocity3D getVelocity() {
+ return ((Solid3D)body).getVelocity();
+ }
+
+ /**
+ * X���𒆐S�ɉ�]����
+ * @param angle ��]�p�i�����v���, �P��:���W�A���j
+ */
+ public void rotX(double angle) {
+ Quaternion3D curQuat = body.getQuaternion();
+ curQuat.add(new AxisAngle4d(GeometryUtility.X_AXIS, angle));
+ body.apply(curQuat, false);
+ }
+
+ /**
+ * Y���𒆐S�ɉ�]����
+ * @param angle ��]�p�i�����v���, �P��:���W�A���j
+ */
+ public void rotY(double angle) {
+ Quaternion3D curQuat = body.getQuaternion();
+ curQuat.add(new AxisAngle4d(GeometryUtility.Y_AXIS, angle));
+ body.apply(curQuat, false);
+ }
+
+ /**
+ * Z���𒆐S�ɉ�]����
+ * @param angle ��]�p�i�����v���, �P��:���W�A���j
+ */
+ public void rotZ(double angle) {
+ Quaternion3D curQuat = body.getQuaternion();
+ curQuat.add(new AxisAngle4d(GeometryUtility.Z_AXIS, angle));
+ body.apply(curQuat, false);
+ }
+
+ /**
+ * ������Ă���d�͂��擾����
+ * @return �d��
+ */
+ public Force3D getGravity() {
+ return mode.getForce((Solid3D)body);
+ }
+
+ /**
+ * �d�S���擾����
+ * @return �d�S�ʒu
+ */
+ public Position3D getGravityCenter() {
+ return ((Solid3D)body).getGravityCenter();
+ }
+
+ /**
+ * �n�ʂɏ���Ă����Ԃ��ۂ����擾����
+ * @return true --- �n�ʂɏ���Ă���, false --- �n�ʂɏ���Ă��Ȃ��i�ɂ���j
+ */
+ public boolean isOnGround() {
+ return (mode instanceof ModeOnGround);
+ }
+
+ /**
+ * �n�ʁi�\�����j�ɗ��������u�ԂɌĂяo�����
+ */
+ public abstract void onEndFall();
+
+ /**
+ * �n�ʁi�\�����j�ɏՓ˂����u�ԂɌĂяo�����
+ * @param normal --- �n�ʂ̖@�������x�N�g��
+ * @param interval --- �O��̓��삩��̌o�ߎ��ԁi�~���b�P�ʁj
+ */
+ public abstract void onIntersect(CollisionResult normal, long interval);
+
+}
diff --git a/src/main/java/framework/gameMain/ActorModel.java b/src/main/java/framework/gameMain/ActorModel.java
new file mode 100644
index 0000000..1ef7b5a
--- /dev/null
+++ b/src/main/java/framework/gameMain/ActorModel.java
@@ -0,0 +1,14 @@
+package framework.gameMain;
+import framework.physics.Solid3D;
+
+
+public abstract class ActorModel extends GameModel {
+
+ public ActorModel(String fileName) {
+ super(fileName);
+ }
+
+ public Solid3D createBody() {
+ return new Solid3D(getModel().createObject());
+ }
+}
diff --git a/src/main/java/framework/gameMain/Animatable.java b/src/main/java/framework/gameMain/Animatable.java
new file mode 100644
index 0000000..8258207
--- /dev/null
+++ b/src/main/java/framework/gameMain/Animatable.java
@@ -0,0 +1,57 @@
+package framework.gameMain;
+
+import javax.media.j3d.TransformGroup;
+
+import framework.animation.Animation3D;
+import framework.model3D.BaseObject3D;
+import framework.model3D.Object3D;
+import framework.model3D.Position3D;
+import framework.model3D.Placeable;
+
+public abstract class Animatable implements Placeable {
+ public Object3D body;
+ public Animation3D animation;
+
+ public Animatable(Object3D body, Animation3D animation) {
+ this.body = body;
+ this.animation = animation;
+ }
+
+ /**
+ * �P�ʎ��Ԃ��Ƃ̓���i�A�j���[�V���������j
+ * @param interval --- �O��Ăяo���ꂽ�Ƃ�����̌o�ߎ��ԁi�~���b�P�ʁj
+ */
+ public void motion(long interval) {
+ if (animation != null) {
+ // 1. �A�j���[�V���������s
+ if (animation.progress(interval) == false) {
+ onEndAnimation();
+ }
+
+ // 2. �p�����
+ body.apply(animation.getPose(), false);
+ }
+ }
+
+ public TransformGroup getTransformGroupToPlace() {
+ return getBody().getTransformGroupToPlace();
+ }
+
+ public BaseObject3D getBody() {
+ return body;
+ }
+
+ /**
+ * �A�j���[�V�������I�����邽�тɌĂ��
+ */
+ public abstract void onEndAnimation();
+
+ public Position3D getPosition() {
+ return body.getPosition3D();
+ }
+
+ public void setPosition(Position3D p) {
+ body.apply(p, false);
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/framework/gameMain/BaseGame.java b/src/main/java/framework/gameMain/BaseGame.java
new file mode 100644
index 0000000..604f6bc
--- /dev/null
+++ b/src/main/java/framework/gameMain/BaseGame.java
@@ -0,0 +1,50 @@
+package framework.gameMain;
+
+import java.util.Stack;
+import java.util.Timer;
+import java.util.TimerTask;
+
+/**
+ * ��ʓI�ȃQ�[���p�̃N���X�i��ԑJ�ڂ������Ƃ��ł���j
+ * @author �V�c����
+ *
+ */
+public abstract class BaseGame extends AbstractGame {
+ Stack gameStateStack = new Stack();
+
+ public abstract AbstractGameState getInitialGameState();
+ public abstract boolean canGoPrevGameState();
+ public abstract AbstractGameState changeNextGameState();
+
+ public BaseGame() {
+ super();
+ pushNewGameState(getInitialGameState());
+ }
+
+ protected AbstractGameState getCurrentGameState() {
+ return gameStateStack.peek();
+ }
+
+ public void goNextGameState(){
+ deactivateState(getCurrentGameState());
+ AbstractGameState g = changeNextGameState();
+ pushNewGameState(g);
+ activateState(g);
+ }
+
+ public void goPrevGameState(){
+ if(canGoPrevGameState()){
+ deactivateState(getCurrentGameState());
+ popGameState();
+ activateState(getCurrentGameState());
+ }
+ }
+
+ private void pushNewGameState(AbstractGameState g) {
+ gameStateStack.push(g);
+ }
+
+ private void popGameState() {
+ gameStateStack.pop();
+ }
+}
diff --git a/src/main/java/framework/gameMain/BaseScenarioGameContainer.java b/src/main/java/framework/gameMain/BaseScenarioGameContainer.java
new file mode 100644
index 0000000..fe4a9bd
--- /dev/null
+++ b/src/main/java/framework/gameMain/BaseScenarioGameContainer.java
@@ -0,0 +1,52 @@
+package framework.gameMain;
+
+import java.awt.GraphicsConfiguration;
+
+import framework.RWT.RWTCanvas3D;
+import framework.RWT.RWTContainer;
+import framework.RWT.RWTLabel;
+import framework.scenario.ScenarioManager;
+
+/**
+ * �V�i���I�Q�[���p���
+ * @author Nitta
+ *
+ */
+abstract public class BaseScenarioGameContainer extends RWTContainer {
+ protected RWTCanvas3D canvas;
+ protected RWTLabel dialog;
+ protected ScenarioManager scenario;
+
+ public BaseScenarioGameContainer(ScenarioManager scenario) {
+ this.scenario = scenario;
+ }
+
+ @Override
+ public void build(GraphicsConfiguration gc) {
+ if (gc != null) {
+ canvas = new RWTCanvas3D(gc);
+ } else {
+ canvas = new RWTCanvas3D();
+ }
+ dialog = new RWTLabel();
+ }
+
+ public void dialogOpen() {
+ dialog.setVisible(true);
+ repaint();
+ }
+
+ public void dialogClose() {
+ dialog.setVisible(false);
+ repaint();
+ }
+
+ public void dialogMessage(String message) {
+ dialog.setString(message);
+ repaint();
+ }
+
+ public boolean isDialogOpen() {
+ return dialog.isVisible();
+ }
+}
diff --git a/src/main/java/framework/gameMain/GameModel.java b/src/main/java/framework/gameMain/GameModel.java
new file mode 100644
index 0000000..6033169
--- /dev/null
+++ b/src/main/java/framework/gameMain/GameModel.java
@@ -0,0 +1,29 @@
+package framework.gameMain;
+import framework.animation.Animation3D;
+import framework.model3D.Model3D;
+import framework.model3D.ModelFactory;
+
+public class GameModel {
+
+ private Model3D model = null;
+ private String fileName;
+
+ public GameModel(String fileName) {
+ this.fileName = fileName;
+ }
+
+ public Animation3D getAnimation() {
+ return new Animation3D();
+ }
+
+ public Model3D getModel() {
+ if(model == null && fileName != null) {
+ model = ModelFactory.loadModel(fileName, false, true);
+ }
+ return model;
+ }
+
+ public void clearModel(){
+ model = null;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/framework/gameMain/IGameState.java b/src/main/java/framework/gameMain/IGameState.java
new file mode 100644
index 0000000..267cee5
--- /dev/null
+++ b/src/main/java/framework/gameMain/IGameState.java
@@ -0,0 +1,9 @@
+package framework.gameMain;
+import framework.RWT.RWTFrame3D;
+import framework.RWT.RWTVirtualController;
+
+public interface IGameState {
+ public abstract void init(RWTFrame3D frame);
+ public abstract boolean useTimer();
+ public abstract void update(RWTVirtualController virtualController, long interval);
+}
\ No newline at end of file
diff --git a/src/main/java/framework/gameMain/Mode.java b/src/main/java/framework/gameMain/Mode.java
new file mode 100644
index 0000000..e7ebe1a
--- /dev/null
+++ b/src/main/java/framework/gameMain/Mode.java
@@ -0,0 +1,10 @@
+package framework.gameMain;
+import framework.physics.Force3D;
+import framework.physics.Solid3D;
+
+
+public abstract class Mode {
+
+ abstract Force3D getForce(Solid3D body);
+
+}
diff --git a/src/main/java/framework/gameMain/ModeFreeFall.java b/src/main/java/framework/gameMain/ModeFreeFall.java
new file mode 100644
index 0000000..97c4b95
--- /dev/null
+++ b/src/main/java/framework/gameMain/ModeFreeFall.java
@@ -0,0 +1,11 @@
+package framework.gameMain;
+import framework.physics.Force3D;
+import framework.physics.PhysicsUtility;
+import framework.physics.Solid3D;
+
+
+public class ModeFreeFall extends Mode {
+ Force3D getForce(Solid3D body) {
+ return PhysicsUtility.getGravity(body);
+ }
+}
diff --git a/src/main/java/framework/gameMain/ModeOnGround.java b/src/main/java/framework/gameMain/ModeOnGround.java
new file mode 100644
index 0000000..f28a6aa
--- /dev/null
+++ b/src/main/java/framework/gameMain/ModeOnGround.java
@@ -0,0 +1,24 @@
+package framework.gameMain;
+
+import javax.vecmath.Vector3d;
+
+import framework.physics.Force3D;
+import framework.physics.PhysicsUtility;
+import framework.physics.Solid3D;
+
+
+public class ModeOnGround extends Mode {
+ private Vector3d normal = PhysicsUtility.vertical;
+
+ public Force3D getForce(Solid3D body) {
+ return Force3D.ZERO;
+ }
+
+ public void setNormal(Vector3d normal) {
+ this.normal = normal;
+ }
+
+ public Vector3d getNormal() {
+ return normal;
+ }
+}
diff --git a/src/main/java/framework/gameMain/MultiViewGame.java b/src/main/java/framework/gameMain/MultiViewGame.java
new file mode 100644
index 0000000..25b2de5
--- /dev/null
+++ b/src/main/java/framework/gameMain/MultiViewGame.java
@@ -0,0 +1,102 @@
+package framework.gameMain;
+
+import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsDevice;
+import java.awt.GraphicsEnvironment;
+
+import javax.media.j3d.BranchGroup;
+import javax.media.j3d.GraphicsConfigTemplate3D;
+
+import com.sun.j3d.utils.universe.SimpleUniverse;
+
+import framework.RWT.RWTFrame3D;
+import framework.RWT.RWTCanvas3D;
+import framework.RWT.RWTContainer;
+import framework.RWT.RWTVirtualController;
+import framework.RWT.RWTVirtualKey;
+import framework.model3D.Universe;
+import framework.view3D.Camera3D;
+
+/**
+ * ��ԑJ�ڂ̂Ȃ��Q�[���p�̃N���X
+ * @author �V�c����
+ *
+ */
+public abstract class MultiViewGame extends AbstractGame implements IGameState {
+ protected Universe universe;
+ protected Camera3D camera1;
+ protected Camera3D camera2;
+ protected RWTContainer container;
+
+ public abstract void init(Universe universe, Camera3D camera1, Camera3D camera2);
+ public abstract void progress(RWTVirtualController virtualController, long interval);
+
+ @Override
+ protected IGameState getCurrentGameState() {
+ return this;
+ }
+
+ @Override
+ public boolean useTimer() {
+ return true;
+ }
+
+ @Override
+ public void init(RWTFrame3D frame) {
+ container = new RWTContainer() {
+ @Override
+ public void build(GraphicsConfiguration gc) {
+ RWTCanvas3D canvas1, canvas2;
+ if (gc != null) {
+ canvas1 = new RWTCanvas3D(gc);
+ canvas2 = new RWTCanvas3D(gc);
+ } else {
+ canvas1 = new RWTCanvas3D();
+ canvas2 = new RWTCanvas3D();
+ }
+ canvas1.setRelativePosition(0.0f, 0.0f);
+ canvas1.setRelativeSize(0.5f, 1.0f);
+ canvas2.setRelativePosition(0.5f, 0.0f);
+ canvas2.setRelativeSize(0.5f, 1.0f);
+ addCanvas(canvas1);
+ addCanvas(canvas2);
+
+ repaint();
+ }
+ // RWT���ł̓C�x���g���������Ȃ�
+ @Override
+ public void keyPressed(RWTVirtualKey key) {}
+ @Override
+ public void keyReleased(RWTVirtualKey key) {}
+ @Override
+ public void keyTyped(RWTVirtualKey key) {}
+ };
+ frame.setContentPane(container);
+ GraphicsConfiguration gc = null;
+ if (frame.isShadowCasting()) {
+ // �e��t����ꍇ
+ // �X�e���V���o�b�t�@���g�p���� GraphicsConfiguration �̐���
+ GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
+ GraphicsDevice gd = ge.getDefaultScreenDevice();
+ GraphicsConfigTemplate3D gct3D = new GraphicsConfigTemplate3D();
+ gct3D.setStencilSize(8);
+ gc = gd.getBestConfiguration(gct3D);
+ }
+ container.build(gc);
+
+ universe = new Universe();
+ camera1 = new Camera3D(universe);
+ camera2 = new Camera3D(universe);
+ init(universe, camera1, camera2);
+ container.getRWTCanvas3D(0).attachCamera(camera1);
+ container.getRWTCanvas3D(1).attachCamera(camera2);
+ universe.compile();
+ }
+
+ @Override
+ public void update(RWTVirtualController virtualController, long interval) {
+ progress(virtualController, interval);
+ camera1.adjust(interval);
+ camera2.adjust(interval);
+ }
+}
diff --git a/src/main/java/framework/gameMain/OvergroundActor.java b/src/main/java/framework/gameMain/OvergroundActor.java
new file mode 100644
index 0000000..7b609d2
--- /dev/null
+++ b/src/main/java/framework/gameMain/OvergroundActor.java
@@ -0,0 +1,51 @@
+package framework.gameMain;
+
+import javax.vecmath.Vector3d;
+
+import framework.animation.Animation3D;
+import framework.model3D.CollisionResult;
+import framework.model3D.Object3D;
+import framework.model3D.Position3D;
+import framework.physics.Solid3D;
+import framework.physics.Velocity3D;
+
+/**
+ * �n�ʂ̏���ړ�������́i�W�����v�⎩�R���������邱�Ƃ��\�j
+ * @author �V�c����
+ *
+ */
+public class OvergroundActor extends Actor {
+
+ public OvergroundActor(Object3D body, Animation3D animation) {
+ super(body, animation);
+ }
+
+ public OvergroundActor(Solid3D body, Animation3D animation) {
+ super(body, animation);
+ }
+
+ public OvergroundActor(ActorModel model) {
+ super(model);
+ }
+
+ public void onIntersect(CollisionResult cr, long interval) {
+ // �߂荞��i�߂荞�ʂ̖@�������Ɂj�����߂�
+ Vector3d back = (Vector3d) cr.normal.clone();
+ back.scale(cr.length * 2.0);
+ body.apply(new Position3D(body.getPosition3D().add(back)), false);
+
+ // ���x�̖ʂ̖@�������̐����� 0 �ɂ���
+ Vector3d v = (Vector3d) ((Solid3D)body).getVelocity().getVector3d().clone();
+ double d = v.dot(cr.normal);
+ v.scaleAdd(-d, cr.normal, v);
+ body.apply(new Velocity3D(v), false);
+ }
+
+ @Override
+ public void onEndFall() {
+ }
+
+ @Override
+ public void onEndAnimation() {
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/framework/gameMain/SimpleGame.java b/src/main/java/framework/gameMain/SimpleGame.java
new file mode 100644
index 0000000..cb6950f
--- /dev/null
+++ b/src/main/java/framework/gameMain/SimpleGame.java
@@ -0,0 +1,100 @@
+package framework.gameMain;
+
+import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsDevice;
+import java.awt.GraphicsEnvironment;
+
+import javax.media.j3d.GraphicsConfigTemplate3D;
+
+import framework.RWT.RWTFrame3D;
+import framework.RWT.RWTCanvas3D;
+import framework.RWT.RWTContainer;
+import framework.RWT.RWTVirtualController;
+import framework.RWT.RWTVirtualKey;
+import framework.model3D.Universe;
+import framework.view3D.Camera3D;
+
+/**
+ * ��ԑJ�ڂ̂Ȃ��Q�[���p�̃N���X
+ * @author �V�c����
+ *
+ */
+public abstract class SimpleGame extends AbstractGame implements IGameState {
+ protected Universe universe;
+ protected Camera3D camera;
+ private IGameState currentState = this;
+
+ public abstract void init(Universe universe, Camera3D camera);
+ public abstract void progress(RWTVirtualController virtualController, long interval);
+
+ @Override
+ protected IGameState getCurrentGameState() {
+ return currentState;
+ }
+
+ protected void setCurrentGameState(IGameState state) {
+ currentState = state;
+ }
+
+ @Override
+ public boolean useTimer() {
+ return true;
+ }
+
+ @Override
+ public void init(RWTFrame3D frame) {
+ RWTContainer container = createRWTContainer();
+ frame.setContentPane(container);
+ GraphicsConfiguration gc = null;
+ if (frame.isShadowCasting()) {
+ // �e��t����ꍇ
+ // �X�e���V���o�b�t�@���g�p���� GraphicsConfiguration �̐���
+ GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
+ GraphicsDevice gd = ge.getDefaultScreenDevice();
+ GraphicsConfigTemplate3D gct3D = new GraphicsConfigTemplate3D();
+ gct3D.setStencilSize(8);
+ gc = gd.getBestConfiguration(gct3D);
+ }
+ container.build(gc);
+
+ universe = new Universe();
+ camera = new Camera3D(universe);
+// universe.setCamera(camera);
+// SceneGraph root = new SceneGraph();
+// universe.setRoot(root);
+ init(universe, camera);
+ container.getPrimaryRWTCanvas3D().attachCamera(camera);
+ universe.compile();
+ }
+
+ @Override
+ public void update(RWTVirtualController virtualController, long interval) {
+ progress(virtualController, interval);
+ camera.adjust(interval);
+ }
+
+ protected RWTContainer createRWTContainer() {
+ return new RWTContainer() {
+ @Override
+ public void build(GraphicsConfiguration gc) {
+ RWTCanvas3D canvas;
+ if (gc != null) {
+ canvas = new RWTCanvas3D(gc);
+ } else {
+ canvas = new RWTCanvas3D();
+ }
+ canvas.setRelativePosition(0.0f, 0.0f);
+ canvas.setRelativeSize(1.0f, 1.0f);
+ addCanvas(canvas);
+ repaint();
+ }
+ // RWT���ł̓C�x���g���������Ȃ�
+ @Override
+ public void keyPressed(RWTVirtualKey key) {}
+ @Override
+ public void keyReleased(RWTVirtualKey key) {}
+ @Override
+ public void keyTyped(RWTVirtualKey key) {}
+ };
+ }
+}
diff --git a/src/main/java/framework/gameMain/SimpleScenarioGame.java b/src/main/java/framework/gameMain/SimpleScenarioGame.java
new file mode 100644
index 0000000..7384e36
--- /dev/null
+++ b/src/main/java/framework/gameMain/SimpleScenarioGame.java
@@ -0,0 +1,42 @@
+package framework.gameMain;
+
+import framework.scenario.IWorld;
+import framework.scenario.ScenarioManager;
+
+/**
+ * �V�i���I�쓮�^�Q�[���̂��߂̃e���v���[�g
+ * @author �V�c����
+ *
+ */
+abstract public class SimpleScenarioGame extends SimpleGame implements IWorld {
+ protected BaseScenarioGameContainer container;
+ protected ScenarioManager scenario;
+
+ @Override
+ public void dialogOpen() {
+ container.dialogOpen();
+ }
+
+ @Override
+ public void dialogClose() {
+ container.dialogClose();
+ }
+
+ @Override
+ public void dialogMessage(String message) {
+ container.dialogMessage(message);
+ }
+
+ @Override
+ public void showOption(int n, String option) {
+ }
+
+ @Override
+ public boolean isDialogOpen() {
+ return container.isDialogOpen();
+ }
+
+ public void setScenario(String scenarioFile) {
+ scenario = new ScenarioManager(scenarioFile, this);
+ }
+}
diff --git a/src/main/java/framework/gameMain/Water.java b/src/main/java/framework/gameMain/Water.java
new file mode 100644
index 0000000..3573405
--- /dev/null
+++ b/src/main/java/framework/gameMain/Water.java
@@ -0,0 +1,210 @@
+package framework.gameMain;
+
+import javax.media.j3d.Appearance;
+import javax.media.j3d.ColoringAttributes;
+import javax.media.j3d.DistanceLOD;
+import javax.media.j3d.IndexedQuadArray;
+import javax.media.j3d.IndexedTriangleArray;
+import javax.media.j3d.Material;
+import javax.media.j3d.Shape3D;
+import javax.media.j3d.Switch;
+import javax.media.j3d.TexCoordGeneration;
+import javax.media.j3d.Texture;
+import javax.media.j3d.TransparencyAttributes;
+import javax.vecmath.Color3f;
+import javax.vecmath.Color4f;
+import javax.vecmath.Point3d;
+import javax.vecmath.Point3f;
+import javax.vecmath.Vector3f;
+import javax.vecmath.Vector4f;
+
+import com.sun.j3d.utils.image.TextureLoader;
+
+import framework.animation.Animation3D;
+import framework.animation.PartAnimation;
+import framework.model3D.BumpMapGenerator;
+import framework.model3D.FresnelsReflectionMapGenerator;
+import framework.model3D.Object3D;
+import framework.model3D.Position3D;
+import framework.model3D.ReflectionMapGenerator;
+
+/**
+ * ���ʂ�\������I�u�W�F�N�g�B
+ * �g�̓����̓o���v�}�b�s���O���X�N���[�������ĕ\�����Ă���B
+ * ���˂ł̓t���l�����ʂ��������Ă���B
+ * Java3D�ł́A���_�Ԃ̔��˃x�N�g���͐��`��Ԃł������߂Ă��Ȃ����߁A
+ * ���x���グ�邽�߂ɁALOD���g���Đ��ʂ̎��_�ɋ߂������̓��b�V���������ׂ������Ă���B
+ * @author Nitta
+ *
+ */
+public class Water extends Animatable {
+ private static int DEFAULT_FIRST_LEVEL_MESH_SIZE = 25;
+ private static int DEFAULT_SECOND_LEVEL_MESH_SIZE = 1;
+ private static int DEFAULT_THIRD_LEVEL_MESH_SIZE = 40;
+
+ public Water(double minX, double minZ, double maxX, double maxZ, double height, boolean bUseLOD) {
+ this(minX, minZ, maxX, maxZ, height, 0.5f, bUseLOD);
+ }
+
+ public Water(double minX, double minZ, double maxX, double maxZ, double height, float transparency, boolean bUseLOD) {
+ this(minX, minZ, maxX, maxZ, height, transparency, 0.3f, bUseLOD);
+ }
+
+ public Water(double minX, double minZ, double maxX, double maxZ, double height, float transparency, float reflection, boolean bUseLOD) {
+ this(minX, minZ, maxX, maxZ, height, transparency, reflection, new Color3f(0.2f, 0.5f, 1.0f), bUseLOD);
+ }
+
+ public Water(double minX, double minZ, double maxX, double maxZ, double height,
+ float transparency, float reflection, Color3f waterColor, boolean bUseLOD) {
+ this(minX, minZ, maxX, maxZ, height, transparency, reflection, new Color3f(0.2f, 0.5f, 1.0f),
+ DEFAULT_FIRST_LEVEL_MESH_SIZE, DEFAULT_SECOND_LEVEL_MESH_SIZE, DEFAULT_THIRD_LEVEL_MESH_SIZE, bUseLOD);
+ }
+
+ public Water(double minX, double minZ, double maxX, double maxZ, double height, float transparency, float reflection,
+ int firstLevelMeshSize, int secondLevelMeshSize, int thirdLevelMeshSize, boolean bUseLOD) {
+ this(minX, minZ, maxX, maxZ, height, transparency, reflection, new Color3f(0.2f, 0.5f, 1.0f),
+ firstLevelMeshSize, secondLevelMeshSize, thirdLevelMeshSize, bUseLOD);
+ }
+
+ public Water(double minX, double minZ, double maxX, double maxZ, double height, float transparency, float reflection, Color3f waterColor,
+ int firstLevelMeshSize, int secondLevelMeshSize, int thirdLevelMeshSize, boolean bUseLOD) {
+ super(null, null);
+
+ int firstLevelMeshSizeX = firstLevelMeshSize;
+ int firstLevelMeshSizeZ = firstLevelMeshSize;
+ int secondLevelMeshSizeX = secondLevelMeshSize;
+ int secondLevelMeshSizeZ = secondLevelMeshSize;
+ int thirdLevelMeshSizeX = thirdLevelMeshSize;
+ int thirdLevelMeshSizeZ = thirdLevelMeshSize;
+
+
+ // ���ʂ̃W�I���g���̍쐬
+ IndexedQuadArray coarseWaterGeometry =
+ new IndexedQuadArray((secondLevelMeshSizeX + 1) * (secondLevelMeshSizeZ + 1),
+ IndexedQuadArray.COORDINATES | IndexedQuadArray.NORMALS, 4 * secondLevelMeshSizeX * secondLevelMeshSizeZ);
+
+ IndexedQuadArray fineWaterGeometry =
+ new IndexedQuadArray((secondLevelMeshSizeX * thirdLevelMeshSizeX + 1) * (secondLevelMeshSizeZ * thirdLevelMeshSizeZ + 1),
+ IndexedQuadArray.COORDINATES | IndexedQuadArray.NORMALS, 4 * secondLevelMeshSizeX * thirdLevelMeshSizeX * secondLevelMeshSizeZ * thirdLevelMeshSizeZ);
+
+ double unitSizeX1 = (maxX - minX) / firstLevelMeshSizeX;
+ double unitSizeZ1 = (maxZ - minZ) / firstLevelMeshSizeZ;
+ double unitSizeX2 = unitSizeX1 / secondLevelMeshSizeX;
+ double unitSizeZ2 = unitSizeZ1 / secondLevelMeshSizeZ;
+ double unitSizeX3 = unitSizeX2 / thirdLevelMeshSizeX;
+ double unitSizeZ3 = unitSizeZ2 / thirdLevelMeshSizeZ;
+ double baseX = -(maxX - minX) / firstLevelMeshSizeX / 2.0;
+ double baseZ = -(maxZ - minZ) / firstLevelMeshSizeZ / 2.0;
+
+ // ���A��O���x���� LOD �Ő�ւ�
+ for (int z2 = 0; z2 < secondLevelMeshSizeZ + 1; z2++) {
+ for (int x2 = 0; x2 < secondLevelMeshSizeX + 1; x2++) {
+ int indexX2 = x2;
+ int indexZ2 = z2;
+ int index20 = indexZ2 * secondLevelMeshSizeX + indexX2;
+ int index21 = indexZ2 * (secondLevelMeshSizeX + 1) + indexX2;
+ int index22 = (indexZ2 + 1) * (secondLevelMeshSizeX + 1) + indexX2;
+ double xx2 = baseX + unitSizeX2 * indexX2;
+ double zz2 = baseZ + unitSizeZ2 * indexZ2;
+ coarseWaterGeometry.setCoordinate(index21, new Point3d(xx2, 0.0, zz2));
+ coarseWaterGeometry.setNormal(index21, new Vector3f(0.0f, 1.0f, 0.0f));
+ if (indexX2 < secondLevelMeshSizeX && indexZ2 < secondLevelMeshSizeZ) {
+ coarseWaterGeometry.setCoordinateIndices(index20 * 4, new int[]{index22, index22 + 1, index21 + 1, index21});
+ if (bUseLOD) {
+ for (int z3 = 0; z3 < thirdLevelMeshSizeZ + 1; z3++) {
+ for (int x3 = 0; x3 < thirdLevelMeshSizeX + 1; x3++) {
+ int indexX3 = x2 * thirdLevelMeshSizeX + x3;
+ int indexZ3 = z2 * thirdLevelMeshSizeZ + z3;
+ int index30 = indexZ3 * (secondLevelMeshSizeX * thirdLevelMeshSizeX) + indexX3;
+ int index31 = indexZ3 * (secondLevelMeshSizeX * thirdLevelMeshSizeX + 1) + indexX3;
+ int index32 = (indexZ3 + 1) * (secondLevelMeshSizeX * thirdLevelMeshSizeX + 1) + indexX3;
+ double xx3 = baseX + unitSizeX3 * indexX3;
+ double zz3 = baseZ + unitSizeZ3 * indexZ3;
+ fineWaterGeometry.setCoordinate(index31, new Point3d(xx3, 0.0, zz3));
+ fineWaterGeometry.setNormal(index31, new Vector3f(0.0f, 1.0f, 0.0f));
+ if (indexX3 < secondLevelMeshSizeX * thirdLevelMeshSizeX
+ && indexZ3 < secondLevelMeshSizeZ * thirdLevelMeshSizeZ) {
+ fineWaterGeometry.setCoordinateIndices(index30 * 4, new int[]{index32, index32 + 1, index31 + 1, index31});
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // ��ꃌ�x���� Object3D �̏W���ō\��
+ Object3D children[] = new Object3D[firstLevelMeshSizeX * firstLevelMeshSizeZ];
+ TextureLoader loaderWater = new TextureLoader("data\\texture\\waternormalMap.jpg",
+ TextureLoader.BY_REFERENCE,
+ null);
+ Texture textureWater = loaderWater.getTexture();
+ // ���ʂ̕\�ʑ����̍쐬�i�S�̂ŋ��L����j
+ Appearance a = new Appearance();
+ a.setCapability(Appearance.ALLOW_TEXTURE_UNIT_STATE_READ);
+ a.setCapability(Appearance.ALLOW_TEXTURE_UNIT_STATE_WRITE);
+ Material m1 = new Material();
+ m1.setDiffuseColor(waterColor); // ���̐F
+ m1.setSpecularColor(0.0f, 0.0f, 0.0f);
+ a.setMaterial(m1);
+ ColoringAttributes ca = new ColoringAttributes();
+ ca.setShadeModel(ColoringAttributes.NICEST);
+ a.setColoringAttributes(ca);
+
+ TransparencyAttributes ta = new TransparencyAttributes();
+ ta.setTransparency(transparency); // �����x
+ ta.setTransparencyMode(TransparencyAttributes.BLENDED);
+ a.setTransparencyAttributes(ta);
+ // �g���\�ʑ����i�S�̂ŋ��L����j
+ TexCoordGeneration tcg = new TexCoordGeneration(TexCoordGeneration.OBJECT_LINEAR, TexCoordGeneration.TEXTURE_COORDINATE_3);
+ tcg.setPlaneS(new Vector4f(0.1f, 0.0f, 0.0f, 0.0f));
+ tcg.setPlaneT(new Vector4f(0.0f, 0.0f, 0.1f, 0.0f));
+ BumpMapGenerator bumpMapGenerator = new BumpMapGenerator(textureWater, tcg, true); // �e�N�X�`�����j�b�g��1�g�p
+ FresnelsReflectionMapGenerator fresnelsReflectionMapGenerator =
+ new FresnelsReflectionMapGenerator(new Color4f(reflection, reflection, reflection, 1.0f), true); // �e�N�X�`�����j�b�g��2�g�p
+
+ for (int z1 = 0; z1 < firstLevelMeshSizeZ; z1++) {
+ for (int x1 = 0; x1 < firstLevelMeshSizeX; x1++) {
+ double xx1 = minX + (maxX - minX) / firstLevelMeshSizeX * x1;
+ double zz1 = minZ + (maxZ - minZ) / firstLevelMeshSizeZ * z1;
+ Object3D waterSurfaceUnit;
+ if (bUseLOD) {
+ DistanceLOD lod = new DistanceLOD();
+ Switch surfaceSwitch = new Switch();
+ surfaceSwitch.addChild(new Shape3D(fineWaterGeometry, a));
+ surfaceSwitch.addChild(new Shape3D(coarseWaterGeometry, a));
+ lod.addSwitch(surfaceSwitch);
+ lod.setDistance(0, unitSizeX1 / 2.0);
+ lod.setPosition(new Point3f(0.0f, 0.0f, 0.0f));
+ waterSurfaceUnit = new Object3D("waterUnit", lod);
+ } else {
+ waterSurfaceUnit = new Object3D("waterUnit", new Shape3D(coarseWaterGeometry, a));
+ }
+ waterSurfaceUnit.apply(new Position3D(xx1, height, zz1), false);
+
+ // �g���\�ʑ�����ݒ�
+ waterSurfaceUnit.setBumpMapping(bumpMapGenerator);
+ waterSurfaceUnit.setReflectionMapping(fresnelsReflectionMapGenerator);
+
+ children[z1 * firstLevelMeshSizeX + x1] = waterSurfaceUnit;
+ }
+ }
+
+ // �S�̃I�u�W�F�N�g���\��
+ Object3D waterSurface = new Object3D("water", children);
+
+ body = waterSurface;
+
+ // �A�j���[�V�����̍쐬
+ Animation3D waveAnimation = new Animation3D();
+ PartAnimation pa = new PartAnimation("waterUnit", 0);
+ pa.addTexture(0L, new Position3D(0.0, 0.0, 0.0));
+ pa.addTexture(10000L, new Position3D(1.0, -1.0, 0.0));
+ waveAnimation.addPartAnimation(pa);
+ animation = waveAnimation;
+ }
+
+ @Override
+ public void onEndAnimation() {
+ }
+}
diff --git a/src/main/java/framework/model3D/BackgroundBox.java b/src/main/java/framework/model3D/BackgroundBox.java
new file mode 100644
index 0000000..bef8956
--- /dev/null
+++ b/src/main/java/framework/model3D/BackgroundBox.java
@@ -0,0 +1,154 @@
+package framework.model3D;
+
+import javax.media.j3d.Appearance;
+import javax.media.j3d.Background;
+import javax.media.j3d.BranchGroup;
+import javax.media.j3d.ImageComponent2D;
+import javax.media.j3d.QuadArray;
+import javax.media.j3d.Shape3D;
+import javax.media.j3d.Texture;
+import javax.vecmath.Point3d;
+import javax.vecmath.TexCoord2f;
+
+
+public class BackgroundBox extends Background {
+ Texture northTex;
+ Texture westTex;
+ Texture southTex;
+ Texture eastTex;
+ Texture topTex;
+ Texture bottomTex;
+
+ public BackgroundBox(Texture northTex, Texture westTex, Texture southTex, Texture eastTex, Texture topTex, Texture bottomTex) {
+ this.northTex = northTex;
+ this.westTex = westTex;
+ this.southTex = southTex;
+ this.eastTex = eastTex;
+ this.topTex = topTex;
+ this.bottomTex = bottomTex;
+ Point3d p0 = new Point3d(-1.0,-1.0,-1.0);
+ Point3d p1 = new Point3d(-1.0,-1.0, 1.0);
+ Point3d p2 = new Point3d(-1.0, 1.0,-1.0);
+ Point3d p3 = new Point3d(-1.0, 1.0, 1.0);
+ Point3d p4 = new Point3d( 1.0, 1.0,-1.0);
+ Point3d p5 = new Point3d( 1.0, 1.0, 1.0);
+ Point3d p6 = new Point3d( 1.0,-1.0,-1.0);
+ Point3d p7 = new Point3d( 1.0,-1.0, 1.0);
+ QuadArray top = new QuadArray(4, QuadArray.COORDINATES | QuadArray.TEXTURE_COORDINATE_2);
+ top.setCoordinate(0, p4);
+ top.setCoordinate(1, p5);
+ top.setCoordinate(2, p3);
+ top.setCoordinate(3, p2);
+ top.setTextureCoordinate(0, 0, new TexCoord2f(1.0f, 0.0f));
+ top.setTextureCoordinate(0, 1, new TexCoord2f(1.0f, 1.0f));
+ top.setTextureCoordinate(0, 2, new TexCoord2f(0.0f, 1.0f));
+ top.setTextureCoordinate(0, 3, new TexCoord2f(0.0f, 0.0f));
+ QuadArray bottom = new QuadArray(4, QuadArray.COORDINATES | QuadArray.TEXTURE_COORDINATE_2);
+ bottom.setCoordinate(0, p7);
+ bottom.setCoordinate(1, p6);
+ bottom.setCoordinate(2, p0);
+ bottom.setCoordinate(3, p1);
+ bottom.setTextureCoordinate(0, 0, new TexCoord2f(1.0f, 0.0f));
+ bottom.setTextureCoordinate(0, 1, new TexCoord2f(1.0f, 1.0f));
+ bottom.setTextureCoordinate(0, 2, new TexCoord2f(0.0f, 1.0f));
+ bottom.setTextureCoordinate(0, 3, new TexCoord2f(0.0f, 0.0f));
+ QuadArray north = new QuadArray(4, QuadArray.COORDINATES | QuadArray.TEXTURE_COORDINATE_2);
+ north.setCoordinate(0, p4);
+ north.setCoordinate(1, p6);
+ north.setCoordinate(2, p7);
+ north.setCoordinate(3, p5);
+ north.setTextureCoordinate(0, 0, new TexCoord2f(1.0f, 0.0f));
+ north.setTextureCoordinate(0, 1, new TexCoord2f(1.0f, 1.0f));
+ north.setTextureCoordinate(0, 2, new TexCoord2f(0.0f, 1.0f));
+ north.setTextureCoordinate(0, 3, new TexCoord2f(0.0f, 0.0f));
+ QuadArray south = new QuadArray(4, QuadArray.COORDINATES | QuadArray.TEXTURE_COORDINATE_2);
+ south.setCoordinate(0, p3);
+ south.setCoordinate(1, p1);
+ south.setCoordinate(2, p0);
+ south.setCoordinate(3, p2);
+ south.setTextureCoordinate(0, 0, new TexCoord2f(1.0f, 0.0f));
+ south.setTextureCoordinate(0, 1, new TexCoord2f(1.0f, 1.0f));
+ south.setTextureCoordinate(0, 2, new TexCoord2f(0.0f, 1.0f));
+ south.setTextureCoordinate(0, 3, new TexCoord2f(0.0f, 0.0f));
+ QuadArray east = new QuadArray(4, QuadArray.COORDINATES | QuadArray.TEXTURE_COORDINATE_2);
+ east.setCoordinate(0, p2);
+ east.setCoordinate(1, p0);
+ east.setCoordinate(2, p6);
+ east.setCoordinate(3, p4);
+ east.setTextureCoordinate(0, 0, new TexCoord2f(1.0f, 0.0f));
+ east.setTextureCoordinate(0, 1, new TexCoord2f(1.0f, 1.0f));
+ east.setTextureCoordinate(0, 2, new TexCoord2f(0.0f, 1.0f));
+ east.setTextureCoordinate(0, 3, new TexCoord2f(0.0f, 0.0f));
+ QuadArray west = new QuadArray(4, QuadArray.COORDINATES | QuadArray.TEXTURE_COORDINATE_2);
+ west.setCoordinate(0, p5);
+ west.setCoordinate(1, p7);
+ west.setCoordinate(2, p1);
+ west.setCoordinate(3, p3);
+ west.setTextureCoordinate(0, 0, new TexCoord2f(1.0f, 0.0f));
+ west.setTextureCoordinate(0, 1, new TexCoord2f(1.0f, 1.0f));
+ west.setTextureCoordinate(0, 2, new TexCoord2f(0.0f, 1.0f));
+ west.setTextureCoordinate(0, 3, new TexCoord2f(0.0f, 0.0f));
+ Appearance apTop = new Appearance();
+ apTop.setTexture(topTex);
+ Shape3D shapeTop = new Shape3D(top, apTop);
+
+ Appearance apBottom = new Appearance();
+ apBottom.setTexture(bottomTex);
+ Shape3D shapeBottom = new Shape3D(bottom, apBottom);
+
+ Appearance apNorth = new Appearance();
+ apNorth.setTexture(northTex);
+ Shape3D shapeNorth = new Shape3D(north, apNorth);
+
+ Appearance apSouth = new Appearance();
+ apSouth.setTexture(southTex);
+ Shape3D shapeSouth = new Shape3D(south, apSouth);
+
+ Appearance apWest = new Appearance();
+ apWest.setTexture(westTex);
+ Shape3D shapeWest = new Shape3D(west, apWest);
+
+ Appearance apEast = new Appearance();
+ apEast.setTexture(eastTex);
+ Shape3D shapeEast = new Shape3D(east, apEast);
+
+ BranchGroup bg = new BranchGroup();
+ bg.addChild(shapeTop);
+ bg.addChild(shapeBottom);
+ bg.addChild(shapeNorth);
+ bg.addChild(shapeSouth);
+ bg.addChild(shapeWest);
+ bg.addChild(shapeEast);
+
+ setGeometry(bg);
+ }
+
+ public ImageComponent2D getNorthImage() {
+ return (ImageComponent2D)northTex.getImage(0);
+ }
+
+
+ public ImageComponent2D getSouthImage() {
+ return (ImageComponent2D)southTex.getImage(0);
+ }
+
+
+ public ImageComponent2D getEastImage() {
+ return (ImageComponent2D)eastTex.getImage(0);
+ }
+
+
+ public ImageComponent2D getWestImage() {
+ return (ImageComponent2D)westTex.getImage(0);
+ }
+
+
+ public ImageComponent2D getTopImage() {
+ return (ImageComponent2D)topTex.getImage(0);
+ }
+
+
+ public ImageComponent2D getBottomImage() {
+ return (ImageComponent2D)bottomTex.getImage(0);
+ }
+}
diff --git a/src/main/java/framework/model3D/BaseObject3D.java b/src/main/java/framework/model3D/BaseObject3D.java
new file mode 100644
index 0000000..957c87b
--- /dev/null
+++ b/src/main/java/framework/model3D/BaseObject3D.java
@@ -0,0 +1,489 @@
+package framework.model3D;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+
+import javax.media.j3d.Appearance;
+import javax.media.j3d.BoundingPolytope;
+import javax.media.j3d.Geometry;
+import javax.media.j3d.IndexedTriangleArray;
+import javax.media.j3d.IndexedTriangleFanArray;
+import javax.media.j3d.IndexedTriangleStripArray;
+import javax.media.j3d.Light;
+import javax.media.j3d.Node;
+import javax.media.j3d.Shape3D;
+import javax.media.j3d.Transform3D;
+import javax.media.j3d.TransformGroup;
+import javax.media.j3d.TriangleArray;
+import javax.media.j3d.TriangleFanArray;
+import javax.media.j3d.TriangleStripArray;
+import javax.vecmath.Vector3d;
+import javax.vecmath.Vector4d;
+
+import com.sun.j3d.utils.geometry.Box;
+import com.sun.j3d.utils.geometry.Cone;
+import com.sun.j3d.utils.geometry.Cylinder;
+import com.sun.j3d.utils.geometry.Primitive;
+import com.sun.j3d.utils.geometry.Sphere;
+
+public class BaseObject3D implements Placeable {
+ public TransformGroup center;
+
+ protected BoundingSurface[] boundingSurfaces = null;
+ private ArrayList shadowVolumes = new ArrayList();
+
+ private BumpMapGenerator bumpMapGenerator = null;
+ private ReflectionMapGenerator reflectionMapGenerator = null;
+ protected boolean bBumpMapApplied = false;
+ protected boolean bReflectionMapApplied = false;
+
+ public BaseObject3D() {
+ center = new TransformGroup();
+ center.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
+ center.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
+ }
+
+ public BaseObject3D(Geometry g, Appearance a) {
+ init(g, a);
+ }
+
+ // �R�s�[�R���X�g���N�^
+ public BaseObject3D(BaseObject3D obj) {
+ Transform3D transCenter = new Transform3D();
+ obj.center.getTransform(transCenter);
+ this.center = new TransformGroup(transCenter);
+ this.center.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
+ this.center.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
+ Enumeration nodes = obj.getPrimitiveNodes();
+ for (; nodes.hasMoreElements();) {
+ Node node = nodes.nextElement();
+ if (node != null && node instanceof Shape3D) {
+ Shape3D shape = (Shape3D)node;
+ shape.setCapability(Shape3D.ALLOW_APPEARANCE_READ);
+ shape.setCapability(Shape3D.ALLOW_APPEARANCE_WRITE);
+ Appearance a = (Appearance)shape.getAppearance().cloneNodeComponent(true);
+ a.setCapability(Appearance.ALLOW_TEXTURE_READ);
+ a.setCapability(Appearance.ALLOW_TEXTURE_WRITE);
+ a.setCapability(Appearance.ALLOW_TEXTURE_ATTRIBUTES_READ);
+ a.setCapability(Appearance.ALLOW_TEXTURE_ATTRIBUTES_WRITE);
+ a.setCapability(Appearance.ALLOW_TEXTURE_UNIT_STATE_READ);
+ a.setCapability(Appearance.ALLOW_TEXTURE_UNIT_STATE_WRITE);
+ this.center.addChild(new Shape3D((Geometry) shape
+ .getAllGeometries().nextElement(), a));
+ } else if (node != null && node instanceof Primitive) {
+ Primitive primitive = (Primitive)node;
+ primitive = (Primitive)primitive.cloneTree();
+ primitive.setCapability(Primitive.ENABLE_APPEARANCE_MODIFY);
+ this.center.addChild(primitive);
+ }
+ }
+ if (obj.boundingSurfaces != null) {
+ this.boundingSurfaces = obj.boundingSurfaces;
+ }
+ this.bumpMapGenerator = obj.bumpMapGenerator;
+ this.reflectionMapGenerator = obj.reflectionMapGenerator;
+ this.bBumpMapApplied = obj.bBumpMapApplied;
+ this.bReflectionMapApplied = obj.bReflectionMapApplied;
+ }
+
+ // ����������i�N���[�������j
+ public BaseObject3D duplicate() {
+ BaseObject3D obj = new BaseObject3D(this);
+ return obj;
+ }
+
+ public void init(Geometry g, Appearance a) {
+ center = new TransformGroup();
+ center.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
+ center.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
+ a.setCapability(Appearance.ALLOW_TEXTURE_READ);
+ a.setCapability(Appearance.ALLOW_TEXTURE_WRITE);
+ a.setCapability(Appearance.ALLOW_TEXTURE_ATTRIBUTES_READ);
+ a.setCapability(Appearance.ALLOW_TEXTURE_ATTRIBUTES_WRITE);
+ a.setCapability(Appearance.ALLOW_TEXTURE_UNIT_STATE_READ);
+ a.setCapability(Appearance.ALLOW_TEXTURE_UNIT_STATE_WRITE);
+ Shape3D shape = new Shape3D(g, a);
+ shape.setCapability(Shape3D.ALLOW_APPEARANCE_READ);
+ shape.setCapability(Shape3D.ALLOW_APPEARANCE_WRITE);
+ shape.setCapability(Shape3D.ALLOW_GEOMETRY_READ);
+ shape.setCapability(Shape3D.ALLOW_GEOMETRY_WRITE);
+ center.addChild(shape);
+ }
+
+ public void updateGeometry(Geometry g) {
+ Node node = getPrimitiveNode();
+ if (node != null && node instanceof Shape3D) {
+ ((Shape3D)node).removeAllGeometries();
+ ((Shape3D)node).addGeometry(g);
+ boundingSurfaces = null;
+ }
+ }
+
+ @Override
+ public TransformGroup getTransformGroupToPlace() {
+ return getBody().center;
+ }
+
+ public BaseObject3D getBody() {
+ return this;
+ }
+
+// public void placeFirst(RWTUniverse universe) {
+// universe.getRoot().insertChild(this.center, 0);
+// }
+//
+// public void placeLast(RWTUniverse universe) {
+// universe.getRoot().addChild(this.center);
+// }
+//
+ public Node getPrimitiveNode() {
+ return (Node)center.getChild(0);
+ }
+
+ public Enumeration getPrimitiveNodes() {
+ return (Enumeration)center.getAllChildren();
+ }
+
+ public Appearance getAppearance() {
+ Appearance ap = null;
+ Node node = getPrimitiveNode();
+ if (node != null && node instanceof Shape3D) {
+ Shape3D shape = (Shape3D)node;
+ ap = shape.getAppearance();
+ if (ap == null) {
+ ap = new Appearance();
+ shape.setAppearance(ap);
+ }
+ } else if (node != null && node instanceof Primitive) {
+ Primitive primitive = (Primitive)node;
+ ap = primitive.getAppearance();
+ if (ap == null) {
+ ap = new Appearance();
+ primitive.setAppearance(ap);
+ }
+ }
+ return ap;
+ }
+
+ public ArrayList getAppearances() {
+ ArrayList appearances = new ArrayList();
+ appearances.add(getAppearance());
+ return appearances;
+ }
+
+ /**
+ * �Փ˔���p�̃{�����[���i�|���S���Ƒe������p�̑��p���j���擾����
+ * @return�@�Փ˔���p�̃{�����[����
+ */
+ public BoundingSurface[] getBoundingSurfaces() {
+ if (boundingSurfaces == null) {
+ Node node = getPrimitiveNode();
+ if (node == null) return null;
+
+ ArrayList vertex3DList = null;
+ if (node instanceof Box) {
+ // Box�̏ꍇ
+ Box box = ((Box)node);
+ // ���_����擾����
+ vertex3DList = getVertexList(box.getShape(Box.BACK).getGeometry());
+ vertex3DList.addAll(getVertexList(box.getShape(Box.BOTTOM).getGeometry()));
+ vertex3DList.addAll(getVertexList(box.getShape(Box.FRONT).getGeometry()));
+ vertex3DList.addAll(getVertexList(box.getShape(Box.LEFT).getGeometry()));
+ vertex3DList.addAll(getVertexList(box.getShape(Box.RIGHT).getGeometry()));
+ vertex3DList.addAll(getVertexList(box.getShape(Box.TOP).getGeometry()));
+ } else if (node instanceof Cylinder) {
+ // Cylinder�̏ꍇ
+ Cylinder cylinder = ((Cylinder)node);
+ // ���_����擾����
+ vertex3DList = getVertexList(cylinder.getShape(Cylinder.BODY).getGeometry());
+ vertex3DList.addAll(getVertexList(cylinder.getShape(Cylinder.BOTTOM).getGeometry()));
+ vertex3DList.addAll(getVertexList(cylinder.getShape(Cylinder.TOP).getGeometry()));
+ } else if (node instanceof Cone) {
+ // Cone�̏ꍇ
+ Cone cone = ((Cone)node);
+ // ���_����擾����
+ vertex3DList = getVertexList(cone.getShape(Cone.BODY).getGeometry());
+ vertex3DList.addAll(getVertexList(cone.getShape(Cone.CAP).getGeometry()));
+ } else if (node instanceof Sphere) {
+ // Sphere�̏ꍇ
+ Sphere sphere = ((Sphere)node);
+ // ���_����擾����
+ vertex3DList = getVertexList(sphere.getShape(Sphere.BODY).getGeometry());
+ } else if (node instanceof Shape3D) {
+ // Shape3D�̏ꍇ
+ Shape3D shape = (Shape3D)node;
+ // ���_����擾����
+ vertex3DList = getVertexList(shape.getGeometry());
+ }
+ if (vertex3DList == null) return null;
+
+ BoundingSurface[] surfaces = new BoundingSurface[vertex3DList.size() / 3];
+
+ for (int i = 0; i < vertex3DList.size(); i += 3) {
+ Vector3d v1 = vertex3DList.get(i);
+ Vector3d v2 = vertex3DList.get(i + 1);
+ Vector3d v3 = vertex3DList.get(i + 2);
+ BoundingSurface bSurface = new BoundingSurface();
+ bSurface.addVertex((Vector3d)v1.clone());
+ bSurface.addVertex((Vector3d)v2.clone());
+ bSurface.addVertex((Vector3d)v3.clone());
+ bSurface.setBounds(createBoundingPolytope(v1, v2, v3));
+ surfaces[i / 3] = bSurface;
+ }
+ boundingSurfaces = surfaces;
+ }
+ return boundingSurfaces;
+ }
+
+ private ArrayList getVertexList(Geometry g) {
+ ArrayList vertex3DList = new ArrayList();
+ double coordinate1[] = new double[3];
+ if (g instanceof IndexedTriangleArray) {
+ // IndexedTriangleArray �̏ꍇ
+ IndexedTriangleArray triArray = (IndexedTriangleArray)g;
+
+ // �S���_��3D��̒��_��vertex3DList�ɓ���Ă����B
+ for (int i = 0; i < triArray.getIndexCount(); i++) {
+ triArray.getCoordinates(triArray.getCoordinateIndex(i), coordinate1);
+ vertex3DList.add(new Vector3d(coordinate1));
+ }
+ } else if (g instanceof TriangleArray) {
+ // TriangleArray �̏ꍇ
+ TriangleArray triArray = (TriangleArray)g;
+
+ // �S���_��3D��̒��_��vertex3DList�ɓ���Ă����B
+ for (int i = 0; i < triArray.getVertexCount(); i++) {
+ triArray.getCoordinates(i, coordinate1);
+ vertex3DList.add(new Vector3d(coordinate1));
+ }
+ } else if (g instanceof IndexedTriangleStripArray) {
+ // IndexedTriangleStripArray �̏ꍇ
+ IndexedTriangleStripArray triStripAttay = (IndexedTriangleStripArray)g;
+ int stripVertexCounts[] = new int[triStripAttay.getNumStrips()];
+ triStripAttay.getStripIndexCounts(stripVertexCounts);
+ // �S���_��3D��̒��_��vertex3DList�ɓ���Ă���
+ int index = 0;
+ double coordinate2[] = new double[3];
+ double coordinate3[] = new double[3];
+ double coordinate4[] = new double[3];
+ for (int i = 0; i < triStripAttay.getNumStrips(); i++) {
+ for (int j = 0; j < stripVertexCounts[i]; j += 2) {
+ triStripAttay.getCoordinates(triStripAttay.getCoordinateIndex(index), coordinate1);
+ triStripAttay.getCoordinates(triStripAttay.getCoordinateIndex(index+1), coordinate2);
+ triStripAttay.getCoordinates(triStripAttay.getCoordinateIndex(index+2), coordinate3);
+ triStripAttay.getCoordinates(triStripAttay.getCoordinateIndex(index+3), coordinate4);
+ vertex3DList.add(new Vector3d(coordinate1)); //1�߂̎O�p�`
+ vertex3DList.add(new Vector3d(coordinate2));
+ vertex3DList.add(new Vector3d(coordinate3));
+ vertex3DList.add(new Vector3d(coordinate2)); //2�߂̎O�p�`
+ vertex3DList.add(new Vector3d(coordinate4));
+ vertex3DList.add(new Vector3d(coordinate3));
+ index += 2;
+ }
+ }
+ } else if (g instanceof TriangleStripArray) {
+ // TriangleStripArray �̏ꍇ
+ TriangleStripArray triStripAttay = (TriangleStripArray)g;
+ int stripVertexCounts[] = new int[triStripAttay.getNumStrips()];
+ triStripAttay.getStripVertexCounts(stripVertexCounts);
+ // �S���_��3D��̒��_��vertex3DList�ɓ���Ă���
+ int index = 0;
+ double coordinate2[] = new double[3];
+ double coordinate3[] = new double[3];
+ double coordinate4[] = new double[3];
+ for (int i = 0; i < triStripAttay.getNumStrips(); i++) {
+ for (int j = 0; j < stripVertexCounts[i]; j += 2) {
+ triStripAttay.getCoordinates(index, coordinate1);
+ triStripAttay.getCoordinates(index+1, coordinate2);
+ triStripAttay.getCoordinates(index+2, coordinate3);
+ triStripAttay.getCoordinates(index+3, coordinate4);
+ vertex3DList.add(new Vector3d(coordinate1)); //1�߂̎O�p�`
+ vertex3DList.add(new Vector3d(coordinate2));
+ vertex3DList.add(new Vector3d(coordinate3));
+ vertex3DList.add(new Vector3d(coordinate2)); //2�߂̎O�p�`
+ vertex3DList.add(new Vector3d(coordinate4));
+ vertex3DList.add(new Vector3d(coordinate3));
+ index += 2;
+ }
+ }
+ } else if (g instanceof IndexedTriangleFanArray) {
+ // IndexedTriangleFanArray �̏ꍇ
+ IndexedTriangleFanArray triFanAttay = (IndexedTriangleFanArray)g;
+ int stripVertexCounts[] = new int[triFanAttay.getNumStrips()];
+ triFanAttay.getStripIndexCounts(stripVertexCounts);
+ // �S���_��3D��̒��_��vertex3DList�ɓ���Ă���
+ int index = 0;
+ double coordinate2[] = new double[3];
+ double coordinate3[] = new double[3];
+ double coordinate4[] = null;
+ for (int i = 0; i < triFanAttay.getNumStrips(); i++) {
+ triFanAttay.getCoordinates(triFanAttay.getCoordinateIndex(index), coordinate1); // ���S�_
+ triFanAttay.getCoordinates(triFanAttay.getCoordinateIndex(index+1), coordinate2);
+ index += 2;
+ for (int j = 2; j < stripVertexCounts[i]; j++) {
+ triFanAttay.getCoordinates(triFanAttay.getCoordinateIndex(index), coordinate3);
+ vertex3DList.add(new Vector3d(coordinate1));
+ vertex3DList.add(new Vector3d(coordinate2));
+ vertex3DList.add(new Vector3d(coordinate3));
+ coordinate4 = coordinate2;
+ coordinate2 = coordinate3;
+ coordinate3 = coordinate4;
+ index++;
+ }
+ }
+ } else if (g instanceof TriangleFanArray) {
+ // TriangleFanArray �̏ꍇ
+ TriangleFanArray triFanAttay = (TriangleFanArray)g;
+ int stripVertexCounts[] = new int[triFanAttay.getNumStrips()];
+ triFanAttay.getStripVertexCounts(stripVertexCounts);
+ // �S���_��3D��̒��_��vertex3DList�ɓ���Ă���
+ int index = 0;
+ double coordinate2[] = new double[3];
+ double coordinate3[] = new double[3];
+ double coordinate4[] = null;
+ for (int i = 0; i < triFanAttay.getNumStrips(); i++) {
+ triFanAttay.getCoordinates(index, coordinate1); // ���S�_
+ triFanAttay.getCoordinates(index + 1, coordinate2);
+ index += 2;
+ for (int j = 2; j < stripVertexCounts[i]; j++) {
+ triFanAttay.getCoordinates(index, coordinate3);
+ vertex3DList.add(new Vector3d(coordinate1));
+ vertex3DList.add(new Vector3d(coordinate2));
+ vertex3DList.add(new Vector3d(coordinate3));
+ coordinate4 = coordinate2;
+ coordinate2 = coordinate3;
+ coordinate3 = coordinate4;
+ index++;
+ }
+ }
+ } else {
+ // QuadArray�n���͖��Ή�
+ return null;
+ }
+ return vertex3DList;
+ }
+
+ protected BoundingPolytope createBoundingPolytope(Vector3d vertex1,
+ Vector3d vertex2, Vector3d vertex3) {
+ Vector3d v1 = new Vector3d();
+ Vector3d v2 = new Vector3d();
+ Vector3d v3 = new Vector3d();
+ Vector3d v4 = new Vector3d();
+ Vector3d v5 = new Vector3d();
+ Vector3d v6 = new Vector3d();
+ Vector3d cv1 = new Vector3d();
+ Vector3d cv2 = new Vector3d();
+ cv1.sub(vertex3, vertex1);
+ cv2.sub(vertex2, vertex1);
+ Vector3d cv = new Vector3d();
+ cv.cross(cv1, cv2);
+ cv.normalize();
+ cv.scale(0.01);
+ v1.set(vertex1);
+ v2.set(vertex2);
+ v3.set(vertex3);
+ v4.set(vertex1);
+ v4.add(cv);
+ v5.set(vertex2);
+ v5.add(cv);
+ v6.set(vertex3);
+ v6.add(cv);
+
+ Vector3d pv1 = new Vector3d();
+ Vector3d pv2 = new Vector3d();
+ Vector3d pv3 = new Vector3d();
+ Vector3d pn = new Vector3d();
+ Vector4d[] plane = new Vector4d[5];
+
+ // 0
+ pv1 = v1;
+ pv2.sub(v2, v1);
+ pv3.sub(v3, v1);
+
+ pn.cross(pv2, pv3);
+ pn.normalize();
+ plane[0] = new Vector4d(pn.x, pn.y, pn.z, -pn.dot(pv1));
+
+ // 1
+ pv1 = v1;
+ pv2.sub(v4, v1);
+ pv3.sub(v2, v1);
+
+ pn.cross(pv2, pv3);
+ pn.normalize();
+ plane[1] = new Vector4d(pn.x, pn.y, pn.z, -pn.dot(pv1));
+
+ // 2
+ pv1 = v1;
+ pv2.sub(v3, v1);
+ pv3.sub(v4, v1);
+
+ pn.cross(pv2, pv3);
+ pn.normalize();
+ plane[2] = new Vector4d(pn.x, pn.y, pn.z, -pn.dot(pv1));
+
+ // 3
+ pv1 = v6;
+ pv2.sub(v3, v6);
+ pv3.sub(v5, v6);
+
+ pn.cross(pv2, pv3);
+ pn.normalize();
+ plane[3] = new Vector4d(pn.x, pn.y, pn.z, -pn.dot(pv1));
+
+ // 4
+ pv1 = v6;
+ pv2.sub(v5, v6);
+ pv3.sub(v4, v6);
+
+ pn.cross(pv2, pv3);
+ pn.normalize();
+ plane[4] = new Vector4d(pn.x, pn.y, pn.z, -pn.dot(pv1));
+
+ return new BoundingPolytope(plane);
+ }
+
+ public void createShadowVolume(ArrayList lights, double shadowDepth, Transform3D localToWorld) {
+ for (int n = 0; n < lights.size(); n++) {
+ shadowVolumes.add(new ShadowVolume(this, lights.get(n), shadowDepth, localToWorld));
+ }
+ }
+
+ public void updateShadowVolume(Transform3D localToWorld) {
+ for (int n = 0; n < shadowVolumes.size(); n++) {
+ shadowVolumes.get(n).update(localToWorld);
+ }
+ }
+
+ public void setBumpMapping(BumpMapGenerator g) {
+ bumpMapGenerator = g;
+ bBumpMapApplied = true;
+ }
+
+ public BumpMapGenerator getBumpMappingInfo() {
+ return bumpMapGenerator;
+ }
+
+ public boolean isBumpMappingApplied() {
+ return bBumpMapApplied;
+ }
+
+ public void setReflectionMapping(ReflectionMapGenerator g) {
+ reflectionMapGenerator = g;
+ bReflectionMapApplied = true;
+ }
+
+ public ReflectionMapGenerator getReflectionMappingInfo() {
+ return reflectionMapGenerator;
+ }
+
+ public boolean isReflectionMappingApplied() {
+ return bReflectionMapApplied;
+ }
+
+ public boolean hasAppearancePrepared() {
+ if (bumpMapGenerator != null && !bumpMapGenerator.hasMapped()) return false;
+ if (reflectionMapGenerator != null && !reflectionMapGenerator.hasMapped()) return false;
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/framework/model3D/BoundingSurface.java b/src/main/java/framework/model3D/BoundingSurface.java
new file mode 100644
index 0000000..c5383ed
--- /dev/null
+++ b/src/main/java/framework/model3D/BoundingSurface.java
@@ -0,0 +1,128 @@
+package framework.model3D;
+import java.util.ArrayList;
+
+import javax.media.j3d.BoundingPolytope;
+import javax.media.j3d.BoundingSphere;
+import javax.media.j3d.Bounds;
+import javax.media.j3d.Transform3D;
+import javax.vecmath.Matrix4d;
+import javax.vecmath.Point3d;
+import javax.vecmath.Vector3d;
+import javax.vecmath.Vector4d;
+
+
+public class BoundingSurface implements Cloneable {
+ private Bounds bounds = null; // �e���Փ˔���p�i�e���n�ʗp�j
+ private ArrayList children = new ArrayList();
+ private ArrayList vertexList = new ArrayList();
+ private static Vector4d plane[] = { new Vector4d(), new Vector4d(), new Vector4d(),
+ new Vector4d(), new Vector4d() };
+
+ public Object clone() {
+ BoundingSurface s = new BoundingSurface();
+ if (bounds != null) {
+ s.setBounds((Bounds)bounds.clone());
+ }
+ for (int i = 0; i < children.size(); i++) {
+ s.children.add((BoundingSurface)children.get(i).clone());
+ }
+ for (int i = 0; i < vertexList.size(); i++) {
+ s.vertexList.add((Vector3d)vertexList.get(i).clone());
+ }
+ return s;
+ }
+
+ public void setBounds(Bounds bounds) {
+ this.bounds = bounds;
+ }
+
+ public Bounds getBounds() {
+ return bounds;
+ }
+
+ public void addVertex(Vector3d v) {
+ vertexList.add(v);
+ }
+
+ public void addChild(BoundingSurface bs, boolean bCombineBounds) {
+ children.add(bs);
+ if (bCombineBounds) {
+ if (bounds == null) {
+ bounds = (Bounds)bs.bounds.clone();
+ } else {
+ bounds.combine(bs.bounds);
+ }
+ }
+ }
+
+ public void transform(Transform3D transform3D) {
+ bounds.transform(transform3D);
+ for (int i = 0; i < vertexList.size(); i++) {
+ Matrix4d mat4d = new Matrix4d();
+ transform3D.get(mat4d);
+ double x = mat4d.m00 * vertexList.get(i).x + mat4d.m01
+ * vertexList.get(i).y + mat4d.m02 * vertexList.get(i).z
+ + mat4d.m03;
+ double y = mat4d.m10 * vertexList.get(i).x + mat4d.m11
+ * vertexList.get(i).y + mat4d.m12 * vertexList.get(i).z
+ + mat4d.m13;
+ double z = mat4d.m20 * vertexList.get(i).x + mat4d.m21
+ * vertexList.get(i).y + mat4d.m22 * vertexList.get(i).z
+ + mat4d.m23;
+ vertexList.get(i).x = x;
+ vertexList.get(i).y = y;
+ vertexList.get(i).z = z;
+ }
+ }
+
+ /**
+ * BoundingSphere�Ƃ̑e���Փ˔���
+ * @param bs �Փ˔���̑Ώ�
+ * @return �Փ˂��Ă���BoundingSurface�̃��X�g�inull��Ԃ����Ƃ͂Ȃ��j
+ */
+ public ArrayList intersect(BoundingSphere bs) {
+ ArrayList results = new ArrayList();
+ if (children == null || children.size() == 0) {
+ if (bounds.intersect(bs)) {
+ results.add(this);
+ }
+ } else {
+ if (bounds == null || bounds.intersect(bs)) {
+ for (int n = 0; n < children.size(); n++) {
+ results.addAll(children.get(n).intersect(bs));
+ }
+ }
+ }
+ return results;
+ }
+
+ /**
+ * OBB�Ƃ̏ڍׂȏՓ˔���
+ * @param obb �Փ˔���̑Ώ�
+ * @return�@�Փ˔���̌���
+ */
+ public CollisionResult intersect(OBB obb) {
+ if (children == null || children.size() == 0) {
+ // �t�̏ꍇ�́A�ʃ|���S���𗧂��グ���������p��
+ if (bounds instanceof BoundingPolytope) {
+ ((BoundingPolytope)bounds).getPlanes(plane);
+ CollisionResult cr = obb.intersect(plane[0]); // obb����ʂ��܂ޖ������ʂƌ�����Ă��邩�H
+ if (cr != null) {
+ // �������ʂƌ�����Ă���ꍇ�A�������ʂƂ̏Փ˓_���ʃ|���S���̓����Ɉʒu���邩�H
+ if (GeometryUtility.inside(vertexList, cr.collisionPoint.getVector3d(), cr.normal)) {
+ return cr;
+ }
+ }
+ }
+ return null;
+ } else {
+ for (int n = 0; n < children.size(); n++) {
+ CollisionResult cr = children.get(n).intersect(obb);
+ if (cr != null) {
+ return cr;
+ }
+ }
+ return null;
+ }
+ }
+}
diff --git a/src/main/java/framework/model3D/BumpMapGenerator.java b/src/main/java/framework/model3D/BumpMapGenerator.java
new file mode 100644
index 0000000..04a9ad0
--- /dev/null
+++ b/src/main/java/framework/model3D/BumpMapGenerator.java
@@ -0,0 +1,29 @@
+package framework.model3D;
+
+import javax.media.j3d.TexCoordGeneration;
+import javax.media.j3d.Texture;
+import javax.vecmath.Color4f;
+
+public class BumpMapGenerator extends MapGenerator {
+ private Texture bumpMap = null;
+ private TexCoordGeneration texCoorgGen = null;
+ private boolean bHorizontal = false;
+
+ public BumpMapGenerator(Texture bumpMap, TexCoordGeneration texCoorgGen, boolean bHorizontal) {
+ this.bumpMap = bumpMap;
+ this.texCoorgGen = texCoorgGen;
+ this.bHorizontal = bHorizontal;
+ }
+
+ public Texture getBumpMap() {
+ return bumpMap;
+ }
+
+ public TexCoordGeneration getTexCoordGeneration() {
+ return texCoorgGen;
+ }
+
+ public boolean isHorizontal() {
+ return bHorizontal;
+ }
+}
diff --git a/src/main/java/framework/model3D/CollisionResult.java b/src/main/java/framework/model3D/CollisionResult.java
new file mode 100644
index 0000000..e95cd8a
--- /dev/null
+++ b/src/main/java/framework/model3D/CollisionResult.java
@@ -0,0 +1,13 @@
+package framework.model3D;
+import java.util.ArrayList;
+
+import javax.vecmath.Vector3d;
+
+
+
+public class CollisionResult {
+ public Position3D collisionPoint = new Position3D();
+ public ArrayList collisionPoints;
+ public Vector3d normal = new Vector3d();
+ public double length = 0.0;
+}
diff --git a/src/main/java/framework/model3D/ContainerModel.java b/src/main/java/framework/model3D/ContainerModel.java
new file mode 100644
index 0000000..db3f8ea
--- /dev/null
+++ b/src/main/java/framework/model3D/ContainerModel.java
@@ -0,0 +1,42 @@
+package framework.model3D;
+
+import javax.media.j3d.Transform3D;
+
+/**
+ * �q���������f��
+ * @author �V�c����
+ *
+ */
+public class ContainerModel extends Model3D {
+ private Model3D[] children;
+ private Transform3D defaultTransform = null;
+
+ public ContainerModel(String name,Model3D[] children) {
+ this.children = children;
+ this.name = name;
+ this.defaultTransform = null;
+ }
+
+ public ContainerModel(String name, Model3D[] children,
+ Transform3D transform) {
+ this.children = children;
+ this.name = name;
+ this.defaultTransform = transform;
+ }
+
+ public Object3D createObject() {
+ Object3D[] objChild = new Object3D[children.length];
+ for(int i = 0;i < children.length;i++){
+ objChild[i] = (Object3D) children[i].createObject();
+ }
+ return new Object3D(name, objChild, defaultTransform);
+ }
+
+ public Object3D createObjectSharingAppearance() {
+ Object3D[] objChild = new Object3D[children.length];
+ for(int i = 0;i < children.length;i++){
+ objChild[i] = (Object3D) children[i].createObjectSharingAppearance();
+ }
+ return new Object3D(name, objChild, defaultTransform);
+ }
+}
diff --git a/src/main/java/framework/model3D/FresnelsReflectionMapGenerator.java b/src/main/java/framework/model3D/FresnelsReflectionMapGenerator.java
new file mode 100644
index 0000000..1825bfe
--- /dev/null
+++ b/src/main/java/framework/model3D/FresnelsReflectionMapGenerator.java
@@ -0,0 +1,16 @@
+package framework.model3D;
+
+import javax.vecmath.Color4f;
+
+public class FresnelsReflectionMapGenerator extends ReflectionMapGenerator {
+ private boolean bTransparent = true;
+
+ public FresnelsReflectionMapGenerator(Color4f blendColor, boolean bTransparent) {
+ super(blendColor);
+ this.bTransparent = bTransparent;
+ }
+
+ public boolean isTransparent() {
+ return bTransparent;
+ }
+}
diff --git a/src/main/java/framework/model3D/GeometryCollector.java b/src/main/java/framework/model3D/GeometryCollector.java
new file mode 100644
index 0000000..ef92d8d
--- /dev/null
+++ b/src/main/java/framework/model3D/GeometryCollector.java
@@ -0,0 +1,131 @@
+package framework.model3D;
+
+import java.util.ArrayList;
+import java.util.Stack;
+
+import javax.media.j3d.Geometry;
+import javax.media.j3d.IndexedGeometryArray;
+import javax.media.j3d.IndexedTriangleArray;
+import javax.media.j3d.IndexedTriangleStripArray;
+import javax.media.j3d.Shape3D;
+import javax.media.j3d.Transform3D;
+
+import com.sun.j3d.utils.geometry.GeometryInfo;
+import com.sun.j3d.utils.geometry.Stripifier;
+
+public class GeometryCollector extends ObjectVisitor{
+ private int totalVertexCount = 0;
+ private int totalIndexCount = 0;
+ private ArrayList geometryList = new ArrayList(); // �t�̂Ƃ��AGeometry��ۑ�
+ IndexedGeometryArray geometry = null;
+// private Stack transforms = new Stack();
+
+ int i=0;
+ int j=0;
+
+ //�R���X�g���N�^
+// public GeometryCollector() {
+// Transform3D t = new Transform3D();
+// transforms.push(t);
+// }
+
+ @Override
+ public void preVisit(Object3D obj) {
+ // TODO Auto-generated method stub
+ if(obj.hasChildren()){
+// System.out.println("pre"+i);
+// i++;
+ }else{
+// System.out.println("pre"+i+" Leaf");
+// i++;
+ Geometry g = ((Shape3D)obj.getBody().getPrimitiveNode()).getGeometry();
+ geometryList.add(g);
+ totalVertexCount += ((IndexedGeometryArray)g).getVertexCount();
+ totalIndexCount += ((IndexedGeometryArray)g).getIndexCount();
+ }
+
+
+ }
+
+ @Override
+ public void postVisit(Object3D obj) {
+ // TODO Auto-generated method stub
+ if(obj.hasChildren()){
+// System.out.println("post"+j);
+ j++;
+ }else{
+// System.out.println("post"+j+" Leaf");
+ j++;
+ }
+ }
+
+ public Geometry getGeometry(){
+ if (geometry == null) {
+ // ���X�g���̕����� Geometry ��1�ɂ܂Ƃ߂�
+ int coordinateOfs = 0;
+ int indexOfs = 0;
+ double coodinates[] = new double[totalVertexCount * 3];
+ int indicies[] = new int[totalIndexCount];
+ for (int n = 0; n < geometryList.size(); n++) {
+ IndexedGeometryArray geometry = (IndexedGeometryArray)geometryList.get(n);
+ double tmpCoordinates[] = new double[geometry.getVertexCount() * 3];
+ geometry.getCoordinates(0, tmpCoordinates);
+ System.arraycopy(tmpCoordinates, 0, coodinates, coordinateOfs * 3, geometry.getVertexCount() * 3);
+ int tmpIndicies[] = new int[geometry.getIndexCount()];
+ geometry.getCoordinateIndices(0, tmpIndicies);
+ for (int m = 0; m < geometry.getIndexCount(); m++) {
+ tmpIndicies[m] += coordinateOfs;
+ }
+ System.arraycopy(tmpIndicies, 0, indicies, indexOfs, geometry.getIndexCount());
+ coordinateOfs += geometry.getVertexCount();
+ indexOfs += geometry.getIndexCount();
+ }
+ geometry = new IndexedTriangleArray(totalVertexCount, IndexedTriangleArray.COORDINATES, totalIndexCount);
+ geometry.setCoordinates(0, coodinates);
+ geometry.setCoordinateIndices(0, indicies);
+
+ // �d�����Ă��钸�_��1�ɂ܂Ƃ߂�
+ GeometryUtility.compressGeometry(geometry);
+
+// // IndexedTriangleStripArray�@�ɕϊ��i�d�����Ă��钸�_��1�ɂ܂Ƃ߂邽�߁j
+// GeometryInfo gi = new GeometryInfo(geometry);
+// Stripifier sf = new Stripifier();
+// sf.stripify(gi);
+// geometry = gi.getIndexedGeometryArray(); // IndexedTriangleStripArray ���Ԃ����
+//
+// // IndexedTriangleArray �ɕϊ��iGeometryGraph �� IndexedTriangleStripArray �ɖ��Ή��̂��߁j
+// if (geometry instanceof IndexedTriangleStripArray) {
+// int numStrips = ((IndexedTriangleStripArray)geometry).getNumStrips();
+// int indexCounts[] = new int[numStrips];
+// ((IndexedTriangleStripArray)geometry).getStripIndexCounts(indexCounts);
+// int dstIndicies[] = new int[(((IndexedTriangleStripArray)geometry).getIndexCount() - numStrips * 2) * 3];
+// int dstOfs = 0;
+// int srcOfs = 0;
+// for (int s = 0; s < numStrips; s++) {
+// for (int i = 2; i < indexCounts[s]; i += 2) {
+// dstIndicies[dstOfs] = ((IndexedTriangleStripArray)geometry).getCoordinateIndex(srcOfs + i - 2);
+// dstIndicies[dstOfs + 1] = ((IndexedTriangleStripArray)geometry).getCoordinateIndex(srcOfs + i - 1);
+// dstIndicies[dstOfs + 2] = ((IndexedTriangleStripArray)geometry).getCoordinateIndex(srcOfs + i);
+// dstOfs += 3;
+// if (i + 1 < indexCounts[s]) {
+// dstIndicies[dstOfs] = ((IndexedTriangleStripArray)geometry).getCoordinateIndex(srcOfs + i);
+// dstIndicies[dstOfs + 1] = ((IndexedTriangleStripArray)geometry).getCoordinateIndex(srcOfs + i - 1);
+// dstIndicies[dstOfs + 2] = ((IndexedTriangleStripArray)geometry).getCoordinateIndex(srcOfs + i + 1);
+// dstOfs += 3;
+// }
+// }
+// srcOfs += indexCounts[s];
+// }
+//
+// int vertexCount = ((IndexedTriangleStripArray)geometry).getVertexCount();
+// coodinates = new double[vertexCount * 3];
+// ((IndexedTriangleStripArray)geometry).getCoordinates(0, coodinates);
+//
+// geometry = new IndexedTriangleArray(vertexCount, IndexedTriangleArray.COORDINATES, dstIndicies.length);
+// geometry.setCoordinates(0, coodinates);
+// geometry.setCoordinateIndices(0, dstIndicies);
+// }
+ }
+ return geometry;
+ }
+}
diff --git a/src/main/java/framework/model3D/GeometryUtility.java b/src/main/java/framework/model3D/GeometryUtility.java
new file mode 100644
index 0000000..a00cd04
--- /dev/null
+++ b/src/main/java/framework/model3D/GeometryUtility.java
@@ -0,0 +1,292 @@
+package framework.model3D;
+
+import java.util.ArrayList;
+import java.util.Hashtable;
+
+import javax.media.j3d.IndexedGeometryArray;
+import javax.vecmath.AxisAngle4d;
+import javax.vecmath.Matrix3d;
+import javax.vecmath.Point3d;
+import javax.vecmath.Vector3d;
+import javax.vecmath.Vector4d;
+
+public class GeometryUtility {
+ public static final double TOLERANCE = 0.0000002;
+ public static final Vector3d X_AXIS = new Vector3d(1.0, 0.0, 0.0);
+ public static final Vector3d Y_AXIS = new Vector3d(0.0, 1.0, 0.0);
+ public static final Vector3d Z_AXIS = new Vector3d(0.0, 0.0, 1.0);
+
+ public static ProjectionResult projection3D(
+ ArrayList vertex3Dlist, Vector3d axis) {
+ double k = 0.0;
+ int i = 0;
+
+ ProjectionResult pr = new ProjectionResult();
+
+ axis.normalize();
+
+ for (i = 0; i < vertex3Dlist.size(); i++) {
+ Vector3d p = vertex3Dlist.get(i);
+ Vector3d p1 = new Vector3d();
+
+ k = p.dot(axis);
+ p1.scaleAdd(-k, axis, p);
+
+ if (i == 0 || k >= pr.max) {
+ pr.max = k;
+ } else if (i == 0 || k <= pr.min) {
+ pr.min = k;
+ }
+ pr.vertexList.add(p1);
+ }
+ return pr;
+ }
+
+ public static ProjectionResult projection2D(
+ ArrayList vertex2Dlist, Vector3d axis) {
+ int i = 0;
+ double k = 0.0;
+ // System.out.println("point3�F"+axis);
+ if (axis.x != 0 || axis.y != 0 || axis.z != 0) {
+ axis.normalize();
+ }
+ // System.out.println("point3_1�F"+axis);
+ ProjectionResult pr = new ProjectionResult();
+
+ for (i = 0; i < vertex2Dlist.size(); i++) {
+ Vector3d p = vertex2Dlist.get(i);
+
+ k = p.dot(axis);
+ // System.out.println("k�F"+k);
+ // System.out.println("point3�F"+axis);
+ if (i == 0 || k >= pr.max) {
+ pr.max = k;
+ } else if (i == 0 || k <= pr.min) {
+ pr.min = k;
+ }
+ }
+ return pr;
+ }
+
+ // �ȉ��A���_�̕\���̔��胁�\�b�h
+ public static boolean inside(Vector3d v, Vector4d plane) {
+ // System.out.println("vertex:" + v.x + "," + v.y + "," + v.z);
+ // System.out.println("plane:" + plane.x + "," + plane.y + "," + plane.z
+ // + "," + plane.w);
+ Vector3d pv = new Vector3d(plane.x, plane.y, plane.z);
+ // Vector3d nv = (Vector3d)pv.clone();
+ // nv.scaleAdd(plane.w / pv.lengthSquared(),v);
+ if (pv.dot(v) + plane.w <= TOLERANCE) {
+ // System.out.println("��������I�I"+nv.dot(pv));
+ pv = null;
+ return true;
+ }
+ // System.out.println("�O������I�I"+nv.dot(pv));
+ pv = null;
+ return false;
+ }
+
+ /**
+ * 3�_��ʂ镽�ʂ��쐬����i�������Av1, v2, v3�̓��e��������������̂Œ��Ӂj
+ *
+ * @param v1
+ * --- 1�_�ڂ̍��W
+ * @param v2
+ * --- 2�_�ڂ̍��W
+ * @param v3
+ * --- 3�_�ڂ̍��W
+ * @return�@v1, v2, v3��ʂ镽��
+ */
+ public static Vector4d createPlane(Vector3d v1, Vector3d v2, Vector3d v3) {
+ v2 = (Vector3d)v2.clone();
+ v3 = (Vector3d)v3.clone();
+ v2.sub(v1);
+ v3.sub(v1);
+ v2.cross(v2, v3);
+ if (v2.length() < TOLERANCE) return null;
+ v2.normalize();
+ return new Vector4d(v2.x, v2.y, v2.z, -v2.dot(v1));
+ }
+
+ /**
+ *
+ * ���ʂƒ����̌�_�����߂�
+ *
+ * @param plane
+ * ����
+ * @param v1
+ * ������̓_1
+ * @param v2
+ * ������̓_2
+ * @return ��_
+ */
+ public static Vector3d intersect(Vector4d plane, Vector3d v1, Vector3d v2) {
+ Vector3d n = new Vector3d(plane.x, plane.y, plane.z);
+ Vector3d v21 = (Vector3d) v2.clone();
+ v21.sub(v1);
+ double s = n.dot(v21);
+ if (Math.abs(s) < TOLERANCE) return null;
+ v21.scale((-plane.w - n.dot(v1)) / s);
+ v21.add(v1);
+ return v21;
+ }
+
+ /**
+ *
+ * �^����ꂽ�_�ɍł��߂�������̓_�����߂�
+ *
+ * @param src ����(����)�̎n�_
+ * @param dst ����(����)�̏I�_
+ * @param pos �Ώۂ̓_
+ * @return src��dst��ʂ钼�����pos�ɍł��߂��_
+ */
+ public static Vector3d nearest(Vector3d src, Vector3d dst, Vector3d pos) {
+ Vector3d dir = (Vector3d)dst.clone();
+ dir.sub(src);
+ dir.normalize();
+ Vector3d p = (Vector3d)pos.clone();
+ p.sub(src);
+ dir.scale(p.dot(dir));
+ dir.add(src);
+ return dir;
+ }
+
+ /**
+ *
+ * �w�肳�ꂽ�_���ʃ|���S���̓����ɕ�܂���Ă��邩�H
+ *
+ * @param vertexList
+ * �ʃ|���S���̒��_��
+ * @param point
+ * �w��_
+ * @return true --- ��܂���Ă���, false --- ��܂���Ă��Ȃ�
+ */
+ public static boolean inside(ArrayList vertexList, Vector3d point, Vector3d normal) {
+ boolean inside = true;
+ for (int i = 0; i < vertexList.size(); i++) {
+ // �|���S���̊e�ӂɑ��ďՓ˓_���E�����������H
+ Vector3d center = (Vector3d) point.clone();
+ Vector3d v2 = (Vector3d) (vertexList.get((i + 1)
+ % vertexList.size()).clone());
+ Vector3d v1 = (Vector3d) vertexList.get(i).clone();
+ center.sub(v1);
+ v2.sub(v1);
+ v1.cross(v2, center);
+ if (normal.dot(v1) < -GeometryUtility.TOLERANCE) {
+ inside = false;
+ break;
+ }
+ }
+ // ���ׂĉE���A�܂��͂��ׂč����������ꍇ�A�ʃ|���S���̓����Ɉʒu�����ƍl����
+ return inside;
+ }
+
+ // IndexedGeometryArray�̃C���f�b�N�X�̂����A�������W�������C���f�b�N�X��u��������
+ public static void compressGeometry(IndexedGeometryArray g) {
+ // �@Hashtable�����Ȃ���Arepresentation[]�����
+ Hashtable> h = new Hashtable>();
+ Point3d p = new Point3d();
+ Point3d p2 = new Point3d();
+ double hash;
+ ArrayList list;
+ int[] representation = new int[g.getVertexCount()];
+
+ for (int i = 0; i < g.getVertexCount(); i++) {
+ g.getCoordinate(i, p);
+
+ hash = p.getX() + p.getY() + p.getZ();
+
+ list = h.get(new Double(hash));
+
+ if (list == null) {// hash�ɑΉ�����v�f���Ȃ��ꍇ
+ // Hashtable�����
+ list = new ArrayList();
+ list.add(new Integer(i));
+ h.put(new Double(hash), list);
+ // representation[]�����
+ representation[i] = i;
+ } else {
+ boolean bFound = false;
+ for (int j = 0; j < list.size(); j++) {
+ g.getCoordinate(list.get(j).intValue(), p2);
+ if (p.getX() == p2.getX() && p.getY() == p2.getY()
+ && p.getZ() == p2.getZ()) {
+ representation[i] = list.get(j).intValue();
+ bFound = true;
+ break;
+ }
+ }
+ if (!bFound) {
+ list.add(new Integer(i));
+ // representation[]�����
+ representation[i] = i;
+ }
+ }
+ }
+
+ // �Aindex�̒u������
+ for (int i = 0; i < g.getIndexCount(); i++) {
+ int index = representation[g.getCoordinateIndex(i)];
+ g.setCoordinateIndex(i, index);
+
+ }
+
+ }
+
+ public static Matrix3d calcRotationForView(Vector3d viewLine) {
+ Vector3d v1 = (Vector3d)viewLine.clone();
+ v1.normalize();
+ Vector3d v2 = new Vector3d();
+ v2.cross(v1, Y_AXIS);
+ double angle2 = Math.atan2(-v2.z, v2.x);
+ double angle1 = Math.PI / 2.0 - Math.acos(v1.dot(Y_AXIS));
+ Matrix3d rot1 = new Matrix3d();
+ rot1.rotX(angle1);
+ Matrix3d rot2 = new Matrix3d();
+ rot2.rotY(angle2);
+ rot2.mul(rot1);
+ return rot2;
+ }
+
+ public static Quaternion3D calcQuaternionForView(Vector3d viewLine) {
+ Vector3d v1 = (Vector3d)viewLine.clone();
+ v1.normalize();
+ Vector3d v2 = new Vector3d();
+ v2.cross(v1, Y_AXIS);
+ double angle2 = Math.atan2(-v2.z, v2.x);
+ double angle1 = Math.PI / 2.0 - Math.acos(v1.dot(Y_AXIS));
+ Quaternion3D quat1 = new Quaternion3D(new AxisAngle4d(X_AXIS, angle1));
+ Quaternion3D quat2 = new Quaternion3D(new AxisAngle4d(Y_AXIS, angle2));
+
+ return quat1.mul(quat2);
+ }
+
+ public static Quaternion3D calcQuaternionFromSrcToDst(Vector3d src, Vector3d dst) {
+ Vector3d v1 = new Vector3d();
+ Vector3d v2 = new Vector3d();
+ v1.cross(src, Y_AXIS);
+ v2.cross(dst, Y_AXIS);
+ Quaternion3D quat1;
+ Quaternion3D quat2;
+ double angle2 = Math.acos(Y_AXIS.dot(src) / src.length()) - Math.acos(Y_AXIS.dot(dst) / dst.length());
+ if (Math.abs(v2.length()) < TOLERANCE) {
+ v1.normalize();
+ quat1 = new Quaternion3D();
+ quat2 = new Quaternion3D(new AxisAngle4d(v1, angle2));
+ } else {
+ if (Math.abs(v1.length()) < TOLERANCE) {
+ quat1 = new Quaternion3D();
+ } else {
+ v1.normalize();
+ v2.normalize();
+ double cos1 = v1.dot(v2);
+ v1.cross(v1, v2);
+ double sin1 = v1.dot(Y_AXIS);
+ double angle1 = Math.atan2(sin1, cos1);
+ quat1 = new Quaternion3D(new AxisAngle4d(Y_AXIS, angle1));
+ }
+ quat2 = new Quaternion3D(new AxisAngle4d(v2, angle2));
+ }
+ return quat1.mul(quat2);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/framework/model3D/IViewer3D.java b/src/main/java/framework/model3D/IViewer3D.java
new file mode 100644
index 0000000..fa6b1f0
--- /dev/null
+++ b/src/main/java/framework/model3D/IViewer3D.java
@@ -0,0 +1,16 @@
+package framework.model3D;
+
+import java.util.ArrayList;
+
+import javax.media.j3d.GraphicsContext3D;
+import javax.media.j3d.Light;
+import javax.media.j3d.Transform3D;
+
+
+
+public interface IViewer3D {
+ public abstract void update(ArrayList lights, BackgroundBox skyBox);
+ public abstract void setGraphicsContext3D(GraphicsContext3D graphicsContext3D);
+ public abstract void setModelTransform(Transform3D t);
+ public abstract void draw(BaseObject3D obj);
+}
diff --git a/src/main/java/framework/model3D/LeafModel.java b/src/main/java/framework/model3D/LeafModel.java
new file mode 100644
index 0000000..c5d3a72
--- /dev/null
+++ b/src/main/java/framework/model3D/LeafModel.java
@@ -0,0 +1,31 @@
+package framework.model3D;
+import javax.media.j3d.Appearance;
+import javax.media.j3d.Geometry;
+
+
+public class LeafModel extends Model3D{
+
+ private Geometry g;
+ private Appearance a;
+
+ public LeafModel(String name,Geometry g,Appearance a){
+ this.name = name;
+ this.g = g;
+ this.a = a;
+ }
+
+ public Object3D createObject(){
+ Appearance a2 = (Appearance)a.cloneNodeComponent(true);
+ a2.setCapability(Appearance.ALLOW_TEXTURE_READ);
+ a2.setCapability(Appearance.ALLOW_TEXTURE_WRITE);
+ a2.setCapability(Appearance.ALLOW_TEXTURE_ATTRIBUTES_READ);
+ a2.setCapability(Appearance.ALLOW_TEXTURE_ATTRIBUTES_WRITE);
+ Object3D obj = new Object3D(name,g,a2);
+ return obj;
+ }
+
+ public Object3D createObjectSharingAppearance(){
+ Object3D obj = new Object3D(name,g,a);
+ return obj;
+ }
+}
diff --git a/src/main/java/framework/model3D/MapGenerator.java b/src/main/java/framework/model3D/MapGenerator.java
new file mode 100644
index 0000000..cd226ac
--- /dev/null
+++ b/src/main/java/framework/model3D/MapGenerator.java
@@ -0,0 +1,17 @@
+package framework.model3D;
+
+public abstract class MapGenerator {
+ private boolean bMapped = false;
+
+ public MapGenerator() {
+ super();
+ }
+
+ public void setMapped() {
+ bMapped = true;
+ }
+
+ public boolean hasMapped() {
+ return bMapped;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/framework/model3D/Model3D.java b/src/main/java/framework/model3D/Model3D.java
new file mode 100644
index 0000000..88dd9ff
--- /dev/null
+++ b/src/main/java/framework/model3D/Model3D.java
@@ -0,0 +1,9 @@
+package framework.model3D;
+
+
+
+public abstract class Model3D {
+ String name;
+ public abstract Object3D createObject();
+ public abstract Object3D createObjectSharingAppearance();
+}
diff --git a/src/main/java/framework/model3D/ModelFactory.java b/src/main/java/framework/model3D/ModelFactory.java
new file mode 100644
index 0000000..b28607d
--- /dev/null
+++ b/src/main/java/framework/model3D/ModelFactory.java
@@ -0,0 +1,1036 @@
+package framework.model3D;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import javax.media.j3d.Appearance;
+import javax.media.j3d.Canvas3D;
+import javax.media.j3d.GeometryArray;
+import javax.media.j3d.IndexedGeometryArray;
+import javax.media.j3d.IndexedTriangleArray;
+import javax.media.j3d.Material;
+import javax.media.j3d.TextureAttributes;
+import javax.media.j3d.Transform3D;
+import javax.media.j3d.TransparencyAttributes;
+import javax.media.j3d.TriangleArray;
+import javax.media.j3d.View;
+import javax.vecmath.Vector2f;
+import javax.vecmath.Vector3f;
+
+import com.sun.j3d.utils.geometry.GeometryInfo;
+import com.sun.j3d.utils.geometry.NormalGenerator;
+import com.sun.j3d.utils.image.TextureLoader;
+import com.sun.j3d.utils.universe.SimpleUniverse;
+
+import cv97.SceneGraph;
+import cv97.j3d.IndexedFaceSetNodeObject;
+import cv97.j3d.SceneGraphJ3dObject;
+import cv97.j3d.TransformNodeObject;
+import cv97.node.AppearanceNode;
+import cv97.node.IndexedFaceSetNode;
+import cv97.node.Node;
+import cv97.node.ShapeNode;
+import cv97.node.TransformNode;
+import cv97.util.LinkedListNode;
+import framework.schedule.ScheduleManager;
+import framework.schedule.TaskController;
+
+/**
+ * 3�������f�������邽�߂̃N���X
+ * @author �V�c����
+ *
+ */
+public class ModelFactory {
+ private static Canvas3D canvas = new Canvas3D(SimpleUniverse.getPreferredConfiguration());
+ public static final String STL_FILE_EXTENSION = ".stl";
+ public static final String OBJ_FILE_EXTENSION = ".obj";
+
+ /**
+ * 3�������f�����K�w�\���Ɗe���̖��̂ƂƂ��Ƀt�@�C������ǂݍ���
+ * @param fileName �t�@�C����
+ * @return
+ */
+ public static Model3D loadModel(String fileName){
+ return loadModel(fileName, false, false);
+ }
+
+ /**
+ * 3�������f�����K�w�\���Ɗe���̖��̂ƂƂ��Ƀt�@�C������ǂݍ��ށi�����e�N�X�`���̗L���̎w��t���j
+ * @param fileName �t�@�C����
+ * @param bTransparent �����e�N�X�`�������邩�ۂ�
+ * @param bCalcNormal TODO
+ * @return
+ */
+ public static Model3D loadModel(String fileName, boolean bTransparent, boolean bCalcNormal){
+// System.out.println(fileName);
+ if (fileName.toLowerCase().endsWith(STL_FILE_EXTENSION)) {
+ // STL�t�@�C���ǂݍ���
+ try {
+ return loadStlFile(fileName, null, bCalcNormal);
+ } catch (IOException | ModelFileFormatException e) {
+ e.printStackTrace();
+ }
+ } else if (fileName.toLowerCase().endsWith(OBJ_FILE_EXTENSION)) {
+ // OBJ�t�@�C���ǂݍ���
+ try {
+ return loadObjFile(fileName, bCalcNormal);
+ } catch (IOException | ModelFileFormatException e) {
+ e.printStackTrace();
+ }
+ }
+
+ SceneGraph sg = new SceneGraph(SceneGraph.NORMAL_GENERATION);
+
+ // �t�@�C���ǂݍ��ݎ��Ƀ����_�����O���s����̂ŁA�I�t�X�N���[�������_�����O���֎~����
+ TaskController renderingController = ScheduleManager.getInstance().getController("rendering");
+ renderingController.waitForActivation();
+ renderingController.activate();
+
+ // �t�@�C���ǂݍ���
+ View view = canvas.getView();
+ if (view != null) view.removeCanvas3D(canvas);
+ SceneGraphJ3dObject sgObject = new SceneGraphJ3dObject(canvas, sg);
+ sg.setObject(sgObject);
+ sg.load(fileName);
+
+ // �I�t�X�N���[�������_�����O�̋���
+ renderingController.deactivate();
+
+ // Model3D�ւ̕ϊ�
+ Model3D model= loadModel(sg, bTransparent, bCalcNormal);
+
+ return model;
+ }
+
+ private static Model3D loadModel(LinkedListNode node, boolean bTransparent, boolean bCalcNormal){
+// System.out.println(node.getClass());
+
+ if( ! (node instanceof ShapeNode) ){
+ Node childNodes;
+ String name = "";
+ if (node instanceof SceneGraph) {
+ childNodes = ((SceneGraph)node).getNodes();
+ } else {
+ childNodes = ((Node)node).getChildNodes();
+ name = ((Node)node).getName();
+ }
+ if(childNodes != null) {
+ ArrayList list = new ArrayList();
+ for(Node n = childNodes;n != null;n = n.next()){
+ Model3D model;
+ if((model = loadModel(n, bTransparent, bCalcNormal)) != null){
+ list.add(model);
+ }
+
+ //�Z��Ŗ������[�v�ɂȂ�Ȃ��悤�ɂ��鏈��
+ Node dummy = n;
+ dummy = dummy.next();
+ if(n == dummy){
+ break;
+ }
+ }
+
+ if(!list.isEmpty()){
+ Model3D modelList[] = new Model3D[list.size()];
+ for(int i = 0;i < list.size();i++){
+ modelList[i] = list.get(i);
+ }
+ if (node instanceof TransformNode) {
+ // �e�K�w�Œ�`����Ă���ϊ������ꏏ�ɕێ����Ă���
+ TransformNode transformNode = (TransformNode)node;
+ TransformNodeObject transformNodeObj = (TransformNodeObject)transformNode.getObject();
+ Transform3D transform = new Transform3D();
+ transformNodeObj.getTransform(transform);
+ return new ContainerModel(name, modelList, transform);
+ }
+ return new ContainerModel(name, modelList);
+ }
+ }
+ return null;
+ } else{
+ //�W�I���g���f�[�^�Ȃ�t�m�[�h�ɂ�����Model3D�f�[�^������Č��ʂ�Ԃ�
+
+ String name = ((Node)node).getName();
+ ShapeNode sp = (ShapeNode)node;
+
+ //�W�I���g���f�[�^�̎擾
+ IndexedFaceSetNode indexfsNode = sp.getIndexedFaceSetNodes();
+
+ if(indexfsNode ==null){
+ return null;
+ }
+ IndexedFaceSetNodeObject indexfsNodeObj = (IndexedFaceSetNodeObject)
+ indexfsNode.getObject();
+
+ IndexedGeometryArray newGeom;
+ if (bCalcNormal) {
+ GeometryInfo gInfo = new GeometryInfo(indexfsNodeObj);
+ NormalGenerator ng = new NormalGenerator();
+ ng.generateNormals(gInfo);
+ // Stripifier st = new Stripifier();
+ // st.stripify(gInfo);
+ newGeom = gInfo.getIndexedGeometryArray();
+ } else {
+ newGeom = indexfsNodeObj;
+ }
+
+ //�A�s�A�����X�f�[�^�̎擾
+ AppearanceNode appearNodes = (AppearanceNode)sp.getAppearanceNodes();
+
+ Appearance appearObj = null;
+ if(appearNodes != null){
+ appearObj = (Appearance)appearNodes.getObject();
+ appearObj = (Appearance)appearObj.cloneNodeComponent(true);
+ TextureAttributes ta = appearObj.getTextureAttributes();
+ if (ta == null) {
+ ta = new TextureAttributes();
+ }
+ ta.setTextureMode(TextureAttributes.MODULATE); // �V�F�[�f�B���O�ƃe�N�X�`������������
+ appearObj.setTextureAttributes(ta);
+ if (bTransparent) {
+ // �����e�N�X�`�����\���Ă���ꍇ
+ TransparencyAttributes tra = appearObj.getTransparencyAttributes();
+ if (tra == null) {
+ tra = new TransparencyAttributes();
+ }
+ tra.setTransparencyMode(TransparencyAttributes.FASTEST);
+ appearObj.setTransparencyAttributes(tra);
+ }
+// Texture tex = appearObj.getTexture();
+// if (tex != null) {
+// ImageComponent ic[] = tex.getImages();
+// for (int n = 0; n < ic.length; n++) {
+// boolean b = ic[n].isYUp();
+// ic[n].setYUp(!b);
+// }
+// tex.setImages(ic);
+// appearObj.setTexture(tex);
+// }
+ }
+
+ //���[�t���f���̍쐬
+ return new LeafModel(name,newGeom,appearObj);
+ }
+ }
+
+ /**
+ * STL�t�@�C��(�A�X�L�[�A�o�C�i��)�̓ǂݍ���
+ * @param res ���\�[�X
+ * @param fileName �t�@�C����
+ * @param ap 3D���f���ɓK�p����\�ʑ���
+ * @param bCalcNormal �@���̍Čv�Z���s����
+ * @return �ǂݍ���3D���f��
+ * @throws IOException
+ * @throws ModelFileFormatException
+ */
+ public static Model3D loadStlFile(String fileName, Appearance ap, boolean bCalcNormal) throws IOException, ModelFileFormatException {
+ // STL�t�@�C���ǂݍ���
+ FileInputStream in = new FileInputStream(fileName);
+ BufferedInputStream bis = new BufferedInputStream(in);
+ byte[] headerBin = new byte[80];
+ int n = bis.read(headerBin);
+ if (headerBin[0] == 's' &&
+ headerBin[1] == 'o' &&
+ headerBin[2] == 'l' &&
+ headerBin[3] == 'i' &&
+ headerBin[4] == 'd' &&
+ headerBin[5] == ' ') {
+ bis.close();
+
+ // STL�̓e�L�X�g�t�@�C��
+ File file = new File(fileName);
+ FileReader filereader = new FileReader(file);
+ BufferedReader br = new BufferedReader(filereader);
+ Model3D model = loadStlAsciiFile(br, ap, bCalcNormal);
+ br.close();
+ return model;
+ } else if (n == 80) {
+ // STL�̓o�C�i���t�@�C��
+ Model3D model = loadStlBinaryFile(bis, headerBin, ap, bCalcNormal);
+ bis.close();
+ return model;
+ }
+ return null;
+ }
+
+ private static Model3D loadStlAsciiFile(BufferedReader br, Appearance ap, boolean bCalcNormal) throws IOException, ModelFileFormatException {
+ // �w�b�_�ǂݍ���
+ String header = br.readLine();
+ if (header == null) {
+ br.close();
+ throw new ModelFileFormatException();
+ }
+ header.trim();
+ String headerContents[] = header.split(" ");
+ String name;
+ if (headerContents.length > 0 && headerContents[0].equals("solid")) {
+ if (headerContents.length > 1) name = headerContents[1];
+ else name = "";
+ } else {
+ System.out.println("STL file's header error!!");
+ br.close();
+ throw new ModelFileFormatException();
+ }
+
+ // Facet�ǂݍ���
+ ArrayList verticies = new ArrayList();
+ String line;
+ while ((line = br.readLine()) != null && !line.startsWith("endsolid ")) {
+ // facet normal ...
+ line.trim();
+ String[] data = line.split(" ");
+ if (data.length < 1 || !data[0].equals("facet")) {
+ System.out.println("Expected facet normal ...");
+ br.close();
+ throw new ModelFileFormatException();
+ }
+
+ // outer loop
+ line = br.readLine();
+ if (line == null) {
+ System.out.println("Expected outer loop");
+ br.close();
+ throw new ModelFileFormatException();
+ }
+ line.trim();
+ if (!line.equals("outer loop")) {
+ System.out.println("Expected outer loop");
+ br.close();
+ throw new ModelFileFormatException();
+ }
+
+ // vertex * 3
+ for (int i = 0; i < 3; i++) {
+ line = br.readLine();
+ if (line == null) {
+ System.out.println("Expected vertex x y z");
+ br.close();
+ throw new ModelFileFormatException();
+ }
+ line.trim();
+ data = line.split(" ");
+ if (data.length < 4 || !data[0].equals("vertex")) {
+ System.out.println("Expected vertex x y z");
+ br.close();
+ throw new ModelFileFormatException();
+ }
+ double[] vertex = new double[]{
+ Double.parseDouble(data[1]), // X���W
+ Double.parseDouble(data[2]), // Y���W
+ Double.parseDouble(data[3]) // Z���W
+ };
+ verticies.add(vertex); // Z���W
+ }
+
+ // endloop
+ line = br.readLine();
+ if (line == null) {
+ System.out.println("Expected endloop");
+ br.close();
+ throw new ModelFileFormatException();
+ }
+ line.trim();
+ if (!line.equals("endloop")) {
+ System.out.println("Expected endloop");
+ br.close();
+ throw new ModelFileFormatException();
+ }
+
+ // endfacet
+ line = br.readLine();
+ if (line == null) {
+ System.out.println("Expected endfacet");
+ br.close();
+ throw new ModelFileFormatException();
+ }
+ line.trim();
+ if (!line.equals("endfacet")) {
+ System.out.println("Expected endfacet");
+ br.close();
+ throw new ModelFileFormatException();
+ }
+ }
+
+ TriangleArray triArray = new TriangleArray(verticies.size(), TriangleArray.COORDINATES);
+ for (int n = 0; n < verticies.size(); n++) {
+ triArray.setCoordinate(n, verticies.get(n));
+ }
+ if (ap == null) ap = new Appearance();
+ return new LeafModel(name, triArray, ap);
+ }
+
+ private static Model3D loadStlBinaryFile(BufferedInputStream bis, byte[] header, Appearance ap, boolean bCalcNormal) throws IOException, ModelFileFormatException {
+ // Facet���ǂݍ���
+ Integer numTri = readInt(bis);
+ if (numTri == null) {
+ System.out.println("Expected vertex count");
+ bis.close();
+ throw new ModelFileFormatException();
+ }
+
+ // Facet�ǂݍ���
+ ArrayList verticies = new ArrayList();
+ ArrayList normals = new ArrayList();
+ Vector3f[] vertex = new Vector3f[] {
+ new Vector3f(),
+ new Vector3f(),
+ new Vector3f()
+ };
+
+ for (int n = 0; n < numTri; n++) {
+ Float nx = readFloat(bis); // �@��X����
+ if (nx == null) {
+ System.out.println("Expected normal");
+ bis.close();
+ throw new ModelFileFormatException();
+ }
+
+ Float ny = readFloat(bis); // �@��Y����
+ if (ny == null) {
+ System.out.println("Expected normal");
+ bis.close();
+ throw new ModelFileFormatException();
+ }
+
+ Float nz = readFloat(bis); // �@��Z����
+ if (nz == null) {
+ System.out.println("Expected normal");
+ bis.close();
+ throw new ModelFileFormatException();
+ }
+
+ for (int i = 0; i < 3; i++) {
+ Float x = readFloat(bis); // X���W
+ if (x == null) {
+ System.out.println("Expected vertex" + (i + 1));
+ bis.close();
+ throw new ModelFileFormatException();
+ }
+
+ Float y = readFloat(bis); // Y���W
+ if (y == null) {
+ System.out.println("Expected vertex" + (i + 1));
+ bis.close();
+ throw new ModelFileFormatException();
+ }
+
+ Float z = readFloat(bis); // Z���W
+ if (z == null) {
+ System.out.println("Expected vertex" + (i + 1));
+ bis.close();
+ throw new ModelFileFormatException();
+ }
+
+ verticies.add(new float[]{x, y, z});
+ vertex[i].x = x;
+ vertex[i].y = y;
+ vertex[i].z = z;
+ }
+ if (bCalcNormal) {
+ vertex[1].sub(vertex[0]);
+ vertex[2].sub(vertex[0]);
+ vertex[1].normalize();
+ vertex[2].normalize();
+ vertex[0].cross(vertex[1], vertex[2]);
+ nx = vertex[0].x;
+ ny = vertex[0].y;
+ nz = vertex[0].z;
+ }
+ normals.add(new float[]{nx, ny, nz});
+ normals.add(new float[]{nx, ny, nz});
+ normals.add(new float[]{nx, ny, nz});
+
+ byte[] optionBin = new byte[2];
+ if (bis.read(optionBin) < 2) {
+ System.out.println("Expected option");
+ bis.close();
+ throw new ModelFileFormatException();
+ }
+ }
+
+ TriangleArray triArray = new TriangleArray(verticies.size(), TriangleArray.COORDINATES | TriangleArray.NORMALS);
+ for (int n = 0; n < verticies.size(); n++) {
+ triArray.setCoordinate(n, verticies.get(n));
+ triArray.setNormal(n, normals.get(n));
+ }
+
+ if (ap == null) ap = new Appearance();
+ return new LeafModel(new String(header), triArray, ap);
+ }
+
+ /**
+ * OBJ�t�@�C���̓ǂݍ���
+ * @param res ���\�[�X
+ * @param fileName �t�@�C����
+ * @param bCalcNormal �@���̍Čv�Z���s����
+ * @return �ǂݍ���3D���f��
+ * @throws IOException
+ * @throws ModelFileFormatException
+ */
+ public static Model3D loadObjFile(String fileName, boolean bCalcNormal) throws IOException, ModelFileFormatException {
+ File file = new File(fileName);
+ FileReader filereader = new FileReader(file);
+ BufferedReader br = new BufferedReader(filereader);
+
+ HashMap appearances = new HashMap();
+ ArrayList objects = new ArrayList();
+ ArrayList groups = new ArrayList();
+ ArrayList subGroups = new ArrayList();
+ ArrayList objCoordinates = new ArrayList();
+ ArrayList objTexCoordinates = new ArrayList();
+ ArrayList objNormals = new ArrayList();
+ ArrayList> subGroupCoordinateIndicies = new ArrayList>();
+ ArrayList> subGroupTexCoordIndicies = new ArrayList>();
+ ArrayList> subGroupNormalIndicies = new ArrayList>();
+ String objectName = "";
+ String groupName = "";
+ String subGroupName = "";
+ Appearance subGroupAp = null;
+
+ String line = null;
+ while ((line = br.readLine()) != null) {
+ line.trim();
+ String data[] = line.split(" ");
+ if (data[0].equals("#")) {
+ // �R�����g
+ } else if (data[0].equals("mtllib")) {
+ // �ގ��t�@�C���̎w��
+ String dir = new File(fileName).getParent();
+ String mtlFileName = line.substring(line.indexOf(" ") + 1);
+ String mtlFilePath = new File(dir, mtlFileName).getPath();
+ appearances = loadMtlFile(mtlFilePath);
+ } else if (data[0].equals("o")) {
+ // �I�u�W�F�N�g�̊J�n
+ if (groups.size() > 0 || subGroups.size() > 0 || subGroupCoordinateIndicies.size() > 0) {
+ // �O�̃I�u�W�F�N�g�̃O���[�v�̎c��A�T�u�O���[�v�̎c��A�X�g���b�v�̎c���V�����I�u�W�F�N�g�Ƃ��Ēlj�
+ Model3D newObject = createRemainingObject(objectName, groups, groupName, objCoordinates,
+ objTexCoordinates, objNormals, subGroups, subGroupName, subGroupAp,
+ subGroupCoordinateIndicies, subGroupTexCoordIndicies, subGroupNormalIndicies);
+ objects.add(newObject);
+ groups.clear();
+ }
+
+ if (data.length < 1) {
+ System.out.println("Expected object's name");
+ throw new ModelFileFormatException();
+ }
+ objectName = data[1];
+ } else if (data[0].equals("g")) {
+ // �O���[�v�̊J�n
+ if (subGroups.size() > 0 || subGroupCoordinateIndicies.size() > 0) {
+ // �O�̃O���[�v�̃T�u�O���[�v�̎c��A�X�g���b�v�̎c���V�����O���[�v�Ƃ��Ēlj�
+ Model3D newGroup = createRemainingGroup(groupName, objCoordinates, objTexCoordinates, objNormals, subGroups,
+ subGroupName, subGroupAp, subGroupCoordinateIndicies, subGroupTexCoordIndicies, subGroupNormalIndicies);
+ groups.add(newGroup);
+ subGroups.clear();
+ }
+
+ if (data.length < 1) {
+ System.out.println("Expected group's name");
+ throw new ModelFileFormatException();
+ }
+ groupName = data[1];
+ } else if (data[0].equals("usemtl")) {
+ // �ގ��̎g�p(�T�u�O���[�v�̊J�n)
+ if (subGroupCoordinateIndicies.size() > 0) {
+ // �O�̃T�u�O���[�v�̃X�g���b�v�̎c���V�����T�u�O���[�v�Ƃ��Ēlj�
+ Model3D newSubGroup = createRemainingSubGroup(objCoordinates, objTexCoordinates, objNormals,
+ subGroupName, subGroupAp, subGroupCoordinateIndicies, subGroupTexCoordIndicies, subGroupNormalIndicies);
+ subGroups.add(newSubGroup);
+ subGroupCoordinateIndicies.clear();
+ subGroupTexCoordIndicies.clear();
+ subGroupNormalIndicies.clear();
+ }
+
+ if (data.length < 1) {
+ System.out.println("Expected mtl file's name");
+ throw new ModelFileFormatException();
+ }
+ subGroupAp = appearances.get(data[1]);
+ subGroupName = groupName + "_" + data[1] + subGroups.size(); // ���T�u�O���[�v�̖��O���d�����Ȃ��悤�ɂ��鏈��
+ } else if (data[0].equals("v")) {
+ // ���_���W�f�[�^
+ if (data.length < 4) {
+ System.out.println("Expected vertex coordinate");
+ throw new ModelFileFormatException();
+ }
+ float x = Float.parseFloat(data[1]);
+ float y = Float.parseFloat(data[2]);
+ float z = Float.parseFloat(data[3]);
+ Vector3f v = new Vector3f(x, y, z);
+ objCoordinates.add(v);
+ } else if (data[0].equals("vt")) {
+ // �e�N�X�`�����W�f�[�^
+ if (data.length < 3) {
+ System.out.println("Expected texture coordinate");
+ throw new ModelFileFormatException();
+ }
+ float x = Float.parseFloat(data[1]);
+ float y = Float.parseFloat(data[2]);
+ Vector2f v = new Vector2f(x, y);
+ objTexCoordinates.add(v);
+ } else if (data[0].equals("vn")) {
+ // �@���x�N�g���f�[�^
+ if (data.length < 4) {
+ System.out.println("Expected normal vector");
+ throw new ModelFileFormatException();
+ }
+ float x = Float.parseFloat(data[1]);
+ float y = Float.parseFloat(data[2]);
+ float z = Float.parseFloat(data[3]);
+ Vector3f v = new Vector3f(x, y, z);
+ objNormals.add(v);
+ } else if (data[0].equals("f")) {
+ // �|���S��(�X�g���b�v)�f�[�^
+ if (data.length < 4) {
+ System.out.println("At least 3 verticies are needed");
+ throw new ModelFileFormatException();
+ }
+ ArrayList coordinateIndicies = new ArrayList();
+ ArrayList texCoordIndicies = new ArrayList();
+ ArrayList normalIndicies = new ArrayList();
+ for (int n = 1; n < data.length; n++) {
+ String elements[] = data[n].split("/");
+ if (elements.length >= 1) {
+ // ���_���W�C���f�b�N�X
+ coordinateIndicies.add(Integer.parseInt(elements[0]) - 1);
+ if (elements.length >= 2) {
+ // �e�N�X�`�����W�C���f�b�N�X
+ if (elements[0].length() > 0) {
+ // "v//vn"�̏ꍇ�����邽��
+ texCoordIndicies.add(Integer.parseInt(elements[1]) - 1);
+ }
+ if (elements.length >= 3) {
+ // �@���x�N�g���C���f�b�N�X
+ normalIndicies.add(Integer.parseInt(elements[2]) - 1);
+ }
+ }
+ }
+ }
+ subGroupCoordinateIndicies.add(coordinateIndicies);
+ subGroupTexCoordIndicies.add(texCoordIndicies);
+ subGroupNormalIndicies.add(normalIndicies);
+ }
+ }
+
+ // �t�@�C���ǂݍ���̏���
+ if (groups.size() > 0 || subGroups.size() > 0 || subGroupCoordinateIndicies.size() > 0) {
+ // �X�g���b�v�̎c��A�T�u�O���[�v�̎c��A�O���[�v�̎c����Ō�̃I�u�W�F�N�g�Ƃ��Ēlj�
+ Model3D newObject = createRemainingObject(objectName, groups,
+ groupName, objCoordinates, objTexCoordinates, objNormals, subGroups,
+ subGroupName, subGroupAp, subGroupCoordinateIndicies, subGroupTexCoordIndicies, subGroupNormalIndicies);
+ objects.add(newObject);
+ }
+ br.close();
+
+ if (objects.size() == 0) {
+ System.out.println("No polygon is included");
+ throw new ModelFileFormatException();
+ } else if (objects.size() == 1) {
+ if (groups.size() == 0) {
+ System.out.println("No polygon is included");
+ throw new ModelFileFormatException();
+ } else if (groups.size() == 1) {
+ // �O���[�v��������̏ꍇ
+ return groups.get(0);
+ } else {
+ // �I�u�W�F�N�g��������̏ꍇ
+ return objects.get(0);
+ }
+ } else {
+ // �I�u�W�F�N�g�������̏ꍇ
+ return new ContainerModel(fileName, (Model3D [])objects.toArray(new Model3D []{}));
+ }
+ }
+
+ /**
+ * �O���[�v�̎c���V�����I�u�W�F�N�g�Ƃ��Ēlj�
+ * @param objectName �V�����I�u�W�F�N�g�̖��O
+ * @param groups�@�V�����I�u�W�F�N�g���\������O���[�v
+ * @param groupName
+ * @param groupCoordinates
+ * @param groupTexCoordinates
+ * @param groupNormals
+ * @param subGroups
+ * @param subGroupName
+ * @param subGroupAp
+ * @param subGroupCoordinateIndicies
+ * @param subGroupTexCoordIndicies
+ * @param subGroupNormalIndicies
+ * @return
+ */
+ private static Model3D createRemainingObject(String objectName, ArrayList groups,
+ String groupName, ArrayList groupCoordinates, ArrayList groupTexCoordinates,
+ ArrayList groupNormals, ArrayList subGroups,
+ String subGroupName, Appearance subGroupAp,
+ ArrayList> subGroupCoordinateIndicies,
+ ArrayList> subGroupTexCoordIndicies,
+ ArrayList> subGroupNormalIndicies) {
+ if (subGroups.size() > 0 || subGroupCoordinateIndicies.size() > 0) {
+ // �X�g���b�v�̎c��A�T�u�O���[�v�̎c���V�����O���[�v�Ƃ��Ēlj�
+ Model3D newGroup = createRemainingGroup(groupName, groupCoordinates, groupTexCoordinates, groupNormals, subGroups,
+ subGroupName, subGroupAp, subGroupCoordinateIndicies, subGroupTexCoordIndicies, subGroupNormalIndicies);
+ groups.add(newGroup);
+ subGroups.clear();
+ }
+
+ // �O���[�v�̎c���V�����I�u�W�F�N�g�Ƃ��č쐬
+ Model3D newObject = new ContainerModel(objectName, (Model3D [])groups.toArray(new Model3D []{}));
+ return newObject;
+ }
+
+ /**
+ * �T�u�O���[�v�̎c���V�����O���[�v�Ƃ��č쐬
+ * @param groupName�@�V�����O���[�v�̖��O
+ * @param groupCoordinates�@���_���W�̒l�̃��X�g
+ * @param groupTexCoordinates�@�e�N�X�`�����W�̒l�̃��X�g
+ * @param groupNormals�@�@���x�N�g���̒l�̃��X�g
+ * @param subGroups �V�����O���[�v���\������T�u�O���[�v
+ * @param subGroupName
+ * @param subGroupAp
+ * @param subGroupCoordinateIndicies
+ * @param subGroupTexCoordIndicies
+ * @param subGroupNormalIndicies
+ * @return
+ */
+ private static Model3D createRemainingGroup(String groupName,
+ ArrayList groupCoordinates, ArrayList groupTexCoordinates, ArrayList groupNormals,
+ ArrayList subGroups,
+ String subGroupName, Appearance subGroupAp,
+ ArrayList> subGroupCoordinateIndicies,
+ ArrayList> subGroupTexCoordIndicies,
+ ArrayList> subGroupNormalIndicies) {
+ if (subGroupCoordinateIndicies.size() > 0) {
+ // �X�g���b�v�̎c���V�����T�u�O���[�v�Ƃ��Ēlj�
+ Model3D newSubGroup = createRemainingSubGroup(groupCoordinates, groupTexCoordinates, groupNormals,
+ subGroupName, subGroupAp, subGroupCoordinateIndicies, subGroupTexCoordIndicies, subGroupNormalIndicies);
+ subGroups.add(newSubGroup);
+ subGroupCoordinateIndicies.clear();
+ subGroupTexCoordIndicies.clear();
+ subGroupNormalIndicies.clear();
+ }
+
+ // �T�u�O���[�v�̎c���V�����O���[�v�Ƃ��č쐬
+ return new ContainerModel(groupName, (Model3D [])subGroups.toArray(new Model3D []{}));
+ }
+
+ /**
+ * �X�g���b�v�̎c���V�����T�u�O���[�v�Ƃ��č쐬
+ * @param groupCoordinates
+ * @param groupTexCoordinates
+ * @param groupNormals
+ * @param subGroupName �V�����T�u�O���[�v�̖��O
+ * @param subGroupAp �V�����T�u�O���[�v�̕\�ʑ���
+ * @param subGroupCoordinateIndicies�@���_���W�ւ̃C���f�b�N�X
+ * @param subGroupTexCoordIndicies �e�N�X�`�����W�ւ̃C���f�b�N�X
+ * @param subGroupNormalIndicies�@�@���x�N�g���ւ̃C���f�b�N�X
+ * @return
+ */
+ private static Model3D createRemainingSubGroup(ArrayList groupCoordinates,
+ ArrayList groupTexCoordinates, ArrayList groupNormals,
+ String subGroupName, Appearance subGroupAp, ArrayList> subGroupCoordinateIndicies,
+ ArrayList> subGroupTexCoordIndicies,
+ ArrayList> subGroupNormalIndicies) {
+ // �X�g���b�v�̎c���V�����T�u�O���[�v�Ƃ��č쐬
+ // Geometry �̍쐬
+ GeometryArray geometry = createGeometryArray(groupCoordinates, groupTexCoordinates, groupNormals,
+ subGroupCoordinateIndicies, subGroupTexCoordIndicies, subGroupNormalIndicies);
+ // Object3D �̍쐬
+ return new LeafModel(subGroupName, geometry, subGroupAp);
+ }
+
+ /**
+ * �X�g���b�v�̃C���f�b�N�X���W�I���g���[���쐬
+ * @param groupCoordinates ���_���W�̒l�̃��X�g
+ * @param groupTexCoordinates �e�N�X�`�����W�̒l�̃��X�g
+ * @param groupNormals �@���x�N�g���̒l�̃��X�g
+ * @param subGroupCoordinateIndicies ���_���W�ւ̃C���f�b�N�X
+ * @param subGroupTexCoordIndicies �e�N�X�`�����W�ւ̃C���f�b�N�X
+ * @param subGroupNormalIndicies �@���x�N�g���ւ̃C���f�b�N�X
+ * @return �쐬�����W�I���g���[
+ */
+ private static GeometryArray createGeometryArray(
+ ArrayList groupCoordinates,
+ ArrayList groupTexCoordinates,
+ ArrayList groupNormals,
+ ArrayList> subGroupCoordinateIndicies,
+ ArrayList> subGroupTexCoordIndicies,
+ ArrayList> subGroupNormalIndicies) {
+ int vertexCount = 0;
+ int indexCount = 0;
+ for (int n = 0; n < subGroupCoordinateIndicies.size(); n++) {
+ ArrayList coordinateIndicies = subGroupCoordinateIndicies.get(n);
+ vertexCount += coordinateIndicies.size();
+ indexCount += (coordinateIndicies.size() - 2) * 3;
+ }
+ int vertexFormat = IndexedGeometryArray.COORDINATES;
+ if (subGroupTexCoordIndicies.size() > 0) {
+ vertexFormat |= IndexedGeometryArray.TEXTURE_COORDINATE_2;
+ }
+ if (subGroupNormalIndicies.size() > 0) {
+ vertexFormat |= IndexedGeometryArray.NORMALS;
+ }
+ IndexedGeometryArray geometry = new IndexedTriangleArray(vertexCount, vertexFormat, indexCount);
+ int vertexNum = 0;
+ int index = 0;
+ for (int n = 0; n < subGroupCoordinateIndicies.size(); n++) {
+ ArrayList coordinateIndicies = subGroupCoordinateIndicies.get(n);
+ ArrayList texCoordIndicies = subGroupTexCoordIndicies.get(n);
+ ArrayList normalIndicies = subGroupNormalIndicies.get(n);
+ Vector3f c = groupCoordinates.get(coordinateIndicies.get(0));
+ geometry.setCoordinate(vertexNum, new float[]{c.x, c.y, c.z});
+ c = groupCoordinates.get(coordinateIndicies.get(1));
+ geometry.setCoordinate(vertexNum + 1, new float[]{c.x, c.y, c.z});
+ if (texCoordIndicies.size() > 0) {
+ Vector2f t = groupTexCoordinates.get(texCoordIndicies.get(0));
+ geometry.setTextureCoordinate(vertexNum, new float[]{t.x, t.y});
+ t = groupTexCoordinates.get(texCoordIndicies.get(1));
+ geometry.setTextureCoordinate(vertexNum + 1, new float[]{t.x, t.y});
+ }
+ if (normalIndicies.size() > 0) {
+ Vector3f nr = groupNormals.get(normalIndicies.get(0));
+ geometry.setNormal(vertexNum, nr);
+ nr = groupNormals.get(normalIndicies.get(1));
+ geometry.setNormal(vertexNum + 1, nr);
+ }
+ int firstCount = vertexNum;
+ vertexNum += 2;
+ for (int i = 2; i < coordinateIndicies.size(); i++) {
+ c = groupCoordinates.get(coordinateIndicies.get(i));
+ geometry.setCoordinate(vertexNum, new float[]{c.x, c.y, c.z});
+ geometry.setCoordinateIndex(index, firstCount);
+ geometry.setCoordinateIndex(index + 1, vertexNum - 1);
+ geometry.setCoordinateIndex(index + 2, vertexNum);
+ if (texCoordIndicies.size() > 0) {
+ Vector2f t = groupTexCoordinates.get(texCoordIndicies.get(i));
+ geometry.setTextureCoordinate(vertexNum, new float[]{t.x, t.y});
+ geometry.setTextureCoordinateIndex(index, firstCount);
+ geometry.setTextureCoordinateIndex(index + 1, vertexNum - 1);
+ geometry.setTextureCoordinateIndex(index + 2, vertexNum);
+ }
+ if (normalIndicies.size() > 0) {
+ Vector3f nr = groupNormals.get(normalIndicies.get(i));
+ geometry.setNormal(vertexNum, nr);
+ geometry.setNormalIndex(index, firstCount);
+ geometry.setNormalIndex(index + 1, vertexNum - 1);
+ geometry.setNormalIndex(index + 2, vertexNum);
+ }
+ vertexNum += 1;
+ index += 3;
+ }
+ }
+ return geometry;
+// ArrayList coordinateIndiciesMap = new ArrayList();
+// ArrayList texCoordIndiciesMap = new ArrayList();
+// ArrayList normalIndiciesMap = new ArrayList();
+// int indexCount = 0;
+// int[] stripIndexCounts = new int[subGroupCoordinateIndicies.size()];
+// for (int n = 0; n < subGroupCoordinateIndicies.size(); n++) {
+// ArrayList coordinateIndicies = subGroupCoordinateIndicies.get(n);
+// ArrayList texCoordIndicies = subGroupTexCoordIndicies.get(n);
+// ArrayList normalIndicies = subGroupNormalIndicies.get(n);
+// indexCount += coordinateIndicies.size();
+// stripIndexCounts[n] = coordinateIndicies.size();
+// for (int i = 0; i < coordinateIndicies.size(); i++) {
+// int c = coordinateIndicies.get(i);
+// int coordinateIndex = coordinateIndiciesMap.indexOf(c);
+// if (coordinateIndex == -1) {
+// coordinateIndex = coordinateIndiciesMap.size();
+// coordinateIndiciesMap.add(c);
+// }
+// coordinateIndicies.set(i, coordinateIndex);
+// if (texCoordIndicies.size() > 0) {
+// int t = texCoordIndicies.get(i);
+// int texCoordIndex = texCoordIndiciesMap.indexOf(t);
+// if (texCoordIndex == -1) {
+// texCoordIndex = texCoordIndiciesMap.size();
+// texCoordIndiciesMap.add(t);
+// }
+// texCoordIndicies.set(i, texCoordIndex);
+// }
+// if (normalIndicies.size() > 0) {
+// int nr = normalIndicies.get(i);
+// int normalIndex = normalIndiciesMap.indexOf(nr);
+// if (normalIndex == -1) {
+// normalIndex = normalIndiciesMap.size();
+// normalIndiciesMap.add(nr);
+// }
+// normalIndicies.set(i, normalIndex);
+// }
+// }
+// }
+// int vertexCount = coordinateIndiciesMap.size();
+// int vertexFormat = IndexedGeometryArray.COORDINATES;
+// if (texCoordIndiciesMap.size() > 0) {
+// if (vertexCount < texCoordIndiciesMap.size()) vertexCount = texCoordIndiciesMap.size();
+// vertexFormat |= IndexedGeometryArray.TEXTURE_COORDINATE_2;
+// }
+// if (normalIndiciesMap.size() > 0) {
+// if (vertexCount < normalIndiciesMap.size()) vertexCount = normalIndiciesMap.size();
+// vertexFormat |= IndexedGeometryArray.NORMALS;
+// }
+// IndexedGeometryArray geometry = new IndexedTriangleFanArray(vertexCount, vertexFormat, indexCount, stripIndexCounts);
+// for (int n = 0; n < coordinateIndiciesMap.size(); n++) {
+// Vector3f c = groupCoordinates.get(coordinateIndiciesMap.get(n));
+// geometry.setCoordinate(n, new float[]{c.x, c.y, c.z});
+// }
+// for (int n = 0; n < texCoordIndiciesMap.size(); n++) {
+// Vector2f t = groupTexCoordinates.get(texCoordIndiciesMap.get(n));
+// geometry.setTextureCoordinate(n, new float[]{t.x, t.y});
+// }
+// for (int n = 0; n < normalIndiciesMap.size(); n++) {
+// Vector3f nr = groupNormals.get(normalIndiciesMap.get(n));
+// geometry.setNormal(n, nr);
+// }
+// int index = 0;
+// for (int n = 0; n < subGroupCoordinateIndicies.size(); n++) {
+// ArrayList coordinateIndicies = subGroupCoordinateIndicies.get(n);
+// ArrayList texCoordIndicies = subGroupTexCoordIndicies.get(n);
+// ArrayList normalIndicies = subGroupNormalIndicies.get(n);
+// for (int i = 0; i < coordinateIndicies.size(); i++) {
+// geometry.setCoordinateIndex(index, coordinateIndicies.get(i));
+// if (texCoordIndicies.size() > 0) {
+// geometry.setTextureCoordinateIndex(index, texCoordIndicies.get(i));
+// }
+// if (normalIndicies.size() > 0) {
+// geometry.setNormalIndex(index, normalIndicies.get(i));
+// }
+// index++;
+// }
+// }
+// return geometry;
+ }
+
+ /**
+ * MTL�t�@�C���̓ǂݍ���
+ * @param res ���\�[�X
+ * @param fileName �t�@�C����
+ * @return�@�ގ�������\�ʑ����I�u�W�F�N�g�ւ̃}�b�s���O
+ * @throws IOException
+ * @throws ModelFileFormatException
+ */
+ private static HashMap loadMtlFile(String fileName) throws IOException, ModelFileFormatException {
+ File file = new File(fileName);
+ FileReader filereader = new FileReader(file);
+ BufferedReader br = new BufferedReader(filereader);
+
+ HashMap appearances = new HashMap();
+ String materialName;
+ Appearance ap = null;
+ Material m = null;
+
+ String line = null;
+ while ((line = br.readLine()) != null) {
+ line.trim();
+ String data[] = line.split(" ");
+ if (data[0].equals("newmtl")) {
+ if (data.length < 1) {
+ System.out.println("Expected material's name");
+ throw new ModelFileFormatException();
+ }
+ materialName = data[1];
+ m = new Material();
+ ap = new Appearance();
+ ap.setMaterial(m);
+ appearances.put(materialName, ap);
+ } else if (data[0].equals("Kd")) {
+ if (data.length < 4) {
+ System.out.println("Expected diffuse color");
+ throw new ModelFileFormatException();
+ }
+ float r = Float.parseFloat(data[1]);
+ float g = Float.parseFloat(data[2]);
+ float b = Float.parseFloat(data[3]);
+ m.setDiffuseColor(r, g, b);
+ } else if (data[0].equals("Ka")) {
+ if (data.length < 4) {
+ System.out.println("Expected ambient color");
+ throw new ModelFileFormatException();
+ }
+ float r = Float.parseFloat(data[1]);
+ float g = Float.parseFloat(data[2]);
+ float b = Float.parseFloat(data[3]);
+ m.setAmbientColor(r, g, b);
+ } else if (data[0].equals("Ks")) {
+ if (data.length < 4) {
+ System.out.println("Expected specular color");
+ throw new ModelFileFormatException();
+ }
+ float r = Float.parseFloat(data[1]);
+ float g = Float.parseFloat(data[2]);
+ float b = Float.parseFloat(data[3]);
+ m.setSpecularColor(r, g, b);
+ } else if (data[0].equals("Tr")) {
+ if (data.length < 4) {
+ System.out.println("Expected emissive color");
+ throw new ModelFileFormatException();
+ }
+ float r = Float.parseFloat(data[1]);
+ float g = Float.parseFloat(data[2]);
+ float b = Float.parseFloat(data[3]);
+ m.setEmissiveColor(r, g, b);
+ } else if (data[0].equals("Ns")) {
+ if (data.length < 2) {
+ System.out.println("Expected shiness value");
+ throw new ModelFileFormatException();
+ }
+ float s = Float.parseFloat(data[1]);
+ m.setShininess(s);
+ } else if (data[0].equals("map_Kd")) {
+ if (data.length < 2) {
+ System.out.println("Expected texture file's name");
+ throw new ModelFileFormatException();
+ }
+ String dir = new File(fileName).getParent();
+ String texFileName = line.substring(line.indexOf(" ") + 1);
+ String texFilePath = new File(dir, texFileName).getPath();
+ TextureLoader texLoader = new TextureLoader(texFilePath, TextureLoader.BY_REFERENCE | TextureLoader.Y_UP, null);
+ ap.setTexture(texLoader.getTexture());
+ }
+ }
+ return appearances;
+ }
+
+ private static Integer readInt(BufferedInputStream bis) throws IOException {
+ byte[] intBin = new byte[4];
+ if (bis.read(intBin, 3, 1) < 1) {
+ return null;
+ }
+ if (bis.read(intBin, 2, 1) < 1) {
+ return null;
+ }
+ if (bis.read(intBin, 1, 1) < 1) {
+ return null;
+ }
+ if (bis.read(intBin, 0, 1) < 1) {
+ return null;
+ }
+ return ByteBuffer.wrap(intBin).getInt();
+ }
+
+ private static Float readFloat(BufferedInputStream bis) throws IOException {
+ byte[] floatBin = new byte[4];
+ if (bis.read(floatBin, 3, 1) < 1) {
+ return null;
+ }
+ if (bis.read(floatBin, 2, 1) < 1) {
+ return null;
+ }
+ if (bis.read(floatBin, 1, 1) < 1) {
+ return null;
+ }
+ if (bis.read(floatBin, 0, 1) < 1) {
+ return null;
+ }
+ return ByteBuffer.wrap(floatBin).getFloat();
+ }
+}
diff --git a/src/main/java/framework/model3D/ModelFileFormatException.java b/src/main/java/framework/model3D/ModelFileFormatException.java
new file mode 100644
index 0000000..d6b359b
--- /dev/null
+++ b/src/main/java/framework/model3D/ModelFileFormatException.java
@@ -0,0 +1,5 @@
+package framework.model3D;
+
+public class ModelFileFormatException extends Exception {
+
+}
diff --git a/src/main/java/framework/model3D/OBB.java b/src/main/java/framework/model3D/OBB.java
new file mode 100644
index 0000000..f8dd6af
--- /dev/null
+++ b/src/main/java/framework/model3D/OBB.java
@@ -0,0 +1,620 @@
+package framework.model3D;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+
+import javax.media.j3d.BoundingPolytope;
+import javax.media.j3d.BoundingSphere;
+import javax.media.j3d.Transform3D;
+import javax.vecmath.Matrix4d;
+import javax.vecmath.Point3d;
+import javax.vecmath.Vector3d;
+import javax.vecmath.Vector4d;
+
+public class OBB implements Cloneable {
+ private ArrayList vertexList = new ArrayList();
+ private Vector4d[] plane;
+ private BoundingPolytope bp = null;
+ private static int edges[][] = { { 0, 1 }, { 0, 2 }, { 1, 3 }, { 2, 3 },
+ { 0, 4 }, { 1, 5 }, { 3, 7 }, { 2, 6 },
+ { 4, 5 }, { 4, 6 }, { 5, 7 }, { 6, 7 } };
+ private static Integer planes[][] = { {0, 2, 3, 1}, {0, 1, 5, 4},
+ {1, 3, 7, 5}, {4, 5, 7, 6},
+ {0, 4, 6, 2}, {2, 6, 7, 3}};
+ private static boolean[][] inside = new boolean[8][6];
+
+ public OBB() {
+ }
+
+ public OBB(Vector3d v1, Vector3d v2, Vector3d v3, Vector3d v4,
+ Vector3d v5, Vector3d v6, Vector3d v7, Vector3d v8) {
+ vertexList.add(v1);
+ vertexList.add(v2);
+ vertexList.add(v3);
+ vertexList.add(v4);
+ vertexList.add(v5);
+ vertexList.add(v6);
+ vertexList.add(v7);
+ vertexList.add(v8);
+ createPlanes();
+ }
+
+ public void addVertex(Vector3d v) {
+ vertexList.add(v);
+ }
+
+ public Vector3d getVertex(int i) {
+ return vertexList.get(i);
+ }
+
+ public BoundingPolytope getBoundingPolytope() {
+ return bp;
+ }
+
+ public BoundingSphere getBoundingSphere() {
+ double radius = 0.0;
+ Point3d p = new Point3d();
+ Vector3d cv = new Vector3d();
+ for (int i = 0; i < vertexList.size() - 1; i++) {
+ for (int j = i + 1; j < vertexList.size(); j++) {
+ Vector3d v = new Vector3d();
+ v.sub(vertexList.get(i), vertexList.get(j));
+ if (radius < v.length()) {
+ radius = v.length();
+ cv.add(vertexList.get(i), vertexList.get(j));
+ cv.scale(0.5);
+ p.x = cv.x;
+ p.y = cv.y;
+ p.z = cv.z;
+ }
+ }
+ }
+ BoundingSphere s = new BoundingSphere(p, radius / 2);
+ return s;
+ }
+
+ /**
+ * ���_�������ɖʂ���ы��E���ʑ̂�����
+ */
+ public void createPlanes() {
+ // �ʂ̍쐬
+ Vector3d v1 = new Vector3d();
+ Vector3d v2 = new Vector3d();
+ Vector3d v3 = new Vector3d();
+ Vector4d[] plane = new Vector4d[6];
+
+ // 0231
+ v1 = getVertex(0);
+ v2.sub(getVertex(2), getVertex(0));
+ v3.sub(getVertex(1), getVertex(0));
+ Vector3d n = new Vector3d();
+ n.cross(v2, v3);
+ n.normalize();
+ plane[0] = new Vector4d();
+ plane[0].set(n.x, n.y, n.z, -n.dot(v1));
+
+
+ // 0154
+ v1 = getVertex(0);
+ v2.sub(getVertex(1), getVertex(0));
+ v3.sub(getVertex(4), getVertex(0));
+ n = new Vector3d();
+ n.cross(v2, v3);
+ n.normalize();
+ plane[1] = new Vector4d();
+ plane[1].set(n.x, n.y, n.z, -n.dot(v1));
+
+ // 1375
+ v1 = getVertex(1);
+ v2.sub(getVertex(3), getVertex(1));
+ v3.sub(getVertex(5), getVertex(1));
+ n = new Vector3d();
+ n.cross(v2, v3);
+ n.normalize();
+ plane[2] = new Vector4d();
+ plane[2].set(n.x, n.y, n.z, -n.dot(v1));
+
+ // 4576
+ v1 = getVertex(6);
+ v2.sub(getVertex(4), getVertex(6));
+ v3.sub(getVertex(7), getVertex(6));
+ n = new Vector3d();
+ n.cross(v2, v3);
+ n.normalize();
+ plane[3] = new Vector4d();
+ plane[3].set(n.x, n.y, n.z, -n.dot(v1));
+
+ // 0462
+ v1 = getVertex(6);
+ v2.sub(getVertex(2), getVertex(6));
+ v3.sub(getVertex(4), getVertex(6));
+ n = new Vector3d();
+ n.cross(v2, v3);
+ n.normalize();
+ plane[4] = new Vector4d();
+ plane[4].set(n.x, n.y, n.z, -n.dot(v1));
+
+ // 2673
+ v1 = getVertex(6);
+ v2.sub(getVertex(7), getVertex(6));
+ v3.sub(getVertex(2), getVertex(6));
+ n = new Vector3d();
+ n.cross(v2, v3);
+ n.normalize();
+ plane[5] = new Vector4d();
+ plane[5].set(n.x, n.y, n.z, -n.dot(v1));
+
+ this.plane = plane;
+
+ bp = new BoundingPolytope();
+ bp.setPlanes(plane);
+ }
+
+ /**
+ * ���ʂƂ̏Փ˔���
+ * @param plane �Փ˔���̑ΏۂƂȂ镽��
+ * @return �Փ˔���̌��ʁi�Փ˂��Ă��Ȃ��ꍇ��null�j
+ */
+ public CollisionResult intersect(Vector4d plane) {
+ int i = 0;
+ boolean inside = false;
+ boolean outside = false;
+ int count = 0;
+ Vector3d center = new Vector3d(0, 0, 0);
+ ArrayList collisionPoints = new ArrayList();
+ double l = Math.sqrt(plane.x * plane.x + plane.y * plane.y + plane.z * plane.z);
+ double length;
+ double deepest = 0.0;
+ Vector3d v;
+ for (i = 0; i < vertexList.size(); i++) {
+ v = vertexList.get(i);
+ if (GeometryUtility.inside(v, plane)) {
+ inside = true;
+ length = -(v.x * plane.x + v.y * plane.y + v.z * plane.z + plane.w) / l;
+ if (length > deepest + GeometryUtility.TOLERANCE) {
+ center.set(v);
+ collisionPoints.clear();
+ collisionPoints.add(v);
+ count = 1;
+ deepest = length;
+ } else if (length >= deepest - GeometryUtility.TOLERANCE) {
+ center.add(v);
+ collisionPoints.add(v);
+ count++;
+ }
+ } else {
+ outside = true;
+ }
+ }
+
+ if (!inside || !outside) {
+ // �S���_���O�����S���_�������̏ꍇ
+ return null;
+ }
+
+ center.scale(1.0 / count);
+
+ CollisionResult cr = new CollisionResult();
+ cr.length = deepest;
+ cr.collisionPoint.setVector3d(center);
+ cr.collisionPoints = collisionPoints;
+ cr.normal.setX(plane.x / l);
+ cr.normal.setY(plane.y / l);
+ cr.normal.setZ(plane.z / l);
+
+ return cr;
+ }
+
+ /**
+ * OBB�Ƃ̏Փ˔���
+ * @param another �Փ˔���̑ΏۂƂȂ�OBB
+ * @return �Փ˔���̌��ʁi�Փ˂��Ă��Ȃ��ꍇ��null�j
+ */
+ public CollisionResult intersect(OBB another) {
+ // another�̊e���_��this�̊e�ʂ̓����ɂ��邩�ׂ�
+ // i�Fanother�̒��_, j�Fthis�̖�
+ OBB o1 = this;
+ OBB o2 = another;
+ for (int i = 0; i < o2.vertexList.size(); i++) {
+ for (int j = 0; j < o1.plane.length; j++) {
+ inside[i][j] = GeometryUtility.inside(o2.vertexList.get(i), o1.plane[j]);
+ }
+ }
+
+ int v = 0;
+ boolean bCollides = false;
+
+ // another�̊e���_��this�ɕ�܂���Ă��邩�H
+ Vector3d contactCenter = new Vector3d();
+ int count = 0;
+ for (int i = 0; i < o2.vertexList.size(); i++) {
+ boolean f1 = false;
+ for (int p = 0; p < o1.plane.length; p++) {
+ f1 = inside[i][p];
+ if (!f1) break; // ��܂���Ă��Ȃ�
+ }
+ if (f1) {
+ // this�̂��ׂĂ̖ʂ̓��� �� this�ɕ�܂���Ă���
+ if (!bCollides) {
+ bCollides = true;
+ v = i;
+ }
+ contactCenter.add(o2.vertexList.get(i));
+ count++;
+ }
+ }
+ if (!bCollides) {
+ // this�̊e���_��another�̊e�ʂ̓����ɂ��邩�ׂ�
+ o1 = another;
+ o2 = this;
+ for (int i = 0; i < o2.vertexList.size(); i++) {
+ for (int j = 0; j < o1.plane.length; j++) {
+ inside[i][j] = GeometryUtility.inside(o2.vertexList.get(i), o1.plane[j]);
+ }
+ }
+ // this�̊e���_��another�ɕ�܂���Ă��邩�H
+ for (int i = 0; i < o2.vertexList.size(); i++) {
+ boolean f1 = false;
+ for (int p = 0; p < o1.plane.length; p++) {
+ f1 = inside[i][p];
+ if (!f1) break; // ��܂���Ă��Ȃ�
+ }
+ if (f1) {
+ // another�̂��ׂĂ̖ʂ̓��� �� another�ɕ�܂���Ă���
+ if (!bCollides) {
+ bCollides = true;
+ v = i;
+ }
+ contactCenter.add(o2.vertexList.get(i));
+ count++;
+ }
+ }
+ }
+
+ CollisionResult cr = new CollisionResult();
+ ArrayList collisionPoints = new ArrayList();
+ if (bCollides) {
+ // �����ꂩ��OBB�̒��_v��������OBB�ɕ�܂���Ă����ꍇ(v��������OBB��o2�A������o1�Ƃ���)
+ // o1�̂ǂ̖ʂƏՓ˂������肷��
+ double lMin = 0;
+ int p1 = -1;
+ Vector3d normal = null;
+ contactCenter.scale(1.0 / (double)count);
+ for (int p = 0; p < o1.plane.length; p++) {
+ Vector3d n = new Vector3d(o1.plane[p].x, o1.plane[p].y, o1.plane[p].z);
+ double l = -(contactCenter.x * o1.plane[p].x + contactCenter.y * o1.plane[p].y +
+ contactCenter.z * o1.plane[p].z + o1.plane[p].w) / n.length();
+ if (lMin > l || normal == null) {
+ lMin = l;
+ p1 = p;
+ normal = n;
+ }
+ }
+
+ // o2���v���܂ޕӂ̂����Փ˖ʂ̖@���Ƌt�����Ɍ������Ă���ӂ�T��(���̂悤�ȕӂ̐��ɂ���ĐڐG���ς��)
+ Vector3d collisionPoint = o2.vertexList.get(v);
+ Vector3d d1;
+ ArrayList contactEdges = new ArrayList();
+ for (int e = 0; e < edges.length; e++) {
+ if (v == edges[e][0]) {
+ d1 = new Vector3d(o2.vertexList.get(edges[e][1]));
+ d1.sub(collisionPoint);
+ if (normal.dot(d1) < GeometryUtility.TOLERANCE) {
+ // �Փ˖ʂɐڂ��Ă����
+ contactEdges.add(edges[e][1]); // v�̔��Α��̒[�_
+ }
+ } else if (v == edges[e][1]) {
+ d1 = new Vector3d(o2.vertexList.get(edges[e][0]));
+ d1.sub(collisionPoint);
+ if (normal.dot(d1) < GeometryUtility.TOLERANCE) {
+ // �Փ˖ʂɐڂ��Ă����
+ contactEdges.add(edges[e][0]); // v�̔��Α��̒[�_
+ }
+ }
+ }
+
+ // �ڐG�ɉ���������
+ if (contactEdges.size() == 0) {
+ // a) ���_�ŐڐG
+ collisionPoints.add(collisionPoint);
+ cr.collisionPoint.setVector3d(collisionPoint);
+ } else if (contactEdges.size() == 1) {
+ // b) �ӂŐڐG
+ boolean f1 = true;
+ Vector3d otherPoint = o2.vertexList.get(contactEdges.get(0));
+ Vector3d intersectionPoint = null;
+ double nearest = 0.0;
+ for (int p = 0; p < o1.plane.length; p++) {
+ if (!inside[contactEdges.get(0)][p]) {
+ // collisionPoint �Ɓ@otherPoint �̊Ԃ�ʂ镽��
+ Vector3d ip = GeometryUtility.intersect(o1.plane[p], collisionPoint, otherPoint);
+ if (ip != null) {
+ f1 = false; // ��܂���Ă��Ȃ�
+ Vector3d ip2 = (Vector3d)ip.clone();
+ ip2.sub(collisionPoint);
+ double d = ip2.length();
+ if (intersectionPoint == null || d < nearest) {
+ intersectionPoint = ip;
+ nearest = d;
+ }
+ }
+ }
+ }
+ if (f1) {
+ // b-1) �ӑS�̂��ڐG���Ă���
+ collisionPoints.add(collisionPoint);
+ collisionPoints.add(otherPoint);
+ Vector3d center = new Vector3d(collisionPoint);
+ center.add(otherPoint);
+ center.scale(0.5);
+ cr.collisionPoint.setVector3d(center);
+ } else {
+ // b-2) �ӂ̈ꕔ���ڐG���Ă���
+ collisionPoints.add(collisionPoint);
+ collisionPoints.add(intersectionPoint);
+ Vector3d center = new Vector3d(collisionPoint);
+ center.add(intersectionPoint);
+ center.scale(0.5);
+ cr.collisionPoint.setVector3d(center);
+ }
+ } else {
+ // c) �ʂŐڐG
+ Vector3d center = new Vector3d();
+ int v2 = contactEdges.get(0);
+ int v3 = contactEdges.get(1);
+ int p2;
+ for (p2 = 0; p2 < o2.plane.length; p2++) {
+ if (v == planes[p2][0] || v == planes[p2][1] || v == planes[p2][2] || v == planes[p2][3]) {
+ if (v2 == planes[p2][0] || v2 == planes[p2][1] || v2 == planes[p2][2] || v2 == planes[p2][3]) {
+ if (v3 == planes[p2][0] || v3 == planes[p2][1] || v3 == planes[p2][2] || v3 == planes[p2][3]) {
+ break;
+ }
+ }
+ }
+ }
+ // o1�̖�p1��o2�̖�p2���ڂ��Ă���
+ // �ʂƖʂ̋��ʗ̈�����߂�
+ for (v2 = 0; v2 < 4; v2++) {
+ if (planes[p2][v2] == v) break;
+ }
+ Vector3d d2 = (Vector3d)o2.vertexList.get(planes[p2][(v2 + 1) % 4]).clone();
+ d2.sub(collisionPoint);
+ d2.cross(normal, d2);
+ int sign = -1;
+ int v1;
+ for (v1 = 4; v1 >= 0; v1--) {
+ d1 = (Vector3d)o1.vertexList.get(planes[p1][v1 % 4]).clone();
+ d1.sub(o1.vertexList.get(planes[p1][(v1 + 1) % 4]));
+ if (d2.dot(d1) > -GeometryUtility.TOLERANCE) {
+ sign = 1;
+ } else if (sign == 1) {
+ // ���ς̕����������畉�ɕς�����Ƃ�
+ v1 = (v1 + 1) % 4;
+ break;
+ }
+ }
+ Vector3d vp1, vp2, dst1, dst2, src1, src2, d3;
+ ArrayList contours = new ArrayList();
+ for (int i = 0; i < 4; i++) {
+ dst1 = vp1 = (Vector3d)o1.vertexList.get(planes[p1][(v1 - i + 4) % 4]).clone();
+ src2 = vp2 = (Vector3d)o2.vertexList.get(planes[p2][(v2 + i) % 4]).clone();
+ src1 = (Vector3d)o1.vertexList.get(planes[p1][(v1 - i + 4 + 1) % 4]).clone();
+ dst2 = (Vector3d)o2.vertexList.get(planes[p2][(v2 + i + 1) % 4]).clone();
+ d1 = (Vector3d)dst1.clone();
+ d1.sub(src1);
+ d2 = (Vector3d)dst2.clone();
+ d2.sub(src2);
+ d3 = (Vector3d)vp2.clone();
+ d3.sub(vp1);
+ d1.cross(d1, normal);
+ if (d1.dot(d3) < GeometryUtility.TOLERANCE) {
+ // o1�̕��́A���_vp2�̓����ɂ���̂ŁA���ʗ̈�̗֊s���\������
+ contours.add(new Vector3d[]{src1, dst1});
+ }
+ d3.negate();
+ d2.cross(d2, normal);
+ if (d2.dot(d3) < GeometryUtility.TOLERANCE) {
+ // o2�̕��́A���_vp1�̓����ɂ���̂ŁA���ʗ̈�̗֊s���\������
+ contours.add(new Vector3d[]{src2, dst2});
+ }
+ }
+ Vector3d[] edge1, edge2;
+ Vector3d d;
+ Vector4d p;
+ for (int i = 0; i < contours.size(); i++) {
+ edge1 = contours.get(i);
+ edge2 = contours.get((i + 1) % contours.size());
+ if (edge1[1].equals(edge2[0])) {
+ // edge1��edge2�͎n�_�ƏI�_�����L���Ă���
+ if (!collisionPoints.contains(edge1[1])) {
+ collisionPoints.add(edge1[1]);
+ center.add(edge1[1]);
+ }
+ } else if (!edge1[0].equals(edge2[0]) && !edge1[1].equals(edge2[1])) {
+ // edge1��edge2�̌�_�����߂�
+ d = (Vector3d)edge2[1].clone();
+ d.add(normal);
+ p = GeometryUtility.createPlane(edge2[0], edge2[1], d);
+ if (p != null) {
+ d = GeometryUtility.intersect(p, edge1[0], edge1[1]);
+ if (d != null && !collisionPoints.contains(d)) {
+ collisionPoints.add(d);
+ center.add(d);
+ }
+ }
+ }
+ }
+ if (collisionPoints.size() <= 2) return null; // �ʂŐڐG���Ă���͂���2�_�ȉ��ł���ꍇ�A�Փ˂��Ă��Ȃ�
+ center.scale(1.0 / (double)collisionPoints.size());
+ cr.collisionPoint.setVector3d(center);
+ }
+ cr.length = lMin;
+ cr.collisionPoints = collisionPoints;
+ if (o2 == this) normal.negate();
+ normal.normalize();
+ cr.normal = normal;
+ return cr;
+ } else {
+ // another�̕ӂ�this�̖ʂƌ�����Ă��邩�H
+ Vector3d center = new Vector3d();
+ Vector3d normal = new Vector3d();
+ ArrayList intersections = new ArrayList();
+ ArrayList contactPlanes = new ArrayList();
+ for (int e = 0; e < edges.length; e++) {
+ // another�̊e��e�ɑ��ď���
+ Vector3d intersection = null;
+ intersections.clear();
+ contactPlanes.clear();
+ for (int p = 0; p < this.plane.length; p++) {
+ if (inside[edges[e][0]][p] == !inside[edges[e][1]][p]) {
+ // another�̕�e���Athis�̖�p���т��Ă���
+ Vector3d ip = GeometryUtility.intersect(
+ this.plane[p],
+ another.vertexList.get(edges[e][0]),
+ another.vertexList.get(edges[e][1]));
+ // e��p�̌�_��this�ɕ�܂���Ă��邩?
+ if (ip != null) {
+ intersection = ip;
+ boolean bInside = true;
+ for (int p2 = 0; p2 < 6; p2++) {
+ if (p != p2
+ && !GeometryUtility.inside(intersection, this.plane[p2])) {
+ bInside = false;
+ break;
+ }
+ }
+ if (bInside) {
+ // e��p�ƌ�����Ă���
+ contactPlanes.add(p);
+ intersections.add(intersection);
+ bCollides = true;
+ }
+ }
+ }
+ }
+ if (contactPlanes.size() == 1) {
+ // e�ƌ�����Ă���this�̖ʂ�1��
+ collisionPoints.add(intersection);
+ center.add(intersection);
+ } else if (contactPlanes.size() == 2) {
+ // e�ƌ�����Ă���this�̖ʂ�2��
+ int p1 = contactPlanes.get(0);
+ int p2 = contactPlanes.get(1);
+ ArrayList p1vs = new ArrayList(Arrays.asList(planes[p1]));
+ ArrayList p2vs = new ArrayList(Arrays.asList(planes[p2]));
+ p1vs.retainAll(p2vs);
+ if (p1vs.size() == 2) {
+ // p1��p2�ׂ͗荇����(another�̕�e��this�̂���ӂƐڐG���Ă���)
+ Vector3d v1 = this.vertexList.get(p1vs.get(0)); // p1��p2�̊Ԃ̕ӂ̎n�_
+ Vector3d v2 = this.vertexList.get(p1vs.get(1)); // p1��p2�̊Ԃ̕ӂ̏I�_
+ Vector3d d1 = (Vector3d)v1.clone();
+ d1.sub(v2);
+ Vector3d d2 = (Vector3d)another.vertexList.get(edges[e][0]).clone();
+ d2.sub(another.vertexList.get(edges[e][1]));
+ normal.cross(d1, d2); // ��e�ƁAp1��p2�̊Ԃ̕ӂ̗����ɐ����ȃx�N�g����@�������Ƃ���
+ normal.normalize();
+ Vector3d n1 = new Vector3d(this.plane[p1].x, this.plane[p1].y, this.plane[p1].z);
+ Vector3d n2 = new Vector3d(this.plane[p2].x, this.plane[p2].y, this.plane[p2].z);
+ n1.normalize();
+ n2.normalize();
+ n1.add(n2);
+ n1.scale(0.5);
+ if (n1.dot(normal) < -GeometryUtility.TOLERANCE) {
+ normal.negate();
+ }
+ intersection = intersections.get(0);
+ intersection.add(intersections.get(1));
+ intersection.scale(0.5);
+ center.add(intersection); // �Փ˓_��1��
+ collisionPoints.add(intersection);
+ Vector3d c = GeometryUtility.nearest(v1, v2, center);
+ c.sub(center);
+ cr.length = c.length();
+ cr.normal = normal;
+ } else {
+ // p1��p2�͌�����������(another�̕�e��this�̂���ʂƐڐG���Ă���)
+ center.add(intersections.get(0)); // �Փ˓_��2��
+ center.add(intersections.get(1));
+ collisionPoints.add(intersections.get(0));
+ collisionPoints.add(intersections.get(1));
+ // this�̂ǂ̖ʂƏՓ˂������肷��
+ double lMin = 0;
+ normal = null;
+ Vector4d plane;
+ for (int p = 0; p < this.plane.length; p++) {
+ plane = this.plane[p];
+ Vector3d n = new Vector3d(plane.x, plane.y, plane.z);
+ double l = -(center.x * plane.x + center.y * plane.y + center.z * plane.z + plane.w) / n.length();
+ if (lMin > l || normal == null) {
+ lMin = l;
+ normal = n;
+ }
+ }
+ normal.normalize();
+ cr.length = lMin;
+ cr.normal = normal;
+ }
+ }
+ }
+ if (!bCollides) return null;
+ center.scale(1.0 / (double)collisionPoints.size());
+ cr.collisionPoint.setVector3d(center);
+ cr.collisionPoints = collisionPoints;
+ return cr;
+ }
+ }
+
+ public Object clone() {
+ OBB obb = new OBB();
+ obb.plane = new Vector4d[6];
+ for (int i = 0; i < plane.length; i++) {
+ obb.plane[i] = (Vector4d) plane[i].clone();
+
+ }
+ for (int i = 0; i < vertexList.size(); i++) {
+ obb.vertexList.add((Vector3d) vertexList.get(i).clone());
+ }
+ obb.bp = new BoundingPolytope(obb.plane);
+
+ // System.out.println("veretexListSIZE:"+vertexList.size());
+ return obb;
+ }
+
+ public void transform(Transform3D t) {
+ // TODO Auto-generated method stub
+ bp.transform(t);
+ bp.getPlanes(plane);
+ // for(int i = 0; i" + plane[i].x + "," + plane[i].y + "," +
+ // plane[i].z + "," + plane[i].w);
+ // }
+ for (int i = 0; i < vertexList.size(); i++) {
+ // System.out.println("vertex");
+ // System.out.print(vertexList.get(i).x + "," + vertexList.get(i).y
+ // + "," + vertexList.get(i).z);
+ Matrix4d mat4d = new Matrix4d();
+ t.get(mat4d);
+ double x = mat4d.m00 * vertexList.get(i).x + mat4d.m01
+ * vertexList.get(i).y + mat4d.m02 * vertexList.get(i).z
+ + mat4d.m03;
+ double y = mat4d.m10 * vertexList.get(i).x + mat4d.m11
+ * vertexList.get(i).y + mat4d.m12 * vertexList.get(i).z
+ + mat4d.m13;
+ double z = mat4d.m20 * vertexList.get(i).x + mat4d.m21
+ * vertexList.get(i).y + mat4d.m22 * vertexList.get(i).z
+ + mat4d.m23;
+ vertexList.get(i).x = x;
+ vertexList.get(i).y = y;
+ vertexList.get(i).z = z;
+ // t.transform(vertexList.get(i));
+ // System.out.println("-->" + vertexList.get(i).x + "," +
+ // vertexList.get(i).y + "," + vertexList.get(i).z);
+ }
+ }
+}
diff --git a/src/main/java/framework/model3D/Object3D.java b/src/main/java/framework/model3D/Object3D.java
new file mode 100644
index 0000000..f6b9dac
--- /dev/null
+++ b/src/main/java/framework/model3D/Object3D.java
@@ -0,0 +1,734 @@
+package framework.model3D;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Iterator;
+
+import javax.media.j3d.Appearance;
+import javax.media.j3d.BoundingSphere;
+import javax.media.j3d.BranchGroup;
+import javax.media.j3d.Geometry;
+import javax.media.j3d.GeometryStripArray;
+import javax.media.j3d.IndexedGeometryArray;
+import javax.media.j3d.LOD;
+import javax.media.j3d.Leaf;
+import javax.media.j3d.Node;
+import javax.media.j3d.Shape3D;
+import javax.media.j3d.Transform3D;
+import javax.media.j3d.TransformGroup;
+import javax.media.j3d.TriangleArray;
+import javax.vecmath.AxisAngle4d;
+import javax.vecmath.Quat4d;
+import javax.vecmath.Vector3d;
+
+import com.sun.j3d.utils.geometry.Box;
+import com.sun.j3d.utils.geometry.Cone;
+import com.sun.j3d.utils.geometry.Cylinder;
+import com.sun.j3d.utils.geometry.Primitive;
+import com.sun.j3d.utils.geometry.Sphere;
+
+/**
+ * �K�w�����ꖼ�O�t����ꂽ��{�I�u�W�F�N�g
+ * @author �V�c����
+ *
+ */
+public class Object3D extends BaseObject3D {
+ public Object3D[] children = new Object3D[0];
+ public String name;
+ public TransformGroup pos;
+ public TransformGroup rot;
+ public TransformGroup scale;
+ protected Position3D position = new Position3D();
+ protected Quaternion3D quaternion;
+
+ public BoundingSphere bs = null;
+ private OBB obb = null;
+ private UndoBuffer undoBuffer = new UndoBuffer();
+ private boolean bLOD = false;
+ private LOD lodNode = null;
+
+ // �R���X�g���N�^
+ public Object3D(String name, Primitive node) {
+ if (name == null) name = "";
+ this.name = new String(name);
+ pos = new TransformGroup();
+ pos.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
+ pos.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
+ rot = new TransformGroup();
+ rot.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
+ rot.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
+ scale = new TransformGroup();
+ scale.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
+ scale.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
+ center = new TransformGroup();
+ center.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
+ center.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
+ pos.addChild(rot);
+ rot.addChild(scale);
+ scale.addChild(center);
+ center.addChild(node);
+ }
+
+ public Object3D(String name, Leaf node) {
+ if (name == null) name = "";
+ this.name = new String(name);
+ if (!(node instanceof LOD)) {
+ pos = new TransformGroup();
+ pos.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
+ pos.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
+ rot = new TransformGroup();
+ rot.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
+ rot.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
+ scale = new TransformGroup();
+ scale.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
+ scale.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
+ center = new TransformGroup();
+ center.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
+ center.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
+ pos.addChild(rot);
+ rot.addChild(scale);
+ scale.addChild(center);
+ center.addChild(node);
+ } else {
+ // LOD �̏ꍇ
+ bLOD = true;
+ lodNode = (LOD)node;
+ pos = new TransformGroup();
+ pos.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
+ pos.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
+ rot = new TransformGroup();
+ rot.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
+ rot.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
+ scale = new TransformGroup();
+ scale.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
+ scale.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
+ center = new TransformGroup();
+ center.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
+ center.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
+ pos.addChild(rot);
+ rot.addChild(scale);
+ scale.addChild(center);
+ BranchGroup lodRoot = new BranchGroup();
+ lodRoot.addChild(lodNode);
+ lodRoot.addChild(lodNode.getSwitch(0));
+ center.addChild(lodRoot);
+ }
+ }
+
+ public Object3D(String name, Geometry g, Appearance a) {
+ if (name == null) name = "";
+ this.name = new String(name);
+ pos = new TransformGroup();
+ pos.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
+ pos.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
+ rot = new TransformGroup();
+ rot.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
+ rot.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
+ scale = new TransformGroup();
+ scale.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
+ scale.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
+ center = new TransformGroup();
+ center.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
+ center.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
+ a.setCapability(Appearance.ALLOW_TEXTURE_READ);
+ a.setCapability(Appearance.ALLOW_TEXTURE_WRITE);
+ a.setCapability(Appearance.ALLOW_TEXTURE_ATTRIBUTES_READ);
+ a.setCapability(Appearance.ALLOW_TEXTURE_ATTRIBUTES_WRITE);
+ a.setCapability(Appearance.ALLOW_TEXTURE_UNIT_STATE_READ);
+ a.setCapability(Appearance.ALLOW_TEXTURE_UNIT_STATE_WRITE);
+ Shape3D shape = new Shape3D(g, a);
+ shape.setCapability(Shape3D.ALLOW_APPEARANCE_READ);
+ shape.setCapability(Shape3D.ALLOW_APPEARANCE_WRITE);
+ pos.addChild(rot);
+ rot.addChild(scale);
+ scale.addChild(center);
+ center.addChild(shape);
+ }
+
+ // �R���X�g���N�^
+ public Object3D(String name, Object3D[] children) {
+ if (name == null)
+ name = "";
+ this.name = name;
+ this.children = children;
+ int n = children.length;
+ int i = 0;
+
+ pos = new TransformGroup();
+ pos.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
+ pos.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
+ rot = new TransformGroup();
+ rot.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
+ rot.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
+ scale = new TransformGroup();
+ scale.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
+ scale.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
+ center = new TransformGroup();
+ center.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
+ center.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
+
+ pos.addChild(rot);
+ rot.addChild(scale);
+ scale.addChild(center);
+
+ for (i = 0; i < n; i++) {
+ center.addChild(children[i].pos);
+ if (children[i].isBumpMappingApplied()) bBumpMapApplied = true;
+ if (children[i].isReflectionMappingApplied()) bReflectionMapApplied = true;
+ }
+ }
+
+ public Object3D(String name, Object3D[] children,
+ Transform3D defaultTransform) {
+ this(name, children);
+ if (defaultTransform == null) return;
+ pos.setTransform(defaultTransform);
+ }
+
+ // �R�s�[�R���X�g���N�^
+ public Object3D(Object3D obj) {
+ this.name = new String(obj.name);
+ if (obj.position != null) {
+ this.position = new Position3D(obj.position);
+ } else {
+ this.position = new Position3D();
+ }
+ if (obj.getQuaternion() != null) {
+ this.quaternion = new Quaternion3D(obj.getQuaternion());
+ } else {
+ this.quaternion = new Quaternion3D();
+ }
+ Transform3D transPos = new Transform3D();
+ obj.pos.getTransform(transPos);
+ this.pos = new TransformGroup(transPos);
+ this.pos.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
+ this.pos.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
+ Transform3D transRot = new Transform3D();
+ obj.rot.getTransform(transRot);
+ this.rot = new TransformGroup(transRot);
+ this.rot.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
+ this.rot.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
+ Transform3D transScale = new Transform3D();
+ obj.scale.getTransform(transScale);
+ this.scale = new TransformGroup(transScale);
+ this.scale.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
+ this.scale.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
+ Transform3D transCenter = new Transform3D();
+ obj.center.getTransform(transCenter);
+ this.center = new TransformGroup(transCenter);
+ this.center.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
+ this.center.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
+ this.pos.addChild(this.rot);
+ this.rot.addChild(this.scale);
+ this.scale.addChild(this.center);
+ this.bLOD = obj.bLOD;
+ if (obj.hasChildren()) {
+ this.children = new Object3D[obj.children.length];
+ for (int i = 0; i < obj.children.length; i++) {
+ this.children[i] = new Object3D(obj.children[i]);
+ this.center.addChild(this.children[i].pos);
+ }
+ } else {
+ this.children = new Object3D[0];
+ if (!bLOD) {
+ Enumeration nodes = obj.getPrimitiveNodes();
+ while (nodes.hasMoreElements()) {
+ Node node = nodes.nextElement();
+ if (node != null && node instanceof Shape3D) {
+ Shape3D shape = (Shape3D)node;
+ shape.setCapability(Shape3D.ALLOW_APPEARANCE_READ);
+ shape.setCapability(Shape3D.ALLOW_APPEARANCE_WRITE);
+ Appearance a = (Appearance)shape.getAppearance().cloneNodeComponent(true);
+ a.setCapability(Appearance.ALLOW_TEXTURE_READ);
+ a.setCapability(Appearance.ALLOW_TEXTURE_WRITE);
+ a.setCapability(Appearance.ALLOW_TEXTURE_ATTRIBUTES_READ);
+ a.setCapability(Appearance.ALLOW_TEXTURE_ATTRIBUTES_WRITE);
+ a.setCapability(Appearance.ALLOW_TEXTURE_UNIT_STATE_READ);
+ a.setCapability(Appearance.ALLOW_TEXTURE_UNIT_STATE_WRITE);
+ this.center.addChild(new Shape3D((Geometry) shape
+ .getAllGeometries().nextElement(), a));
+ } else if (node != null && node instanceof Primitive) {
+ Primitive primitive = (Primitive)node;
+ primitive = (Primitive)primitive.cloneTree();
+ primitive.setCapability(Primitive.ENABLE_APPEARANCE_MODIFY);
+ this.center.addChild(primitive);
+ }
+ }
+ } else {
+ // LOD �̏ꍇ
+ this.lodNode = (LOD)obj.lodNode.cloneTree();
+ BranchGroup lodRoot = new BranchGroup();
+ lodRoot.addChild(lodNode);
+ lodRoot.addChild(lodNode.getSwitch(0));
+ this.center.addChild(lodRoot);
+ }
+ }
+ if (obj.obb != null) {
+ this.obb = obj.obb;
+ }
+ if (obj.bs != null) {
+ this.bs = obj.bs;
+ }
+ if (obj.boundingSurfaces != null) {
+ this.boundingSurfaces = obj.boundingSurfaces;
+ }
+ this.undoBuffer = new UndoBuffer(obj.undoBuffer);
+ }
+
+ public Node getPrimitiveNode() {
+ if (hasChildren()) return null;
+ if (!bLOD) {
+ return (Node)center.getChild(0);
+ } else {
+ // LOD �̏ꍇ
+ return lodNode.getSwitch(0).getChild(0);
+ }
+ }
+
+ public Enumeration getPrimitiveNodes() {
+ if (hasChildren()) return null;
+ if (!bLOD) {
+ return (Enumeration)center.getAllChildren();
+ } else {
+ // LOD �̏ꍇ
+ return lodNode.getSwitch(0).getAllChildren();
+ }
+ }
+
+ public ArrayList getAppearances() {
+ ArrayList appearances = new ArrayList();
+ if (!bLOD) {
+ if (!hasChildren()) {
+ appearances.add(getAppearance());
+ } else {
+ for (int n = 0; n < children.length; n++) {
+ appearances.addAll(children[n].getAppearances());
+ }
+ }
+ return appearances;
+ } else {
+ // LOD �̏ꍇ
+ Enumeration nodes = getPrimitiveNodes();
+ while (nodes.hasMoreElements()) {
+ Node node = nodes.nextElement();
+ Appearance ap = null;
+ if (node != null && node instanceof Shape3D) {
+ Shape3D shape = (Shape3D)node;
+ ap = shape.getAppearance();
+ if (ap == null) {
+ ap = new Appearance();
+ shape.setAppearance(ap);
+ }
+ } else if (node != null && node instanceof Primitive) {
+ Primitive primitive = (Primitive)node;
+ ap = primitive.getAppearance();
+ if (ap == null) {
+ ap = new Appearance();
+ primitive.setAppearance(ap);
+ }
+ }
+ appearances.add(ap);
+ }
+ return appearances;
+ }
+ }
+
+ // ����part�i�����j�̃I�u�W�F�N�g��T��
+ public Object3D getPart(String part) {
+
+ int j = 0;
+ int N = children.length;
+ Object3D obj;
+
+ // if(part == children[j].name) return this;
+ if (part.equals(this.name))
+ return this;
+
+ for (j = 0; j < N; j++) {
+ if (children[j] != null) {
+ obj = children[j].getPart(part);
+ if (obj != null)
+ return obj;
+ else
+ continue;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public TransformGroup getTransformGroupToPlace() {
+ return pos;
+ }
+
+ // Position3D �� applyTo() �ȊO����͌ĂȂ�����
+ void setPosition(Position3D p) {
+ position = (Position3D) p.clone();
+ Vector3d v = new Vector3d(p.getX(), p.getY(), p.getZ());
+ Transform3D trans = new Transform3D();
+ trans.set(v);
+ pos.setTransform(trans);
+ }
+
+ public void scale(double s) {
+ Transform3D trans = new Transform3D();
+ trans.setScale(s);
+ scale.setTransform(trans);
+ }
+
+ public void scale(double x, double y, double z) {
+ Transform3D trans = new Transform3D();
+ trans.setScale(new Vector3d(x, y, z));
+ scale.setTransform(trans);
+ }
+
+ public Position3D getPosition3D() {
+ return (Position3D) position.clone();
+
+ }
+
+ // �L�����N�^�[����]������
+ public void rotate(double vx, double vy, double vz, double a) {
+ AxisAngle4d t = new AxisAngle4d(vx, vy, vz, a);
+ Transform3D trans = new Transform3D();
+ trans.setRotation(t);
+ rot.setTransform(trans);
+ }
+
+ private void rotate(Quat4d quat) {
+ Transform3D trans = new Transform3D();
+ trans.setRotation(quat);
+ rot.setTransform(trans);
+ }
+
+ // �L�����N�^�[��part(�̂̕���)����]������
+ public void rotate(String part, double vx, double vy, double vz, double a) {
+ getPart(part).rotate(vx, vy, vz, a);
+ }
+
+ public void apply(Property3D p, boolean enableUndo) {
+ if (enableUndo) {
+ undoBuffer.push(p);
+ }
+ p.applyTo(this);
+ }
+
+ // ����������i�N���[�������j
+ public Object3D duplicate() {
+ Object3D obj = new Object3D(this);
+ return obj;
+ }
+
+ // v�i�K��ҁj�ɖK����������
+ public void accept(ObjectVisitor v) {
+ int i;
+ v.preVisit(this);
+ if (children != null) {
+ for (i = 0; i < children.length; i++)
+ children[i].accept(v);
+ } else
+ ;
+ v.postVisit(this);
+ }
+
+ // object�Ɏq�������邩�ǂ����ׂ�
+ public boolean hasChildren() {
+ if (this.children != null && this.children.length > 0)
+ return true;
+ else
+ return false;
+ }
+
+ /*
+ * undo����|�C���g��ݒ肷��B
+ */
+ public void setUndoMark() {
+ undoBuffer.setUndoMark();
+ }
+
+ /*
+ * undo����B
+ */
+ public void undo() {
+ Iterator iterator = undoBuffer.undo().iterator();
+ while (iterator.hasNext()) {
+ Property3D p = iterator.next();
+ p.applyTo(this);
+ }
+ }
+
+ /**
+ * �����蔻�菈���AOriented Bounding Box(OBB)������B 0:�ő�ʐϖ@�@1:�Œ��Ίp���@
+ */
+ public OBB getOBB(int pattern) {
+ if (obb == null) {
+ Node node = getPrimitiveNode();
+ if (node == null) return null;
+ if (node instanceof Box) {
+ // Box�̏ꍇ
+ Box box = ((Box)node);
+ double xDim = box.getXdimension();
+ double yDim = box.getYdimension();
+ double zDim = box.getZdimension();
+ obb = new OBB(new Vector3d(-xDim, -yDim, -zDim),
+ new Vector3d(-xDim, yDim, -zDim),
+ new Vector3d(-xDim, -yDim, zDim),
+ new Vector3d(-xDim, yDim, zDim),
+ new Vector3d(xDim, -yDim, -zDim),
+ new Vector3d(xDim, yDim, -zDim),
+ new Vector3d(xDim, -yDim, zDim),
+ new Vector3d(xDim, yDim, zDim));
+ } else if (node instanceof Cylinder) {
+ // Cylinder�̏ꍇ
+ Cylinder cylinder = ((Cylinder)node);
+ double xDim = cylinder.getRadius();
+ double yDim = cylinder.getHeight() / 2;
+ double zDim = cylinder.getRadius();
+ obb = new OBB(new Vector3d(-xDim, -yDim, -zDim),
+ new Vector3d(-xDim, yDim, -zDim),
+ new Vector3d(-xDim, -yDim, zDim),
+ new Vector3d(-xDim, yDim, zDim),
+ new Vector3d(xDim, -yDim, -zDim),
+ new Vector3d(xDim, yDim, -zDim),
+ new Vector3d(xDim, -yDim, zDim),
+ new Vector3d(xDim, yDim, zDim));
+ } else if (node instanceof Cone) {
+ // Cone�̏ꍇ
+ Cone cone = ((Cone)node);
+ double xDim = cone.getRadius();
+ double yDim = cone.getHeight() / 2;
+ double zDim = cone.getRadius();
+ obb = new OBB(new Vector3d(-xDim, -yDim, -zDim),
+ new Vector3d(-xDim, yDim, -zDim),
+ new Vector3d(-xDim, -yDim, zDim),
+ new Vector3d(-xDim, yDim, zDim),
+ new Vector3d(xDim, -yDim, -zDim),
+ new Vector3d(xDim, yDim, -zDim),
+ new Vector3d(xDim, -yDim, zDim),
+ new Vector3d(xDim, yDim, zDim));
+ } else if (node instanceof Sphere) {
+ // Sphere�̏ꍇ
+ Sphere sphere = ((Sphere)node);
+ double xDim = sphere.getRadius();
+ double yDim = sphere.getRadius();
+ double zDim = sphere.getRadius();
+ obb = new OBB(new Vector3d(-xDim, -yDim, -zDim),
+ new Vector3d(-xDim, yDim, -zDim),
+ new Vector3d(-xDim, -yDim, zDim),
+ new Vector3d(-xDim, yDim, zDim),
+ new Vector3d(xDim, -yDim, -zDim),
+ new Vector3d(xDim, yDim, -zDim),
+ new Vector3d(xDim, -yDim, zDim),
+ new Vector3d(xDim, yDim, zDim));
+ } else {
+ if (!(node instanceof Shape3D)) return null;
+ // Shape3D�̏ꍇ
+ Shape3D shape = (Shape3D)node;
+ double coordinate[] = new double[3];
+
+ // OBB�̍쐬�ɗp���钸�_��̎擾
+ ArrayList vertex3DList = new ArrayList();
+ if (shape.getGeometry() instanceof IndexedGeometryArray) {
+ // IndexedGeometryArray�̏ꍇ
+ IndexedGeometryArray iga = (IndexedGeometryArray) shape.getGeometry();
+ for (int i = 0; i < iga.getIndexCount() - 3; i++) {
+ iga.getCoordinates(iga.getCoordinateIndex(i), coordinate);
+ Vector3d p = new Vector3d(coordinate[0], coordinate[1], coordinate[2]);
+ vertex3DList.add(p);
+ }
+ } else if (shape.getGeometry() instanceof GeometryStripArray) {
+ // GeometryStripArray�̏ꍇ
+ GeometryStripArray gsa = (GeometryStripArray) shape.getGeometry();
+ for (int i = 0; i < gsa.getVertexCount(); i++) {
+ gsa.getCoordinates(i, coordinate);
+ Vector3d p = new Vector3d(coordinate[0], coordinate[1], coordinate[2]);
+ vertex3DList.add(p);
+ }
+ } else if (shape.getGeometry() instanceof TriangleArray) {
+ // TriangleArray�̏ꍇ
+ TriangleArray tra = (TriangleArray) shape.getGeometry();
+ for (int i = 0; i < tra.getVertexCount(); i++) {
+ tra.getCoordinates(i, coordinate);
+ Vector3d p = new Vector3d(coordinate[0], coordinate[1], coordinate[2]);
+ vertex3DList.add(p);
+ }
+ }
+
+ if (pattern == 0) {
+ // �ő�ʐϖ@
+ Vector3d cv1 = new Vector3d();
+ Vector3d cv2 = new Vector3d();
+
+ double cvMax = 0.0;
+ Vector3d axis1 = new Vector3d(); // 3D���_���狁�߂��@���x�N�g��
+ Vector3d axis2 = new Vector3d(); // 2D���_���狁�߂��@���x�N�g��
+ Vector3d axis3 = new Vector3d(); // axis1,axis2�̊O�ς��狁�߂��@���x�N�g��
+
+ // �ʐς�3D���_���X�g���狁�߁A�@�������߂鏈��
+ for (int i = 0; i < vertex3DList.size(); i += 3) {
+ cv1.sub(vertex3DList.get(i + 2), vertex3DList.get(i));
+ cv2.sub(vertex3DList.get(i + 1), vertex3DList.get(i));
+ Vector3d cv = new Vector3d();
+ cv.cross(cv1, cv2);
+ if (i == 0 || cv.length() >= cvMax) {
+ cvMax = cv.length();
+ axis1 = cv;
+ }
+ }
+
+ ProjectionResult pr1 = GeometryUtility.projection3D(vertex3DList, axis1);
+ // �ӂ̂�2D���_���X�g���狁�߁A�@�������߂鏈��
+ for (int i = 0; i < pr1.vertexList.size() - 1; i++) {
+ Vector3d cv = new Vector3d();
+ cv.sub(vertex3DList.get(i + 1), vertex3DList.get(i));
+ if (i == 0 || cv.length() >= cvMax) {
+ cvMax = cv.length();
+ axis2 = cv;
+ }
+ }
+
+
+ ProjectionResult pr2 = GeometryUtility.projection2D(pr1.vertexList, axis2);
+ // axis1,axis2�ŊO�ς�axis3�����߂�B
+ axis3.cross(axis1, axis2);
+
+ ProjectionResult pr3 = GeometryUtility.projection2D(pr1.vertexList, axis3);
+ AxisResult ar = new AxisResult(axis1, axis2, axis3);
+
+ // ��������ő�ʐϖ@�ŋ��߂��_���擾���Ă�������
+
+ // OBB�̐���
+ obb = new OBB();
+
+ // No.1
+ ar.axis1.scale(pr1.min);
+ ar.axis2.scale(pr2.min);
+ ar.axis3.scale(pr3.min);
+ ar.axis1.add(ar.axis2);
+ ar.axis3.add(ar.axis1);
+ obb.addVertex(ar.axis3);
+
+ // No.2
+ ar = new AxisResult(axis1, axis2, axis3);
+ ar.axis1.scale(pr1.min);
+ ar.axis2.scale(pr2.max);
+ ar.axis3.scale(pr3.min);
+ ar.axis1.add(ar.axis2);
+ ar.axis3.add(ar.axis1);
+ obb.addVertex(ar.axis3);
+
+ // No.3
+ ar = new AxisResult(axis1, axis2, axis3);
+ ar.axis1.scale(pr1.min);
+ ar.axis2.scale(pr2.min);
+ ar.axis3.scale(pr3.max);
+ ar.axis1.add(ar.axis2);
+ ar.axis3.add(ar.axis1);
+ obb.addVertex(ar.axis3);
+
+ // No.4
+ ar = new AxisResult(axis1, axis2, axis3);
+ ar.axis1.scale(pr1.min);
+ ar.axis2.scale(pr2.max);
+ ar.axis3.scale(pr3.max);
+ ar.axis1.add(ar.axis2);
+ ar.axis3.add(ar.axis1);
+ obb.addVertex(ar.axis3);
+
+ // No.5
+ ar = new AxisResult(axis1, axis2, axis3);
+ ar.axis1.scale(pr1.max);
+ ar.axis2.scale(pr2.min);
+ ar.axis3.scale(pr3.min);
+ ar.axis1.add(ar.axis2);
+ ar.axis3.add(ar.axis1);
+ obb.addVertex(ar.axis3);
+
+ // No.6
+ ar = new AxisResult(axis1, axis2, axis3);
+ ar.axis1.scale(pr1.max);
+ ar.axis2.scale(pr2.max);
+ ar.axis3.scale(pr3.min);
+ ar.axis1.add(ar.axis2);
+ ar.axis3.add(ar.axis1);
+ obb.addVertex(ar.axis3);
+
+ // No.7
+ ar = new AxisResult(axis1, axis2, axis3);
+ ar.axis1.scale(pr1.max);
+ ar.axis2.scale(pr2.min);
+ ar.axis3.scale(pr3.max);
+ ar.axis1.add(ar.axis2);
+ ar.axis3.add(ar.axis1);
+ obb.addVertex(ar.axis3);
+
+ // No.8
+ ar = new AxisResult(axis1, axis2, axis3);
+ ar.axis1.scale(pr1.max);
+ ar.axis2.scale(pr2.max);
+ ar.axis3.scale(pr3.max);
+ ar.axis1.add(ar.axis2);
+ ar.axis3.add(ar.axis1);
+ obb.addVertex(ar.axis3);
+
+ // �ʂ���ы��E���ʑ̂̐���
+ obb.createPlanes();
+ } else {
+ // AABB
+ double minX, maxX, minY, maxY, minZ, maxZ;
+ minX = maxX = vertex3DList.get(0).x;
+ minY = maxY = vertex3DList.get(0).y;
+ minZ = maxZ = vertex3DList.get(0).z;
+ for (int n = 1; n < vertex3DList.size(); n++) {
+ Vector3d v = vertex3DList.get(n);
+ if (minX > v.x) minX = v.x;
+ if (maxX < v.x) maxX = v.x;
+ if (minY > v.y) minY = v.y;
+ if (maxY < v.y) maxY = v.y;
+ if (minZ > v.z) minZ = v.z;
+ if (maxZ < v.z) maxZ = v.z;
+ }
+ obb = new OBB(new Vector3d(minX, minY, minZ),
+ new Vector3d(minX, maxY, minZ),
+ new Vector3d(minX, minY, maxZ),
+ new Vector3d(minX, maxY, maxZ),
+ new Vector3d(maxX, minY, minZ),
+ new Vector3d(maxX, maxY, minZ),
+ new Vector3d(maxX, minY, maxZ),
+ new Vector3d(maxX, maxY, maxZ));
+ }
+ }
+ }
+ return obb;
+ }
+
+ private class AxisResult {
+ Vector3d axis1;
+ Vector3d axis2;
+ Vector3d axis3;
+
+ AxisResult(Vector3d a1, Vector3d a2, Vector3d a3) {
+ axis1 = (Vector3d) a1.clone();
+ axis2 = (Vector3d) a2.clone();
+ axis3 = (Vector3d) a3.clone();
+ }
+ }
+
+ // Quaternion3D �� applyTo() �ȊO����͌ĂȂ�����
+ void setQuaternion(Quaternion3D quaternion) {
+ this.quaternion = quaternion;
+ rotate(quaternion.getQuat());
+ }
+
+ public Quaternion3D getQuaternion() {
+ return quaternion;
+ }
+
+ public boolean isLODSet() {
+ return bLOD;
+ }
+
+ public LOD getLOD() {
+ return lodNode;
+ }
+}
diff --git a/src/main/java/framework/model3D/ObjectVisitor.java b/src/main/java/framework/model3D/ObjectVisitor.java
new file mode 100644
index 0000000..1e5a5f9
--- /dev/null
+++ b/src/main/java/framework/model3D/ObjectVisitor.java
@@ -0,0 +1,57 @@
+package framework.model3D;
+
+import java.util.ArrayList;
+
+import javax.media.j3d.Transform3D;
+
+/**
+ * �I�u�W�F�N�g�̊K�w�\�����g���o�[�X����r�W�^�[
+ * @author �V�c����
+ *
+ */
+public abstract class ObjectVisitor {
+ /**
+ * ������K��ߓ_�܂ł̃p�X��ɑ��݂���ϊ��s��
+ */
+ protected ArrayList stackList = new ArrayList();
+
+ /*
+ * �ߓ_�i�I�u�W�F�N�g�j��K�₷�钼�O�ɌĂ�郁�\�b�h
+ * @param obj �K��ߓ_
+ */
+ public abstract void preVisit(Object3D obj);
+ /**
+ * �ߓ_�i�I�u�W�F�N�g��K�₵������ɌĂ�郁�\�b�h�j
+ * @param obj �K��ߓ_
+ */
+ public abstract void postVisit(Object3D obj);
+
+ /**
+ * 1�K�w�������Ƃ��ɕϊ��s��𑝂₷
+ * @param obj�@�V�����K�₵���ߓ_
+ */
+ protected void pushTransform(Object3D obj) {
+ Transform3D transPos = new Transform3D();
+ obj.pos.getTransform(transPos);
+ stackList.add(transPos);
+ Transform3D transRot = new Transform3D();
+ obj.rot.getTransform(transRot);
+ stackList.add(transRot);
+ Transform3D transScale = new Transform3D();
+ obj.scale.getTransform(transScale);
+ stackList.add(transScale);
+ Transform3D transCenter = new Transform3D();
+ obj.center.getTransform(transCenter);
+ stackList.add(transCenter);
+ }
+
+ /**
+ *�@1�K�w���A�����Ƃ��ɕϊ��s��� ���炷
+ */
+ protected void popTransform() {
+ for (int i = 0; i < 4; i++) {
+ stackList.remove(stackList.size() - 1);
+ }
+ }
+
+}
diff --git a/src/main/java/framework/model3D/Placeable.java b/src/main/java/framework/model3D/Placeable.java
new file mode 100644
index 0000000..e8ecce0
--- /dev/null
+++ b/src/main/java/framework/model3D/Placeable.java
@@ -0,0 +1,13 @@
+package framework.model3D;
+
+import javax.media.j3d.TransformGroup;
+
+/**
+ * �z�u�ł�����̑S��
+ * @author �V�c����
+ *
+ */
+public interface Placeable {
+ abstract TransformGroup getTransformGroupToPlace();
+ abstract BaseObject3D getBody();
+}
diff --git a/src/main/java/framework/model3D/Position3D.java b/src/main/java/framework/model3D/Position3D.java
new file mode 100644
index 0000000..064dda8
--- /dev/null
+++ b/src/main/java/framework/model3D/Position3D.java
@@ -0,0 +1,151 @@
+package framework.model3D;
+
+import javax.vecmath.Vector3d;
+
+/**
+ * ���W�l��\��
+ * @author �V�c����
+ *
+ */
+public class Position3D extends Property3D {
+ private double x;
+ private double y;
+ private double z;
+
+ // �R���X�g���N�^
+ public Position3D() {
+ x = 0.0;
+ y = 0.0;
+ z = 0.0;
+ }
+
+ // �R���X�g���N�^
+ public Position3D(double px, double py, double pz) {
+ x = px;
+ y = py;
+ z = pz;
+ }
+
+ public Position3D(Vector3d v) {
+ x = v.x;
+ y = v.y;
+ z = v.z;
+ }
+
+ // property3D�̒��ۃN���X�߂�
+ public void applyTo(Object3D o) {
+ o.setPosition(this);
+ }
+
+ // �R�s�[�R���X�g���N�^
+ public Position3D(Position3D p) {
+ this.x = p.x;
+ this.y = p.y;
+ this.z = p.z;
+ }
+
+ public Position3D set(double x, double y, double z) {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ return this;
+ }
+
+ // ���Z
+ public Position3D add(double x, double y, double z) {
+ this.x += x;
+ this.y += y;
+ this.z += z;
+ return this;
+ }
+
+ // ���Z
+ public Position3D add(Position3D p) {
+ this.x += p.x;
+ this.y += p.y;
+ this.z += p.z;
+ return this;
+ }
+
+ // ���Z
+ public Position3D add(Vector3d v) {
+ this.x += v.x;
+ this.y += v.y;
+ this.z += v.z;
+ return this;
+ }
+
+ // ���Z
+ public Position3D sub(double x, double y, double z) {
+ this.x -= x;
+ this.y -= y;
+ this.z -= z;
+ return this;
+ }
+
+ // ���Z
+ public Position3D sub(Position3D p) {
+ this.x -= p.x;
+ this.y -= p.y;
+ this.z -= p.z;
+ return this;
+ }
+
+ // ���Z
+ public Position3D sub(Vector3d v) {
+ this.x -= v.x;
+ this.y -= v.y;
+ this.z -= v.z;
+ return this;
+ }
+
+ // �X�J���[�{
+ public Position3D mul(double d) {
+ this.x *= d;
+ this.y *= d;
+ this.z *= d;
+ return this;
+ }
+
+ public Position3D setX(double x) {
+ this.x = x;
+ return this;
+ }
+
+ public double getX() {
+ return x;
+ }
+
+ public Position3D setY(double y) {
+ this.y = y;
+ return this;
+ }
+
+ public double getY() {
+ return y;
+ }
+
+ public Position3D setZ(double z) {
+ this.z = z;
+ return this;
+ }
+
+ public double getZ() {
+ return z;
+ }
+
+ public Vector3d getVector3d() {
+ return new Vector3d(x, y, z);
+ }
+
+ public Position3D setVector3d(Vector3d v) {
+ x = v.x;
+ y = v.y;
+ z = v.z;
+ return this;
+ }
+
+ public Position3D clone() {
+ return new Position3D(this);
+ }
+}
diff --git a/src/main/java/framework/model3D/ProjectionResult.java b/src/main/java/framework/model3D/ProjectionResult.java
new file mode 100644
index 0000000..8cfeed1
--- /dev/null
+++ b/src/main/java/framework/model3D/ProjectionResult.java
@@ -0,0 +1,11 @@
+package framework.model3D;
+import java.util.ArrayList;
+
+import javax.vecmath.Vector3d;
+
+
+public class ProjectionResult {
+ double max = 0.0;
+ double min = 0.0;
+ ArrayList vertexList = new ArrayList();
+}
diff --git a/src/main/java/framework/model3D/Property3D.java b/src/main/java/framework/model3D/Property3D.java
new file mode 100644
index 0000000..4c82645
--- /dev/null
+++ b/src/main/java/framework/model3D/Property3D.java
@@ -0,0 +1,8 @@
+package framework.model3D;
+
+
+public abstract class Property3D{
+ public abstract void applyTo(Object3D o);
+
+ public abstract Property3D clone();
+}
diff --git a/src/main/java/framework/model3D/Quaternion3D.java b/src/main/java/framework/model3D/Quaternion3D.java
new file mode 100644
index 0000000..3ba2afa
--- /dev/null
+++ b/src/main/java/framework/model3D/Quaternion3D.java
@@ -0,0 +1,103 @@
+package framework.model3D;
+
+import javax.vecmath.AxisAngle4d;
+import javax.vecmath.Quat4d;
+
+public class Quaternion3D extends Property3D{
+ private Quat4d quaternion;
+
+ //�R���X�g���N�^=============================
+ public Quaternion3D(){
+ AxisAngle4d aa = new AxisAngle4d(0.0, 0.0, 1.0, 0.0);
+ quaternion = new Quat4d();
+ quaternion.set(aa);
+ }
+
+ public Quaternion3D(AxisAngle4d aa){
+ quaternion = new Quat4d();
+ quaternion.set(aa);
+ }
+
+ public Quaternion3D(double x,double y,double z,double w){
+ AxisAngle4d aa = new AxisAngle4d(x, y, z, w);
+ quaternion = new Quat4d();
+ quaternion.set(aa);
+ }
+ public Quaternion3D(Quaternion3D q){
+ this.quaternion = (Quat4d)q.getQuat().clone();
+ }
+ public Quat4d getQuat(){
+ return quaternion;
+ }
+
+ //�Q�b�^=================================
+ public double getX(){
+ return quaternion.x;
+ }
+ public double getY(){
+ return quaternion.y;
+ }
+ public double getZ(){
+ return quaternion.z;
+ }
+ public double getW(){
+ return quaternion.w;
+ }
+ public Quaternion3D getInterpolate(Quaternion3D q,double alpha){
+ quaternion.interpolate(q.getQuat(), alpha);
+ return this;
+ }
+
+ public AxisAngle4d getAxisAngle() {
+ AxisAngle4d axisAngle = new AxisAngle4d();
+ axisAngle.set(quaternion);
+ return axisAngle;
+ }
+
+ //�Z�b�^=================================
+ public Quaternion3D setQuaternion(double x,double y,double z,double w){
+ quaternion = new Quat4d(x, y, z, w);
+ return this;
+ }
+
+ public Quaternion3D setAxisAngle(double x,double y,double z,double w){
+ AxisAngle4d aa = new AxisAngle4d(x, y, z, w);
+ quaternion = new Quat4d();
+ quaternion.set(aa);
+ return this;
+ }
+
+ public Quaternion3D add(AxisAngle4d aa){
+ Quat4d q = new Quat4d();
+ q.set(aa);
+ q.mul(quaternion);
+ quaternion = q;
+ return this;
+ }
+
+ public Quaternion3D mul(Quaternion3D q){
+ quaternion.mul(q.getQuat());
+ return this;
+ }
+
+ @Override
+ public void applyTo(Object3D o) {
+ // TODO Auto-generated method stub
+ o.setQuaternion(this);
+ }
+
+ @Override
+ public Property3D clone() {
+ // TODO Auto-generated method stub
+ return new Quaternion3D(this);
+ }
+
+ public double norm() {
+ return quaternion.w * quaternion.w + quaternion.x * quaternion.x + quaternion.y * quaternion.y + quaternion.z * quaternion.z;
+ }
+
+ public Quaternion3D normalize() {
+ quaternion.normalize();
+ return this;
+ }
+}
diff --git a/src/main/java/framework/model3D/ReflectionMapGenerator.java b/src/main/java/framework/model3D/ReflectionMapGenerator.java
new file mode 100644
index 0000000..57aa4f9
--- /dev/null
+++ b/src/main/java/framework/model3D/ReflectionMapGenerator.java
@@ -0,0 +1,15 @@
+package framework.model3D;
+
+import javax.vecmath.Color4f;
+
+public class ReflectionMapGenerator extends MapGenerator {
+ private Color4f blendColor = null;
+
+ public ReflectionMapGenerator(Color4f blendColor) {
+ this.blendColor = blendColor;
+ }
+
+ public Color4f getBlendColor() {
+ return blendColor;
+ }
+}
diff --git a/src/main/java/framework/model3D/ShadowVolume.java b/src/main/java/framework/model3D/ShadowVolume.java
new file mode 100644
index 0000000..1422677
--- /dev/null
+++ b/src/main/java/framework/model3D/ShadowVolume.java
@@ -0,0 +1,596 @@
+package framework.model3D;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Hashtable;
+import java.util.Iterator;
+
+import javax.media.j3d.Appearance;
+import javax.media.j3d.DirectionalLight;
+import javax.media.j3d.Geometry;
+import javax.media.j3d.GeometryArray;
+import javax.media.j3d.IndexedQuadArray;
+import javax.media.j3d.IndexedTriangleArray;
+import javax.media.j3d.IndexedTriangleFanArray;
+import javax.media.j3d.IndexedTriangleStripArray;
+import javax.media.j3d.Light;
+import javax.media.j3d.Material;
+import javax.media.j3d.Node;
+import javax.media.j3d.PointLight;
+import javax.media.j3d.PolygonAttributes;
+import javax.media.j3d.RenderingAttributes;
+import javax.media.j3d.Shape3D;
+import javax.media.j3d.Transform3D;
+import javax.media.j3d.TransparencyAttributes;
+import javax.media.j3d.TriangleFanArray;
+import javax.media.j3d.TriangleStripArray;
+import javax.vecmath.Point3d;
+import javax.vecmath.Point3f;
+import javax.vecmath.Vector3d;
+import javax.vecmath.Vector3f;
+
+import com.sun.j3d.utils.geometry.Box;
+import com.sun.j3d.utils.geometry.Cone;
+import com.sun.j3d.utils.geometry.Cylinder;
+import com.sun.j3d.utils.geometry.Sphere;
+
+/**
+ * �X�e���V���o�b�t�@��p�����V���h�E�{�����[��
+ * @author �V�c����
+ *
+ */
+public class ShadowVolume {
+ private static final boolean WIRE_FRAME_VIEW = false;
+
+ private Light light = null;
+ private double shadowDepth = 10.0;
+
+ private IndexedQuadArray volumeGeometry = null;
+ private Shape3D shadowVolumeFront = null;
+ private Shape3D shadowVolumeBack = null;
+
+ private int vertexCount = 0;
+ private double coordinates[] = null;
+ private int indicies[] = null;
+ private Hashtable edges = null;
+ private ArrayList triangles = null;
+
+ /**
+ * ���s�����p�̃V���h�E�{�����[��
+ * @param occuluder �Օ��I�u�W�F�N�g�i�e�𗎂Ƃ��I�u�W�F�N�g�j
+ * @param light ����
+ * @param shadowDepth �e�̐[��
+ * @param localToWorld �Օ��I�u�W�F�N�g�p�̍��W�ϊ�
+ */
+ public ShadowVolume(BaseObject3D occuluder, Light light, double shadowDepth,
+ Transform3D localToWorld) {
+ this.light = light;
+ this.shadowDepth = shadowDepth;
+
+ // ���̒��o
+ if (!extractGeometricInformation(occuluder)) return;
+
+ // �V���h�E�{�����[���̕\�ʂ�
+ volumeGeometry = createVolumeSurface(light, shadowDepth, localToWorld, coordinates, edges, triangles);
+
+ // �V���h�E�{�����[���I�u�W�F�N�g�̐���
+ createShadowVolumeObject(volumeGeometry, occuluder);
+ }
+
+ /**
+ * �V���h�E�{�����[���̍X�V
+ * @param localToWorld �Օ��I�u�W�F�N�g�p�̍��W�ϊ�
+ */
+ public void update(Transform3D localToWorld) {
+ // �V���h�E�{�����[���̕\�ʂ��Đ���
+ volumeGeometry = createVolumeSurface(light, shadowDepth, localToWorld, coordinates, edges, triangles);
+
+ // �V���h�E�{�����[���I�u�W�F�N�g�̍X�V
+ shadowVolumeFront.removeAllGeometries();
+ shadowVolumeFront.addGeometry(volumeGeometry);
+ shadowVolumeBack.removeAllGeometries();
+ shadowVolumeBack.addGeometry(volumeGeometry);
+ }
+
+ /**
+ * ���̒��o
+ * @param shadowCastingObject ���o���̃I�u�W�F�N�g
+ * @return true --- ����ɒ��o�ł���, false --- ����ɒ��o�ł��Ȃ�����
+ */
+ private boolean extractGeometricInformation(BaseObject3D shadowCastingObject) {
+ Node node = shadowCastingObject.getPrimitiveNode();
+ if (node == null) return false;
+ // GeometryArray�̏K��
+ ArrayList geometries = new ArrayList();
+ Geometry g = null;
+ if (node instanceof Shape3D) {
+ g = ((Shape3D)node).getGeometry();
+ geometries.add(g);
+ } else if (node instanceof Cone) {
+ g = ((Cone)node).getShape(Cone.BODY).getGeometry();
+ geometries.add(g);
+ g = ((Cone)node).getShape(Cone.CAP).getGeometry();
+ geometries.add(g);
+ } else if (node instanceof Cylinder) {
+ g = ((Cylinder)node).getShape(Cylinder.BODY).getGeometry();
+ geometries.add(g);
+ g = ((Cylinder)node).getShape(Cylinder.TOP).getGeometry();
+ geometries.add(g);
+ g = ((Cylinder)node).getShape(Cylinder.BOTTOM).getGeometry();
+ geometries.add(g);
+ } else if (node instanceof Box) {
+ g = ((Box)node).getShape(Box.TOP).getGeometry();
+ geometries.add(g);
+ g = ((Box)node).getShape(Box.BOTTOM).getGeometry();
+ geometries.add(g);
+ g = ((Box)node).getShape(Box.FRONT).getGeometry();
+ geometries.add(g);
+ g = ((Box)node).getShape(Box.BACK).getGeometry();
+ geometries.add(g);
+ g = ((Box)node).getShape(Box.LEFT).getGeometry();
+ geometries.add(g);
+ g = ((Box)node).getShape(Box.RIGHT).getGeometry();
+ geometries.add(g);
+ } else if (node instanceof Sphere) {
+ g = ((Sphere)node).getShape().getGeometry();
+ geometries.add(g);
+ } else {
+ return false;
+ }
+
+ // ���_�̍��W�l���擾���A�ݒ�
+ vertexCount = 0;
+ for (int n = 0; n < geometries.size(); n++) {
+ g = geometries.get(n);
+ if (g instanceof GeometryArray) {
+ // GeometryArray �̏ꍇ
+ GeometryArray geometryArray = (GeometryArray)g;
+ vertexCount += geometryArray.getVertexCount();
+ }
+ }
+ coordinates = new double[vertexCount * 3 * 2];
+ indicies = new int[vertexCount * 4 * 3]; // �ӂ̐��_�̐��̍ő�3�{�ƍl���Ă���
+ int base = 0;
+ for (int n = 0; n < geometries.size(); n++) {
+ g = geometries.get(n);
+ if (g instanceof GeometryArray) {
+ // GeometryArray �̏ꍇ
+ GeometryArray geometryArray = (GeometryArray)g;
+ double coordinate[] = new double[3];
+ int count = geometryArray.getVertexCount();
+ for (int v = 0; v < count; v++) {
+ geometryArray.getCoordinate(v, coordinate);
+ coordinates[(v + base) * 3] = coordinate[0];
+ coordinates[(v + base) * 3 + 1] = coordinate[1];
+ coordinates[(v + base) * 3 + 2] = coordinate[2];
+ }
+ base += count;
+ }
+ }
+
+ // �ʂƕӂ̏����쐬
+ edges = new Hashtable();
+ triangles = new ArrayList();
+ base = 0;
+ for (int n = 0; n < geometries.size(); n++) {
+ g = geometries.get(n);
+ if (g instanceof GeometryArray) {
+ // GeometryArray �̏ꍇ
+ GeometryArray geometryArray = (GeometryArray)g;
+ Point3d p1 = new Point3d();
+ Point3d p2 = new Point3d();
+ Point3d p3 = new Point3d();
+ int v1, v2, v3;
+ if (g instanceof TriangleStripArray) {
+ // TriangleStripArray �̏ꍇ
+ TriangleStripArray triStripArray = (TriangleStripArray)g;
+ int num = triStripArray.getNumStrips();
+ int strips[] = new int[num];
+ triStripArray.getStripVertexCounts(strips);
+ int index = base;
+ for (int j = 0; j < num; j++) {
+ index += 2;
+ for (int i = 2; i < strips[j]; i += 2) {
+ addTriangle(index - 2, index - 1, index, p1, p2, p3);
+ if (i <= strips[j] - 2) {
+ addTriangle(index - 1, index + 1, index, p1, p2, p3);
+ index += 1;
+ }
+ index += 1;
+ }
+ }
+ } else if (g instanceof TriangleFanArray) {
+ // TriangleFanArray �̏ꍇ
+ TriangleFanArray triFanArray = (TriangleFanArray)g;
+ int num = triFanArray.getNumStrips();
+ int strips[] = new int[num];
+ triFanArray.getStripVertexCounts(strips);
+ int index = base;
+ for (int j = 0; j < num; j++) {
+ v1 = index;
+ index += 1;
+ for (int i = 1; i < strips[j] - 1; i += 1) {
+ addTriangle(v1, index, index + 1, p1, p2, p3);
+ index += 1;
+ }
+ }
+ } else if (g instanceof IndexedTriangleArray) {
+ // IndexedTriangleArray �̏ꍇ
+ IndexedTriangleArray triArray = (IndexedTriangleArray)g;
+ int indexCount = triArray.getIndexCount();
+ for (int i = 0; i < indexCount; i += 3) {
+ v1 = triArray.getCoordinateIndex(i) + base;
+ v2 = triArray.getCoordinateIndex(i + 1) + base;
+ v3 = triArray.getCoordinateIndex(i + 2) + base;
+ addTriangle(v1, v2, v3, p1, p2, p3);
+ }
+ } else if (g instanceof IndexedTriangleStripArray) {
+ // IndexedTriangleStripArray �̏ꍇ
+ IndexedTriangleStripArray triStripArray = (IndexedTriangleStripArray)g;
+ int num = triStripArray.getNumStrips();
+ int strips[] = new int[num];
+ triStripArray.getStripIndexCounts(strips);
+ int index = 0;
+ for (int j = 0; j < num; j++) {
+ index += 2;
+ for (int i = 2; i < strips[j]; i += 2) {
+ v1 = triStripArray.getCoordinateIndex(index - 2) + base;
+ v2 = triStripArray.getCoordinateIndex(index - 1) + base;
+ v3 = triStripArray.getCoordinateIndex(index) + base;
+ addTriangle(v1,v2, v3, p1, p2, p3);
+ if (i <= strips[j] - 2) {
+ v1 = v2;
+ v2 = triStripArray.getCoordinateIndex(index + 1) + base;
+ addTriangle(v1, v2, v3, p1, p2, p3);
+ index += 1;
+ }
+ index += 1;
+ }
+ }
+ } else if (g instanceof IndexedTriangleFanArray) {
+ // IndexedTriangleFanArray �̏ꍇ
+ IndexedTriangleFanArray triFanArray = (IndexedTriangleFanArray)g;
+ int num = triFanArray.getNumStrips();
+ int strips[] = new int[num];
+ triFanArray.getStripIndexCounts(strips);
+ int index = 0;
+ for (int j = 0; j < num; j++) {
+ v1 = triFanArray.getCoordinateIndex(index) + base;
+ index += 1;
+ for (int i = 1; i < strips[j] - 1; i += 1) {
+ v2 = triFanArray.getCoordinateIndex(index) + base;
+ v3 = triFanArray.getCoordinateIndex(index + 1) + base;
+ addTriangle(v1, v2, v3, p1, p2, p3);
+ index += 1;
+ }
+ }
+ }
+ base += geometryArray.getVertexCount();
+ }
+ }
+ return true;
+ }
+
+ private void addTriangle(int v1, int v2, int v3, Point3d p1, Point3d p2, Point3d p3) {
+ Vector3d vec1;
+ Vector3d vec2;
+ Vector3d vec;
+ Triangle tri;
+ Edge e;
+ p1.x = coordinates[v1 * 3];
+ p1.y = coordinates[v1 * 3 + 1];
+ p1.z = coordinates[v1 * 3 + 2];
+ p2.x = coordinates[v2 * 3];
+ p2.y = coordinates[v2 * 3 + 1];
+ p2.z = coordinates[v2 * 3 + 2];
+ p3.x = coordinates[v3 * 3];
+ p3.y = coordinates[v3 * 3 + 1];
+ p3.z = coordinates[v3 * 3 + 2];
+ vec = new Vector3d(p1);
+ vec1 = new Vector3d(p2);
+ vec2 = new Vector3d(p3);
+ vec1.sub(vec);
+ vec2.sub(vec);
+ vec1.cross(vec1, vec2);
+ if (vec1.length() < GeometryUtility.TOLERANCE) {
+ return;
+ }
+ vec1.normalize();
+ tri = new Triangle(v1, v2, v3, vec1);
+ triangles.add(tri);
+ e = edges.get(new Integer(v2 * vertexCount + v1)); // �t�����ɉ���Ă���ӂ̂��L
+ if (e != null) {
+ tri.edges[0] = e;
+ e.triangles[1] = tri;
+ } else {
+ vec = new Vector3d(p2);
+ vec.sub(p1);
+ e = new Edge(v1, v2, vec);
+ tri.edges[0] = e;
+ e.triangles[0] = tri;
+ edges.put(new Integer(v1 * vertexCount + v2), e);
+ }
+ e = edges.get(new Integer(v3 * vertexCount + v2)); // �t�����ɉ���Ă���ӂ̂��L
+ if (e != null) {
+ tri.edges[1] = e;
+ e.triangles[1] = tri;
+ } else {
+ vec = new Vector3d(p3);
+ vec.sub(p2);
+ e = new Edge(v2, v3, vec);
+ tri.edges[1] = e;
+ e.triangles[0] = tri;
+ edges.put(new Integer(v2 * vertexCount + v3), e);
+ }
+ e = edges.get(new Integer(v1 * vertexCount + v3)); // �t�����ɉ���Ă���ӂ̂��L
+ if (e != null) {
+ tri.edges[2] = e;
+ e.triangles[1] = tri;
+ } else {
+ vec = new Vector3d(p1);
+ vec.sub(p3);
+ e = new Edge(v3, v1, vec);
+ tri.edges[2] = e;
+ e.triangles[0] = tri;
+ edges.put(new Integer(v3 * vertexCount + v1), e);
+ }
+ }
+
+ /**
+ * �V���h�E�{�����[���̃W�I���g���̍쐬
+ * @param light
+ * @param shadowDepth
+ * @param localToWorld
+ * @param coordinates
+ * @param edges
+ * @param triangles
+ * @return �V���h�E�{�����[���̃W�I���g��
+ */
+ private IndexedQuadArray createVolumeSurface(Light light, double shadowDepth, Transform3D localToWorld,
+ double[] coordinates, Hashtable edges, ArrayList triangles) {
+ // �I�u�W�F�N�g�ɑ��鑊���W�n�ɕϊ�
+ Vector3d displacement = null;
+ Point3d localLightPosition = null;
+ Transform3D worldToLocal;
+ Point3d worldLightPosition = null;
+ if (light instanceof DirectionalLight) {
+ // ���s�����̏ꍇ
+ Vector3f lightDirectionF = new Vector3f();
+ ((DirectionalLight)light).getDirection(lightDirectionF);
+ displacement = new Vector3d(lightDirectionF);
+ displacement.scale(shadowDepth);
+ worldToLocal = new Transform3D(localToWorld);
+ worldToLocal.invert();
+ worldToLocal.transform(displacement);
+ } else if (light instanceof PointLight) {
+ // �_�����̏ꍇ
+ Point3f worldLightPositionF = new Point3f();
+ ((PointLight)light).getPosition(worldLightPositionF);
+ worldLightPosition = new Point3d(worldLightPositionF);
+ localLightPosition = new Point3d(worldLightPosition);
+ worldToLocal = new Transform3D(localToWorld);
+ worldToLocal.invert();
+ worldToLocal.transform(localLightPosition);
+ } else {
+ return null;
+ }
+
+ Triangle tri;
+ // ���ׂĂ̖ʂ̌����ɑ���������v�Z
+ if (displacement != null) {
+ for (int n = 0; n < triangles.size(); n++) {
+ tri = triangles.get(n);
+ tri.innerProduct = tri.normal.dot(displacement);
+ }
+ } else if (localLightPosition != null) {
+ for (int n = 0; n < triangles.size(); n++) {
+ tri = triangles.get(n);
+ Vector3d v = new Vector3d(coordinates[tri.v1*3], coordinates[tri.v1*3 + 1], coordinates[tri.v1*3 + 2]);
+ v.sub(localLightPosition);
+ tri.innerProduct = tri.normal.dot(v);
+ }
+ }
+ Collection es = edges.values();
+ Edge edge;
+ int index = 0;
+ boolean doesGenerateSurface = false;
+ double i0 = 0, i1 = 0;
+ Vector3d displacement1 = displacement;
+ Vector3d displacement2 = displacement;
+ Vector3d tempVec = new Vector3d();
+ Point3d worldPos = new Point3d();
+ if (localLightPosition != null) {
+ // �_�����̏ꍇ
+ displacement1 = new Vector3d();
+ displacement2 = new Vector3d();
+ }
+ for (Iterator it = es.iterator(); it.hasNext(); ) {
+ edge = it.next();
+ // edge�ɑ��ăV���h�E�{�����[���̕\�ʂ����邩�ۂ��̔���
+ doesGenerateSurface = false;
+ if (edge.triangles[1] == null) {
+ // �J���ʑ̂̏ꍇ
+ i0 = edge.triangles[0].innerProduct;
+ if (i0 < -GeometryUtility.TOLERANCE) {
+ // �����ɑ��ĕ\�����̖ʂ̕ӂɑ��Ă̂ݐ���
+ doesGenerateSurface = true; // ��������
+ }
+ } else {
+ i0 = edge.triangles[0].innerProduct;
+ i1 = edge.triangles[1].innerProduct;
+ if (i0 * i1 < GeometryUtility.TOLERANCE) {
+ if (i0 * i1 > -GeometryUtility.TOLERANCE) {
+ // �ӂ����ނQ�̖ʂ̈���������̌����ɑ��ĕ��s�ł���
+ if (i0 < -GeometryUtility.TOLERANCE || i1 < -GeometryUtility.TOLERANCE) {
+ // �����ꂩ�̖ʂ��\�����������ꍇ
+ tempVec.cross(edge.triangles[0].normal, edge.triangles[1].normal);
+ if (edge.v1ToV2.dot(tempVec) > GeometryUtility.TOLERANCE) {
+ // �ӂ��ʂ̏ꍇ�̂ݐ���
+ doesGenerateSurface = true; // ��������
+ }
+ }
+ } else {
+ // �ӂ����ނQ�̖ʂ������̌����ɑ��ė��\�ł���
+ doesGenerateSurface = true; // ��������
+ }
+ }
+ }
+ if (doesGenerateSurface) {
+ // �V���h�E�{�����[���̕\�ʂ�����
+ if (localLightPosition != null) {
+ // �_�����̏ꍇ
+ displacement1.x = coordinates[edge.v1 * 3] - localLightPosition.x;
+ displacement1.y = coordinates[edge.v1 * 3 + 1] - localLightPosition.y;
+ displacement1.z = coordinates[edge.v1 * 3 + 2] - localLightPosition.z;
+ worldPos.x = coordinates[edge.v1 * 3];
+ worldPos.y = coordinates[edge.v1 * 3 + 1];
+ worldPos.z = coordinates[edge.v1 * 3 + 2];
+ localToWorld.transform(worldPos);
+ displacement1.scale(shadowDepth / worldPos.distance(worldLightPosition));
+ displacement2.x = coordinates[edge.v2 * 3] - localLightPosition.x;
+ displacement2.y = coordinates[edge.v2 * 3 + 1] - localLightPosition.y;
+ displacement2.z = coordinates[edge.v2 * 3 + 2] - localLightPosition.z;
+ worldPos.x = coordinates[edge.v2 * 3];
+ worldPos.y = coordinates[edge.v2 * 3 + 1];
+ worldPos.z = coordinates[edge.v2 * 3 + 2];
+ localToWorld.transform(worldPos);
+ displacement2.scale(shadowDepth / worldPos.distance(worldLightPosition));
+ }
+ if (i0 < -GeometryUtility.TOLERANCE) {
+ // �\�������Ă���ʂ�edge.triangles[0]�Aedge�̌����͏��edge.triangles[0]�̕ӂ̌����ƈ�v����̂ŁA
+ // edge�̌����ɏ]���ăV���h�E�{�����[���̕\�ʂ�
+ indicies[index] = edge.v2;
+ indicies[index + 1] = edge.v1;
+ indicies[index + 2] = edge.v1 + vertexCount;
+ indicies[index + 3] = edge.v2 + vertexCount;
+ } else {
+ // �\�������Ă���ʂ�edge.triangles[1]�Aedge�̌����͏��edge.triangles[1]�̕ӂ̌����Ɣ��Ȃ̂ŁA
+ // edge�̌����Ƌt�����ɃV���h�E�{�����[���̕\�ʂ�
+ indicies[index] = edge.v1;
+ indicies[index + 1] = edge.v2;
+ indicies[index + 2] = edge.v2 + vertexCount;
+ indicies[index + 3] = edge.v1 + vertexCount;
+ }
+ coordinates[(edge.v1 + vertexCount) * 3] = coordinates[edge.v1 * 3] + displacement1.x;
+ coordinates[(edge.v1 + vertexCount) * 3 + 1] = coordinates[edge.v1 * 3 + 1] + displacement1.y;
+ coordinates[(edge.v1 + vertexCount) * 3 + 2] = coordinates[edge.v1 * 3 + 2] + displacement1.z;
+ coordinates[(edge.v2 + vertexCount) * 3] = coordinates[edge.v2 * 3] + displacement2.x;
+ coordinates[(edge.v2 + vertexCount) * 3 + 1] = coordinates[edge.v2 * 3 + 1] + displacement2.y;
+ coordinates[(edge.v2 + vertexCount) * 3 + 2] = coordinates[edge.v2 * 3 + 2] + displacement2.z;
+ index += 4;
+ }
+ }
+ if (index == 0) return null;
+ int validIndicies[] = new int[index];
+ System.arraycopy(indicies, 0, validIndicies, 0, index);
+ volumeGeometry = new IndexedQuadArray(coordinates.length / 3,
+ IndexedQuadArray.COORDINATES | IndexedQuadArray.BY_REFERENCE,
+ index);
+ volumeGeometry.setCapability(IndexedQuadArray.ALLOW_COORDINATE_READ);
+ volumeGeometry.setCapability(IndexedQuadArray.ALLOW_COORDINATE_WRITE);
+ volumeGeometry.setCapability(IndexedQuadArray.ALLOW_COORDINATE_INDEX_READ);
+ volumeGeometry.setCapability(IndexedQuadArray.ALLOW_COORDINATE_INDEX_WRITE);
+
+ volumeGeometry.setCoordRefDouble(coordinates);
+ volumeGeometry.setCoordinateIndices(0, validIndicies);
+ return volumeGeometry;
+ }
+
+ /**
+ * �V���h�E�{�����[���̐���
+ * @param volumeGeometry
+ * @param ������������������
+ */
+ private void createShadowVolumeObject(IndexedQuadArray volumeGeometry, BaseObject3D ������������������) {
+ // �V���h�E�{�����[���̕\�ʂ̃I�u�W�F�N�g�̐���
+ Appearance frontAp = new Appearance();
+ if (WIRE_FRAME_VIEW) frontAp.setMaterial(new Material());
+ RenderingAttributes frontRA = new RenderingAttributes();
+ if (!WIRE_FRAME_VIEW) frontRA.setStencilEnable(true); // �X�e���V���o�b�t�@��p����i�������ACanvas3D�œK�Ȑݒ肪����Ă���K�v������j
+ if (!WIRE_FRAME_VIEW) frontRA.setDepthBufferWriteEnable(false); // Z�o�b�t�@���X�V���Ȃ�
+ frontRA.setDepthTestFunction(RenderingAttributes.LESS_OR_EQUAL); // Z�o�b�t�@�̉e������
+ frontRA.setStencilFunction(RenderingAttributes.ALWAYS, 0, ~0); // �X�e���V���o�b�t�@�̉e�����Ȃ�
+ frontRA.setStencilOp(RenderingAttributes.STENCIL_KEEP,
+ RenderingAttributes.STENCIL_KEEP,
+ RenderingAttributes.STENCIL_INCR); // �����Ă���s�N�Z���̂݃X�e���V���o�b�t�@�̒l�𑝂₷
+ frontAp.setRenderingAttributes(frontRA);
+ PolygonAttributes pa1 = new PolygonAttributes();
+ if (WIRE_FRAME_VIEW) pa1.setPolygonMode(PolygonAttributes.POLYGON_LINE);
+ pa1.setCullFace(PolygonAttributes.CULL_BACK); // ���ʂ��������Ȃ�
+ frontAp.setPolygonAttributes(pa1);
+ if (!WIRE_FRAME_VIEW) {
+ TransparencyAttributes frontTA = new TransparencyAttributes(); // setVisible(false)���ƃX�e���V���o�b�t�@���X�V����Ȃ��̂ŁA�����ɂ���
+ frontTA.setTransparencyMode(TransparencyAttributes.BLENDED);
+ frontTA.setTransparency(1.0f);
+ frontAp.setTransparencyAttributes(frontTA);
+ }
+ shadowVolumeFront = new Shape3D(volumeGeometry, frontAp);
+ shadowVolumeFront.setCapability(Shape3D.ALLOW_GEOMETRY_READ);
+ shadowVolumeFront.setCapability(Shape3D.ALLOW_GEOMETRY_WRITE);
+ ������������������.center.addChild(shadowVolumeFront);
+
+ // �V���h�E�{�����[���̗��ʂ̃I�u�W�F�N�g�̐���
+ Appearance backAp= new Appearance();
+ if (WIRE_FRAME_VIEW) backAp.setMaterial(new Material());
+ RenderingAttributes backRA= new RenderingAttributes();
+ if (!WIRE_FRAME_VIEW) backRA.setStencilEnable(true); // �X�e���V���o�b�t�@��p����i�������ACanvas3D�œK�Ȑݒ肪����Ă���K�v������j
+ if (!WIRE_FRAME_VIEW) backRA.setDepthBufferWriteEnable(false); // Z�o�b�t�@���X�V���Ȃ�
+ backRA.setDepthTestFunction(RenderingAttributes.LESS_OR_EQUAL); // Z�o�b�t�@�̉e������
+ backRA.setStencilFunction(RenderingAttributes.ALWAYS, 0, ~0); // �X�e���V���o�b�t�@�̉e�����Ȃ�
+ backRA.setStencilOp(RenderingAttributes.STENCIL_KEEP,
+ RenderingAttributes.STENCIL_KEEP,
+ RenderingAttributes.STENCIL_DECR); // �����Ă���s�N�Z���̂݃X�e���V���o�b�t�@�̒l�����炷
+ backAp.setRenderingAttributes(backRA);
+ PolygonAttributes pa2 = new PolygonAttributes();
+ if (WIRE_FRAME_VIEW) pa2.setPolygonMode(PolygonAttributes.POLYGON_LINE);
+ pa2.setCullFace(PolygonAttributes.CULL_FRONT); // �\�ʂ��������Ȃ�
+ backAp.setPolygonAttributes(pa2);
+ if (!WIRE_FRAME_VIEW) {
+ TransparencyAttributes backTA = new TransparencyAttributes(); // setVisible(false)���ƃX�e���V���o�b�t�@���X�V����Ȃ��̂ŁA�����ɂ���
+ backTA.setTransparencyMode(TransparencyAttributes.BLENDED);
+ backTA.setTransparency(1.0f);
+ backAp.setTransparencyAttributes(backTA);
+ }
+ shadowVolumeBack = new Shape3D(volumeGeometry, backAp);
+ shadowVolumeBack.setCapability(Shape3D.ALLOW_GEOMETRY_READ);
+ shadowVolumeBack.setCapability(Shape3D.ALLOW_GEOMETRY_WRITE);
+ ������������������.center.addChild(shadowVolumeBack);
+ }
+
+ private class Triangle {
+ Edge edges[] = new Edge[3];
+ Vector3d normal;
+ double innerProduct;
+ int v1, v2, v3;
+
+ Triangle(int v1, int v2, int v3, Vector3d normal) {
+ this.v1 = v1;
+ this.v2 = v2;
+ this.v3 = v3;
+ this.normal = normal;
+ }
+ }
+
+ private class Edge {
+ Triangle triangles[] = new Triangle[2];
+ int v1, v2;
+ Vector3d v1ToV2;
+// Vector3d normal = null;
+
+ Edge(int v1, int v2, Vector3d v1ToV2) {
+ this.v1 = v1;
+ this.v2 = v2;
+ this.v1ToV2 = v1ToV2;
+ }
+
+// Vector3d normal() {
+// if (normal != null) return normal;
+// normal = new Vector3d(triangles[0].normal);
+// if (triangles[1] != null) {
+// normal.add(triangles[1].normal);
+// normal.scale(0.5);
+// }
+// return normal;
+// }
+ }
+}
diff --git a/src/main/java/framework/model3D/ShadowVolumeVisitor.java b/src/main/java/framework/model3D/ShadowVolumeVisitor.java
new file mode 100644
index 0000000..b50ed96
--- /dev/null
+++ b/src/main/java/framework/model3D/ShadowVolumeVisitor.java
@@ -0,0 +1,70 @@
+package framework.model3D;
+
+import java.util.ArrayList;
+
+import javax.media.j3d.Light;
+import javax.media.j3d.Transform3D;
+import javax.vecmath.Vector3d;
+
+/**
+ * �V���h�E�{�����[���p�̃r�W�^�[
+ * @author Nitta
+ *
+ */
+public class ShadowVolumeVisitor extends ObjectVisitor {
+ private boolean bInitialize = true;
+ private ArrayList lights = null;
+ private double shadowDepth = 0;
+
+ /**
+ * �V���h�E�{�����[�����X�V����ꍇ
+ */
+ public ShadowVolumeVisitor() {
+ this.bInitialize = false;
+ Transform3D t = new Transform3D();
+ stackList.add(t);
+ }
+
+ /**
+ * �V���h�E�{�����[�����쐬����ꍇ
+ * @param lights ����
+ * @param shadowDepth �e�̐[��
+ */
+ public ShadowVolumeVisitor(ArrayList lights, double shadowDepth) {
+ this.lights = lights;
+ this.shadowDepth = shadowDepth;
+ this.bInitialize = true;
+ Transform3D t = new Transform3D();
+ stackList.add(t);
+ }
+
+ @Override
+ public void preVisit(Object3D obj) {
+ Transform3D t = new Transform3D(stackList.get(stackList.size() - 1));
+ Transform3D t2 = new Transform3D();
+ obj.pos.getTransform(t2);
+ t.mul(t2);
+ obj.rot.getTransform(t2);
+ t.mul(t2);
+ obj.scale.getTransform(t2);
+ t.mul(t2);
+ obj.center.getTransform(t2);
+ t.mul(t2);
+ stackList.add(t);
+ }
+
+ @Override
+ public void postVisit(Object3D obj) {
+ Transform3D t = stackList.remove(stackList.size() - 1);
+ if (!obj.hasChildren()) {
+ // �t�I�u�W�F�N�g�̏ꍇ�A�V���h�E�{�����[���̏���������
+ if (bInitialize) {
+ // �������̏ꍇ�A�V���h�E�{�����[���̐���
+ obj.createShadowVolume(lights, shadowDepth, t);
+ } else {
+ // �������łȂ��ꍇ�A�V���h�E�{�����[���̍X�V
+ obj.updateShadowVolume(t);
+ }
+ }
+ }
+}
diff --git a/src/main/java/framework/model3D/Terrain3D.java b/src/main/java/framework/model3D/Terrain3D.java
new file mode 100644
index 0000000..695bac1
--- /dev/null
+++ b/src/main/java/framework/model3D/Terrain3D.java
@@ -0,0 +1,466 @@
+package framework.model3D;
+
+import javax.media.j3d.Appearance;
+import javax.media.j3d.BoundingBox;
+import javax.media.j3d.Shape3D;
+import javax.media.j3d.IndexedTriangleStripArray;
+import javax.media.j3d.TriangleStripArray;
+import javax.vecmath.Point3d;
+import javax.vecmath.Vector3d;
+import javax.vecmath.Vector3f;
+
+/**
+ * ���b�V���ō\�����ꂽ�n�`�p�̃I�u�W�F�N�g�i�Փ˔��肪����������Ă���j
+ * @author �V�c����
+ *
+ */
+public class Terrain3D extends BaseObject3D {
+ static final int MESH_SIZE = 4;
+ private Position3D origin;
+ private double sizeX = 0;
+ private double sizeZ = 0;
+ private double heightMap[][] = null;
+ private int meshX = 0;
+ private int meshZ = 0;
+ private TriangleStripArray triStripAttay = null;
+
+ public Terrain3D(Position3D origin, double sizeX, double sizeZ, double heightMap[][], Appearance a) {
+ super();
+ this.origin = origin;
+ this.sizeX = sizeX;
+ this.sizeZ = sizeZ;
+ this.heightMap = heightMap;
+ meshX = heightMap[0].length;
+ meshZ = heightMap.length;
+
+ int stripVertexCounts[] = new int[meshZ - 1];
+ for (int n = 0; n < meshZ - 1; n++) {
+ stripVertexCounts[n] = meshX * 2;
+ }
+ triStripAttay = new TriangleStripArray(meshX * 2 * (meshZ - 1),
+ TriangleStripArray.COORDINATES | TriangleStripArray.NORMALS,
+ stripVertexCounts);
+ int index = 0;
+ for (int z = 0; z < meshZ; z++) {
+ for (int x = 0; x < meshX; x++) {
+ // ���b�V�����ƂɎO�p�`��2�Â���
+ if (z < meshZ - 1) {
+ // ���_���W�̐ݒ�
+ // ���_�̖@���x�N�g���̐ݒ�
+ triStripAttay.setCoordinate(index,
+ new Point3d(origin.getX() + sizeX * (double)x,
+ origin.getY() + heightMap[z][x],
+ origin.getZ() + sizeZ * (double)z));
+ Vector3f normal = calcNormal(z, x);
+ normal.normalize();
+ triStripAttay.setNormal(index, normal);
+
+ triStripAttay.setCoordinate(index + 1,
+ new Point3d(origin.getX() + sizeX * (double)x,
+ origin.getY() + heightMap[z + 1][x],
+ origin.getZ() + sizeZ * (double)(z + 1)));
+ normal = calcNormal(z + 1, x);
+ normal.normalize();
+ triStripAttay.setNormal(index + 1, normal);
+
+ index += 2;
+ }
+ }
+ }
+ Appearance a2 = (Appearance)a.cloneNodeComponent(true);
+ a2.setCapability(Appearance.ALLOW_MATERIAL_READ);
+ a2.setCapability(Appearance.ALLOW_TEXTURE_READ);
+ a2.setCapability(Appearance.ALLOW_TEXTURE_WRITE);
+ a2.setCapability(Appearance.ALLOW_TEXTURE_ATTRIBUTES_READ);
+ a2.setCapability(Appearance.ALLOW_TEXTURE_ATTRIBUTES_WRITE);
+ Shape3D shape = new Shape3D(triStripAttay, a2);
+ shape.setCapability(Shape3D.ALLOW_APPEARANCE_READ);
+ shape.setCapability(Shape3D.ALLOW_APPEARANCE_WRITE);
+ center.addChild(shape);
+ }
+
+ private Vector3f calcNormal(int z, int x) {
+ Vector3f normal = new Vector3f();
+ if (x < meshX - 1) {
+ Vector3f xp = new Vector3f((float)sizeX, (float)(heightMap[z][x+1] - heightMap[z][x]), 0.0f);
+ if (z < meshZ - 1) {
+ Vector3f zp = new Vector3f(0.0f, (float)(heightMap[z+1][x] - heightMap[z][x]), (float)sizeZ);
+ Vector3f v1 = new Vector3f();
+ v1.cross(zp, xp);
+ v1.normalize();
+ normal.add(v1);
+ }
+ if (z > 0) {
+ Vector3f zm = new Vector3f(0.0f, (float)(heightMap[z-1][x] - heightMap[z][x]), -(float)sizeZ);
+ Vector3f v1 = new Vector3f();
+ v1.cross(xp, zm);
+ v1.normalize();
+ normal.add(v1);
+ }
+ }
+ if (x > 0) {
+ Vector3f xm = new Vector3f(-(float)sizeX, (float)(heightMap[z][x-1] - heightMap[z][x]), 0.0f);
+ if (z < meshZ - 1) {
+ Vector3f zp = new Vector3f(0.0f, (float)(heightMap[z+1][x] - heightMap[z][x]), (float)sizeZ);
+ Vector3f v1 = new Vector3f();
+ v1.cross(xm, zp);
+ v1.normalize();
+ normal.add(v1);
+ }
+ if (z > 0) {
+ Vector3f zm = new Vector3f(0.0f, (float)(heightMap[z-1][x] - heightMap[z][x]), -(float)sizeZ);
+ Vector3f v1 = new Vector3f();
+ v1.cross(zm, xm);
+ v1.normalize();
+ normal.add(v1);
+ }
+ }
+ return normal;
+ }
+
+ /**
+ * �Փ˔���p�̃{�����[���i�|���S���Ƒe������p�̒����́j���擾����
+ * @return�@�Փ˔���p�̃{�����[����
+ */
+ public BoundingSurface[] getBoundingSurfaces() {
+ if (boundingSurfaces == null) {
+ if (triStripAttay == null) return null;
+ double coordinate1[] = new double[3];
+ double coordinate2[] = new double[3];
+ double coordinate3[] = new double[3];
+ double coordinate4[] = new double[3];
+
+ // GeometryArray�̏K��
+ if (triStripAttay instanceof TriangleStripArray) {
+ // IndexedTriangleStripArray �̏ꍇ
+ // 8 x 8 ���b�V���P�ʂł܂Ƃ߂�
+ BoundingSurface surfaces[] = new BoundingSurface[((meshX + MESH_SIZE - 2) / MESH_SIZE) * ((meshZ + MESH_SIZE - 2) / MESH_SIZE)];
+ int n = 0;
+ for (int j = 0; j < meshZ - 1; j += MESH_SIZE) {
+ for (int i = 0; i < meshX - 1; i += MESH_SIZE) {
+ BoundingSurface parent = new BoundingSurface();
+ double lowY = 1.0;
+ double highY = -1.0;
+ for (int j2 = 0; j + j2 < meshZ - 1 && j2 < MESH_SIZE; j2++) {
+ for (int i2 = 0; i + i2 < meshX - 1 && i2 < MESH_SIZE; i2++) {
+ int index = (j + j2) * meshX * 2 + (i + i2) * 2;
+ triStripAttay.getCoordinates(index, coordinate1);
+ triStripAttay.getCoordinates(index + 1, coordinate2);
+ triStripAttay.getCoordinates(index + 2, coordinate3);
+ triStripAttay.getCoordinates(index + 3, coordinate4);
+ if (lowY > highY) {
+ lowY = highY = coordinate1[1];
+ } else {
+ if (lowY > coordinate1[1]) {
+ lowY = coordinate1[1];
+ } else if (highY < coordinate1[1]) {
+ highY = coordinate1[1];
+ }
+ if (lowY > coordinate2[1]) {
+ lowY = coordinate2[1];
+ } else if (highY < coordinate2[1]) {
+ highY = coordinate2[1];
+ }
+ if (lowY > coordinate3[1]) {
+ lowY = coordinate3[1];
+ } else if (highY < coordinate3[1]) {
+ highY = coordinate3[1];
+ }
+ if (lowY > coordinate4[1]) {
+ lowY = coordinate4[1];
+ } else if (highY < coordinate4[1]) {
+ highY = coordinate4[1];
+ }
+ }
+
+ // 1 x 1 ���b�V������BoundingSurface
+ Vector3d v1 = new Vector3d(coordinate1);
+ Vector3d v2 = new Vector3d(coordinate2);
+ Vector3d v3 = new Vector3d(coordinate3);
+ Vector3d v4 = new Vector3d(coordinate4);
+ BoundingSurface bSurface = new BoundingSurface();
+ bSurface.addVertex((Vector3d)v1.clone()); //1�߂̎O�p�`
+ bSurface.addVertex((Vector3d)v2.clone());
+ bSurface.addVertex((Vector3d)v3.clone());
+ bSurface.setBounds(createBoundingPolytope(v1, v2, v3));
+ parent.addChild(bSurface, false);
+
+ bSurface = new BoundingSurface();
+ bSurface.addVertex((Vector3d)v2.clone()); //2�߂̎O�p�`
+ bSurface.addVertex((Vector3d)v4.clone());
+ bSurface.addVertex((Vector3d)v3.clone());
+ bSurface.setBounds(createBoundingPolytope(v2, v4, v3));
+ parent.addChild(bSurface, true);
+ }
+ }
+ // 8 x 8 ���b�V���P�ʂ�BoundingSurface
+ triStripAttay.getCoordinates(j * meshX * 2 + i * 2, coordinate1);
+ parent.setBounds(new BoundingBox(new Point3d(coordinate1[0], lowY, coordinate1[2]),
+ new Point3d(coordinate4[0], highY, coordinate4[2])));
+ surfaces[n] = parent;
+ n++;
+ }
+ }
+ boundingSurfaces = surfaces;
+ } else {
+ return null;
+ }
+ }
+ return boundingSurfaces;
+ }
+
+ public double getHeight(double x, double z) {
+ int i = (int)((x - origin.getX()) / sizeX);
+ int j = (int)((z - origin.getZ()) / sizeZ);
+ if (i >= meshX || i < 0 || j >= meshZ || j < 0) return 0.0;
+
+ int index = j * meshX * 2 + i * 2;
+ double coordinate1[] = new double[3];
+ double coordinate2[] = new double[3];
+ double coordinate3[] = new double[3];
+ double coordinate4[] = new double[3];
+ triStripAttay.getCoordinates(index, coordinate1);
+ triStripAttay.getCoordinates(index + 1, coordinate2);
+ triStripAttay.getCoordinates(index + 2, coordinate3);
+ triStripAttay.getCoordinates(index + 3, coordinate4);
+ Vector3d v1 = new Vector3d(coordinate1);
+ Vector3d v2 = new Vector3d(coordinate2);
+ Vector3d v3 = new Vector3d(coordinate3);
+ Vector3d v4 = new Vector3d(coordinate4);
+ Vector3d p1 = new Vector3d(x, 0.0, z);
+ Vector3d p2 = new Vector3d(x, 1.0, z);
+
+ double x2 = x - (double)i * sizeX - origin.getX();
+ double z2 = z - (double)j * sizeZ - origin.getZ();
+ if (x2 < GeometryUtility.TOLERANCE || (meshZ - z2) / x2 > meshZ / meshX) {
+ // 1�߂̎O�p�`��ʂ�ꍇ
+ Vector3d crossPoint = GeometryUtility.intersect(GeometryUtility.createPlane(v1, v2, v3), p1, p2);
+ return crossPoint.getY();
+ } else {
+ // 2�߂̎O�p�`��ʂ�ꍇ
+ Vector3d crossPoint = GeometryUtility.intersect(GeometryUtility.createPlane(v2, v4, v3), p1, p2);
+ return crossPoint.getY();
+ }
+ }
+}
+
+//
+// ********** IndexedTriangleStripArray ���g���o�[�W���� **********
+// (IndexedTriangleStripArray��p����ƃ�������ߖ�ł��邪�A�V�F�[�f�B���O���ł��Ȃ��̂Œ���)
+//
+//public class Terrain3D extends BaseObject3D {
+// static final int MESH_SIZE = 8;
+// private Position3D origin;
+// private double sizeX = 0;
+// private double sizeZ = 0;
+// private double heightMap[][] = null;
+// private int meshX = 0;
+// private int meshZ = 0;
+// private IndexedTriangleStripArray triStripAttay = null;
+//
+// public Terrain3D(Position3D origin, double sizeX, double sizeZ, double heightMap[][], Appearance a) {
+// super();
+// this.origin = origin;
+// this.sizeX = sizeX;
+// this.sizeZ = sizeZ;
+// this.heightMap = heightMap;
+// meshX = heightMap[0].length;
+// meshZ = heightMap.length;
+//
+// int stripVertexCounts[] = new int[meshZ - 1];
+// for (int n = 0; n < meshZ - 1; n++) {
+// stripVertexCounts[n] = meshX * 2;
+// }
+// triStripAttay = new IndexedTriangleStripArray(meshX * meshZ,
+// IndexedTriangleStripArray.COORDINATES | IndexedTriangleStripArray.NORMALS,
+// meshX * 2 * (meshZ - 1),
+// stripVertexCounts);
+// int index = 0, index2 = 0, i1, i2;
+// for (int z = 0; z < meshZ; z++) {
+// for (int x = 0; x < meshX; x++) {
+// // ���_���W�̐ݒ�
+// triStripAttay.setCoordinate(index,
+// new Point3d(origin.getX() + sizeX * (double)x,
+// origin.getY() + heightMap[z][x],
+// origin.getZ() + sizeZ * (double)z));
+// // ���_�̖@���x�N�g���̐ݒ�
+// Vector3f normal = new Vector3f();
+// if (x < meshX - 1) {
+// Vector3f xp = new Vector3f((float)sizeX, (float)(heightMap[z][x+1] - heightMap[z][x]), 0.0f);
+// if (z < meshZ - 1) {
+// Vector3f zp = new Vector3f(0.0f, (float)(heightMap[z+1][x] - heightMap[z][x]), (float)sizeZ);
+// Vector3f v1 = new Vector3f();
+// v1.cross(zp, xp);
+// v1.normalize();
+// normal.add(v1);
+// }
+// if (z > 0) {
+// Vector3f zm = new Vector3f(0.0f, (float)(heightMap[z-1][x] - heightMap[z][x]), -(float)sizeZ);
+// Vector3f v1 = new Vector3f();
+// v1.cross(xp, zm);
+// v1.normalize();
+// normal.add(v1);
+// }
+// }
+// if (x > 0) {
+// Vector3f xm = new Vector3f(-(float)sizeX, (float)(heightMap[z][x-1] - heightMap[z][x]), 0.0f);
+// if (z < meshZ - 1) {
+// Vector3f zp = new Vector3f(0.0f, (float)(heightMap[z+1][x] - heightMap[z][x]), (float)sizeZ);
+// Vector3f v1 = new Vector3f();
+// v1.cross(xm, zp);
+// v1.normalize();
+// normal.add(v1);
+// }
+// if (z > 0) {
+// Vector3f zm = new Vector3f(0.0f, (float)(heightMap[z-1][x] - heightMap[z][x]), -(float)sizeZ);
+// Vector3f v1 = new Vector3f();
+// v1.cross(zm, xm);
+// v1.normalize();
+// normal.add(v1);
+// }
+// }
+// normal.normalize();
+// triStripAttay.setNormal(index, normal);
+// index++;
+// // ���b�V�����ƂɎO�p�`��2�Â���
+// if (z < meshZ - 1) {
+// i1 = z * meshX + x;
+// i2 = (z + 1) * meshX + x;
+// triStripAttay.setCoordinateIndices(index2, new int[]{i1, i2});
+// index2 += 2;
+// }
+// }
+// }
+// Appearance a2 = (Appearance)a.cloneNodeComponent(true);
+// a2.setCapability(Appearance.ALLOW_MATERIAL_READ);
+// a2.setCapability(Appearance.ALLOW_TEXTURE_READ);
+// a2.setCapability(Appearance.ALLOW_TEXTURE_WRITE);
+// a2.setCapability(Appearance.ALLOW_TEXTURE_ATTRIBUTES_READ);
+// a2.setCapability(Appearance.ALLOW_TEXTURE_ATTRIBUTES_WRITE);
+// Shape3D shape = new Shape3D(triStripAttay, a2);
+// shape.setCapability(Shape3D.ALLOW_APPEARANCE_READ);
+// shape.setCapability(Shape3D.ALLOW_APPEARANCE_WRITE);
+// center.addChild(shape);
+// }
+//
+// public BoundingSurface[] getBoundingSurfaces() {
+// if (boundingSurfaces == null) {
+// if (triStripAttay == null) return null;
+// double coordinate1[] = new double[3];
+// double coordinate2[] = new double[3];
+// double coordinate3[] = new double[3];
+// double coordinate4[] = new double[3];
+//
+// // GeometryArray�̏K��
+// if (triStripAttay instanceof IndexedTriangleStripArray) {
+// // IndexedTriangleStripArray �̏ꍇ
+// // 8 x 8 ���b�V���P�ʂł܂Ƃ߂�
+// BoundingSurface surfaces[] = new BoundingSurface[((meshX + MESH_SIZE - 2) / MESH_SIZE) * ((meshZ + MESH_SIZE - 2) / MESH_SIZE)];
+// int n = 0;
+// for (int j = 0; j < meshZ - 1; j += MESH_SIZE) {
+// for (int i = 0; i < meshX - 1; i += MESH_SIZE) {
+// BoundingSurface parent = new BoundingSurface();
+// double lowY = 1.0;
+// double highY = -1.0;
+// for (int j2 = 0; j + j2 < meshZ - 1 && j2 < MESH_SIZE; j2++) {
+// for (int i2 = 0; i + i2 < meshX - 1 && i2 < MESH_SIZE; i2++) {
+// int index = (j + j2) * meshX * 2 + (i + i2) * 2;
+// triStripAttay.getCoordinates(triStripAttay.getCoordinateIndex(index), coordinate1);
+// triStripAttay.getCoordinates(triStripAttay.getCoordinateIndex(index+1), coordinate2);
+// triStripAttay.getCoordinates(triStripAttay.getCoordinateIndex(index+2), coordinate3);
+// triStripAttay.getCoordinates(triStripAttay.getCoordinateIndex(index+3), coordinate4);
+// if (lowY > highY) {
+// lowY = highY = coordinate1[1];
+// } else {
+// if (lowY > coordinate1[1]) {
+// lowY = coordinate1[1];
+// } else if (highY < coordinate1[1]) {
+// highY = coordinate1[1];
+// }
+// if (lowY > coordinate2[1]) {
+// lowY = coordinate2[1];
+// } else if (highY < coordinate2[1]) {
+// highY = coordinate2[1];
+// }
+// if (lowY > coordinate3[1]) {
+// lowY = coordinate3[1];
+// } else if (highY < coordinate3[1]) {
+// highY = coordinate3[1];
+// }
+// if (lowY > coordinate4[1]) {
+// lowY = coordinate4[1];
+// } else if (highY < coordinate4[1]) {
+// highY = coordinate4[1];
+// }
+// }
+//
+// // 1 x 1 ���b�V������BoundingSurface
+// Vector3d v1 = new Vector3d(coordinate1);
+// Vector3d v2 = new Vector3d(coordinate2);
+// Vector3d v3 = new Vector3d(coordinate3);
+// Vector3d v4 = new Vector3d(coordinate4);
+// BoundingSurface bSurface = new BoundingSurface();
+// bSurface.addVertex((Vector3d)v1.clone()); //1�߂̎O�p�`
+// bSurface.addVertex((Vector3d)v2.clone());
+// bSurface.addVertex((Vector3d)v3.clone());
+// bSurface.setBounds(createBoundingPolytope(v1, v2, v3));
+// parent.addChild(bSurface, false);
+//
+// bSurface = new BoundingSurface();
+// bSurface.addVertex((Vector3d)v2.clone()); //2�߂̎O�p�`
+// bSurface.addVertex((Vector3d)v4.clone());
+// bSurface.addVertex((Vector3d)v3.clone());
+// bSurface.setBounds(createBoundingPolytope(v2, v4, v3));
+// parent.addChild(bSurface, true);
+// }
+// }
+// // 8 x 8 ���b�V���P�ʂ�BoundingSurface
+// triStripAttay.getCoordinates(triStripAttay.getCoordinateIndex(j * meshX * 2 + i * 2), coordinate1);
+// parent.setBounds(new BoundingBox(new Point3d(coordinate1[0], lowY, coordinate1[2]),
+// new Point3d(coordinate4[0], highY, coordinate4[2])));
+// surfaces[n] = parent;
+// n++;
+// }
+// }
+// boundingSurfaces = surfaces;
+// } else {
+// return null;
+// }
+// }
+// return boundingSurfaces;
+// }
+//
+// public double getHeight(double x, double z) {
+// int i = (int)((x - origin.getX()) / sizeX);
+// int j = (int)((z - origin.getZ()) / sizeZ);
+// if (i >= meshX || i < 0 || j >= meshZ || j < 0) return 0.0;
+//
+// int index = j * meshX * 2 + i * 2;
+// double coordinate1[] = new double[3];
+// double coordinate2[] = new double[3];
+// double coordinate3[] = new double[3];
+// double coordinate4[] = new double[3];
+// triStripAttay.getCoordinates(triStripAttay.getCoordinateIndex(index), coordinate1);
+// triStripAttay.getCoordinates(triStripAttay.getCoordinateIndex(index+1), coordinate2);
+// triStripAttay.getCoordinates(triStripAttay.getCoordinateIndex(index+2), coordinate3);
+// triStripAttay.getCoordinates(triStripAttay.getCoordinateIndex(index+3), coordinate4);
+// Vector3d v1 = new Vector3d(coordinate1);
+// Vector3d v2 = new Vector3d(coordinate2);
+// Vector3d v3 = new Vector3d(coordinate3);
+// Vector3d v4 = new Vector3d(coordinate4);
+// Vector3d p1 = new Vector3d(x, 0.0, z);
+// Vector3d p2 = new Vector3d(x, 1.0, z);
+//
+// double x2 = x - (double)i * sizeX - origin.getX();
+// double z2 = z - (double)j * sizeZ - origin.getZ();
+// if (x2 < GeometryUtility.TOLERANCE || (meshZ - z2) / x2 > meshZ / meshX) {
+// // 1�߂̎O�p�`��ʂ�ꍇ
+// Vector3d crossPoint = GeometryUtility.intersect(GeometryUtility.createPlane(v1, v2, v3), p1, p2);
+// return crossPoint.getY();
+// } else {
+// // 2�߂̎O�p�`��ʂ�ꍇ
+// Vector3d crossPoint = GeometryUtility.intersect(GeometryUtility.createPlane(v2, v4, v3), p1, p2);
+// return crossPoint.getY();
+// }
+// }
+//}
diff --git a/src/main/java/framework/model3D/UndoBuffer.java b/src/main/java/framework/model3D/UndoBuffer.java
new file mode 100644
index 0000000..aad37c7
--- /dev/null
+++ b/src/main/java/framework/model3D/UndoBuffer.java
@@ -0,0 +1,50 @@
+package framework.model3D;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Hashtable;
+
+
+
+public class UndoBuffer {
+
+ @SuppressWarnings("unchecked")
+ private ArrayList> list = new ArrayList>();
+ @SuppressWarnings("unchecked")
+ private Hashtable nowCondition = new Hashtable();
+ private static final int max = 3;
+
+ UndoBuffer() {
+ }
+
+ UndoBuffer(UndoBuffer another) {
+ this.list = (ArrayList>)another.list.clone();
+ this.nowCondition = (Hashtable)another.nowCondition.clone();
+ }
+
+ public void push(Property3D p) {
+ nowCondition.put(p.getClass(), p.clone());
+ }
+
+ @SuppressWarnings("unchecked")
+ public void setUndoMark() {
+ if(list.size() == max) {
+ list.remove(max - 1);
+ }
+ list.add(0, (Hashtable) nowCondition.clone());
+ }
+
+ @SuppressWarnings("unchecked")
+ public Collection undo() {
+ if(list.size() != 0) {
+ nowCondition = list.remove(0);
+ return nowCondition.values();
+ }
+ else {
+ return new Hashtable().values();
+ }
+ }
+
+ public void clear() {
+
+ }
+}
diff --git a/src/main/java/framework/model3D/Universe.java b/src/main/java/framework/model3D/Universe.java
new file mode 100644
index 0000000..e52c392
--- /dev/null
+++ b/src/main/java/framework/model3D/Universe.java
@@ -0,0 +1,415 @@
+package framework.model3D;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Stack;
+
+import javax.media.j3d.Appearance;
+import javax.media.j3d.BranchGroup;
+import javax.media.j3d.Light;
+import javax.media.j3d.Locale;
+import javax.media.j3d.Material;
+import javax.media.j3d.Node;
+import javax.media.j3d.RenderingAttributes;
+import javax.media.j3d.Transform3D;
+import javax.media.j3d.TransformGroup;
+import javax.media.j3d.VirtualUniverse;
+import javax.vecmath.Color3f;
+
+
+
+/**
+ * �e�A���˃}�b�s���O�A�o���v�}�b�s���O�Ȃǂ������_�����O�ł��� SimpleUniverse
+ * �i���ׂĂ̕��̂�z�u������ɁA�K�� compile() ���ĂȂ��Ƃ����Ȃ����Ƃɒ��ӁI�j
+ * @author �V�c����
+ *
+ */
+public class Universe extends VirtualUniverse {
+ private Locale locale = null;
+ private BranchGroup root = null;
+ private BranchGroup additionalRoot = null;
+ private ArrayList lights = new ArrayList();
+ private BackgroundBox skyBox = null;
+// private ArrayList backgrounds = new ArrayList();
+ private double shadowDepth = 100.0;
+ private ArrayList occluders = new ArrayList();
+ private ArrayList shadows = new ArrayList();
+ private ArrayList receivers = new ArrayList();
+ private ArrayList extraObjects = new ArrayList();
+
+ public Universe() {
+ super();
+ locale = new Locale(this);
+ root = new BranchGroup();
+ additionalRoot = new BranchGroup();
+ additionalRoot.setCapability(BranchGroup.ALLOW_CHILDREN_EXTEND);
+ additionalRoot.setCapability(BranchGroup.ALLOW_CHILDREN_READ);
+ additionalRoot.setCapability(BranchGroup.ALLOW_CHILDREN_WRITE);
+ shadowDepth = 100.0;
+ }
+
+ /**
+ * ���f���̃��[�g��ݒ肷��
+ * @param root
+ */
+ public void setRoot(BranchGroup root) {
+ removeRoot();
+ this.root = root;
+ }
+
+ /**
+ * ���f���̃��[�g���擾����
+ * @return ���f���̃��[�g�ɑ������� SceneGraph
+ */
+ public BranchGroup getRoot() {
+ return root;
+ }
+
+ /**
+ * ���f���̃��[�g���폜����
+ */
+ public void removeRoot() {
+ if (root == null) return;
+ Enumeration branchGroups = locale.getAllBranchGraphs();
+ while (branchGroups.hasMoreElements()) {
+ if (branchGroups.nextElement() == root) {
+ locale.removeBranchGraph(root);
+ root = null;
+ break;
+ }
+ }
+ }
+
+ public void addBranchGraph(BranchGroup g) {
+ locale.addBranchGraph(g);
+ }
+
+ /**
+ * �I�u�W�F�N�g��z�u����
+ * @param obj �z�u����I�u�W�F�N�g
+ */
+ public void place(Node obj) {
+ if (!root.isCompiled()) {
+ root.addChild(obj);
+ } else {
+ additionalRoot.addChild(obj);
+ }
+ }
+
+ /**
+ * �I�u�W�F�N�g��z�u����
+ * @param obj �z�u����I�u�W�F�N�g
+ */
+ public void place(Placeable obj) {
+ BaseObject3D body = obj.getBody();
+ if (body.isReflectionMappingApplied() || body.isBumpMappingApplied()) {
+ extraObjects.add(body);
+ } else {
+ place(obj.getTransformGroupToPlace());
+ }
+ }
+
+ /**
+ * ��Ŏ�菜����悤�ɃI�u�W�F�N�g��z�u����
+ * @param obj �z�u����I�u�W�F�N�g
+ */
+ public void placeDisplacable(Node obj) {
+ BranchGroup objRoot;
+ if (obj.getParent() != null
+ && obj.getParent() instanceof BranchGroup) {
+ objRoot = (BranchGroup)obj.getParent();
+ } else {
+ objRoot = new BranchGroup();
+ objRoot.setCapability(BranchGroup.ALLOW_DETACH);
+ objRoot.addChild(obj);
+ }
+ additionalRoot.addChild(objRoot);
+ }
+
+ /**
+ * ��Ŏ�菜����悤�ɃI�u�W�F�N�g��z�u����
+ * @param obj �z�u����I�u�W�F�N�g
+ */
+ public void placeDisplacable(Placeable obj) {
+ BaseObject3D body = obj.getBody();
+ if (body != null && (body.isReflectionMappingApplied() || body.isBumpMappingApplied())) {
+ extraObjects.add(body);
+ } else {
+ placeDisplacable(obj.getTransformGroupToPlace());
+ }
+ }
+
+ /**
+ * �e�t���Ŕz�u����
+ * @param obj �z�u����I�u�W�F�N�g
+ */
+ public void placeAsAnOcculuder(Placeable obj) {
+ BaseObject3D body = obj.getBody();
+ if (body instanceof Object3D) {
+ addShadowOcculuder((Object3D)body);
+ } else {
+ place(obj);
+ }
+ }
+
+ /**
+ * ���̃I�u�W�F�N�g�̉e��������悤�ɃI�u�W�F�N�g��z�u����
+ * @param obj �z�u����I�u�W�F�N�g
+ */
+ public void placeAsAReceiver(Placeable obj) {
+ addShadowReceiver(obj.getBody(), new Color3f(0.5f, 0.5f, 0.5f));
+ }
+
+ /**
+ * ���̃I�u�W�F�N�g�̉e��������悤�ɃI�u�W�F�N�g��\������
+ * @param obj �\������I�u�W�F�N�g
+ * @param shadowColor �e�̐F
+ */
+ public void placeAsAReceiver(Placeable obj, Color3f shadowColor) {
+ addShadowReceiver(obj.getBody(), shadowColor);
+ }
+
+ /**
+ * �����̒lj�
+ * @param light �lj��������
+ */
+ public void placeLight(Light light) {
+ root.addChild(light);
+ getLights().add((Light)light.cloneTree());
+ }
+
+ /**
+ * �����̒lj��i�e���j
+ * @param light �lj��������
+ * @param shadowDepth �e�̐[��
+ */
+ public void placeLight(Light light, double shadowDepth) {
+ root.addChild(light);
+ getLights().add((Light)light.cloneTree());
+ this.shadowDepth = shadowDepth;
+ }
+
+ /**
+ * �X�J�C�{�b�N�X�̒lj�
+ * @param skyBox �lj�����X�J�C�{�b�N�X
+ */
+ public void placeSkyBox(BackgroundBox skyBox) {
+ root.addChild(skyBox);
+ this.skyBox = skyBox;
+ }
+
+ /**
+ * �I�u�W�F�N�g���\�Ȃ�Ύ�菜��
+ * @param obj ��菜���I�u�W�F�N�g
+ */
+ public void displace(Node obj) {
+ Node parent = obj.getParent();
+ if (parent == root) return;
+ if (parent == additionalRoot) {
+ additionalRoot.removeChild(obj);
+ } else if (parent instanceof BranchGroup
+ && parent.getCapability(BranchGroup.ALLOW_DETACH)
+ && parent.getParent() == additionalRoot) {
+ additionalRoot.removeChild(parent);
+ }
+ }
+
+ /**
+ * �I�u�W�F�N�g���\�Ȃ�Ύ�菜��
+ * @param obj ��菜���I�u�W�F�N�g
+ */
+ public void displace(Placeable obj) {
+ BaseObject3D body = obj.getBody();
+ if (occluders.contains(body)) {
+ occluders.remove(body);
+ }
+ if (shadows.contains(body)) {
+ shadows.remove(body);
+ }
+ if (receivers.contains(body)) {
+ receivers.remove(body);
+ }
+ if (extraObjects.contains(body)) {
+ extraObjects.remove(body);
+ }
+ displace(obj.getTransformGroupToPlace());
+ }
+
+ public ArrayList getLights() {
+ return lights;
+ }
+
+ public BackgroundBox getSkyBox() {
+ return skyBox;
+ }
+
+ private void addShadowOcculuder(Object3D occluder) {
+// occluder.view(this); // occluder ���g�̕\��
+ ShadowVolumeVisitor shadowVolumeVisitor =
+ new ShadowVolumeVisitor(getLights(), shadowDepth); // ShadowVolume �̐���
+ occluder.accept(shadowVolumeVisitor); // occluder ������ ShadowVolume ���ێ������
+ occluders.add(occluder);
+ }
+
+ private void addShadowReceiver(BaseObject3D receiverObject, Color3f shadowColor) {
+ BaseObject3D receiverObjectBody = receiverObject.duplicate();
+
+ // ���� BaseObject3D ���e�\���p�ɂ���
+ ArrayList aps = receiverObject.getAppearances();
+ Material m = new Material();
+ m.setDiffuseColor(shadowColor); // �e�̐F
+ m.setAmbientColor(0.0f, 0.0f, 0.0f);
+ m.setSpecularColor(0.0f, 0.0f, 0.0f);
+ m.setShininess(1.0f);
+ RenderingAttributes ra = new RenderingAttributes();
+ ra.setStencilEnable(false); // �X�e���V���o�b�t�@���g��Ȃ�
+ ra.setDepthBufferWriteEnable(true); // �ʏ�ʂ�Z�o�b�t�@�ɏ�������
+ ra.setDepthTestFunction(RenderingAttributes.LESS_OR_EQUAL); // �ʏ�ʂ�Z�o�b�t�@�Ŕ��肷��
+ for (int n = 0; n < aps.size(); n++) {
+ Appearance ap = aps.get(n);
+ ap.setMaterial(m);
+ ap.setRenderingAttributes(ra);
+ }
+
+ shadows.add(receiverObject);
+
+ // �������� BaseObject3D ��ʏ�\���p�i�������e�̕����͕`�悵�Ȃ��j�ɂ���
+ ArrayList aps2 = receiverObjectBody.getAppearances();
+ RenderingAttributes ra2 = new RenderingAttributes();
+ ra2.setStencilEnable(true); // �X�e���V���o�b�t�@���g��
+ ra2.setDepthBufferWriteEnable(true);
+ ra2.setDepthTestFunction(RenderingAttributes.LESS_OR_EQUAL); // �e�̏�ɏ㏑������
+ ra2.setStencilFunction(RenderingAttributes.GREATER_OR_EQUAL, 0, ~0); // �X�e���V���o�b�t�@�̒l��1�ȏ�̂Ƃ��`�悵�Ȃ�
+ ra2.setStencilOp(RenderingAttributes.STENCIL_REPLACE, // �X�e���V���o�b�t�@���N���A����
+ RenderingAttributes.STENCIL_REPLACE,
+ RenderingAttributes.STENCIL_REPLACE);
+// TransparencyAttributes ta2 = new TransparencyAttributes();
+// ta2.setTransparencyMode(TransparencyAttributes.BLENDED);
+// ta2.setTransparency(0.0001f);
+ for (int n = 0; n < aps2.size(); n++) {
+ Appearance ap2 = aps2.get(n);
+ ap2.setRenderingAttributes(ra2);
+// ap2.setTransparencyAttributes(ta2);
+ }
+
+ receivers.add(receiverObjectBody);
+ }
+
+ public void update() {
+ ShadowVolumeVisitor shadowVolumeVisitor =
+ new ShadowVolumeVisitor(); // ShadowVolume �� �X�V
+ for (int n = 0; n < occluders.size(); n++) {
+ occluders.get(n).accept(shadowVolumeVisitor);
+ }
+ }
+
+ /**
+ * Mixed���[�h�����_�����O��p���ĉe�̕`����s��
+ * �i�e��������I�u�W�F�N�g�i���V�[�o�j�̉e�����A�V���h�E�{�����[���j
+ * @param graphicsContext3D
+ */
+ public void preRender(IViewer3D viewer) {
+ update();
+
+ viewer.update(lights, skyBox);
+ }
+
+ /**
+ * Mixed���[�h�����_�����O��p���ĉe�̕`����s��
+ * �i�e��������I�u�W�F�N�g�̉e�ȊO�̕����j
+ * @param graphicsContext3D
+ */
+ public void renderField(IViewer3D viewer) {
+ // ������ �����_�����O�͈ȉ��̏��Ԃł������܂������Ȃ� ������
+ // ���Ƃ��A�V���h�E�{�����[���������_�����O������Ƀ��V�[�o�̉e�ȊO�̕����������_�����O����ƁA
+ // BackgroundBox�̕`�悪�Ȃ��������Ȃ��Ă��܂��B
+
+ // 1. ���V�[�o�̉e����
+ Transform3D trans = new Transform3D();
+ for (int n = 0; n < shadows.size(); n++) {
+ BaseObject3D obj = shadows.get(n);
+ if (obj instanceof Object3D) {
+ ((Object3D)obj).accept(new ObjectRenderer(viewer));
+ } else {
+ obj.center.getTransform(trans);
+ viewer.setModelTransform(trans);
+ viewer.draw(obj);
+ }
+ }
+
+ // 2. ���V�[�o�̉e�ȊO�̕���
+ for (int n = 0; n < receivers.size(); n++) {
+ BaseObject3D obj = receivers.get(n);
+ if (obj instanceof Object3D) {
+ ((Object3D)obj).accept(new ObjectRenderer(viewer));
+ } else {
+ obj.center.getTransform(trans);
+ viewer.setModelTransform(trans);
+ viewer.draw(obj);
+ }
+ }
+
+ // 3. �V���h�E�{�����[���̕\�ʁiocculuder�����ɐς�ł���j
+ // 4. �V���h�E�{�����[���̗��ʁiocculuder�����ɐς�ł���j
+ for (int n = 0; n < occluders.size(); n++) {
+ Object3D occuluder = occluders.get(n);
+ occuluder.accept(new ObjectRenderer(viewer));
+ }
+
+ // ����ȃ����_�����O���K�v�ƂȂ�I�u�W�F�N�g
+ for (int n = 0; n < extraObjects.size(); n++) {
+ BaseObject3D extra = extraObjects.get(n);
+ if (extra instanceof Object3D) {
+ ((Object3D)extra).accept(new ObjectRenderer(viewer));
+ } else {
+ extra.center.getTransform(trans);
+ viewer.setModelTransform(trans);
+ viewer.draw(extra);
+ }
+ }
+ }
+
+ public void postRender(IViewer3D viewer) {
+ }
+
+ public void compile() {
+ root.compile();
+ locale.addBranchGraph(root);
+ locale.addBranchGraph(additionalRoot);
+ }
+
+ private class ObjectRenderer extends ObjectVisitor {
+ Stack transforms = new Stack();
+ IViewer3D viewer = null;
+
+ public ObjectRenderer(IViewer3D viewer) {
+ Transform3D t = new Transform3D();
+ transforms.push(t);
+ this.viewer = viewer;
+ }
+
+ @Override
+ public void preVisit(Object3D obj) {
+ Transform3D t = new Transform3D(transforms.peek());
+ Transform3D t2 = new Transform3D();
+ obj.pos.getTransform(t2);
+ t.mul(t2);
+ obj.rot.getTransform(t2);
+ t.mul(t2);
+ obj.scale.getTransform(t2);
+ t.mul(t2);
+ obj.center.getTransform(t2);
+ t.mul(t2);
+ transforms.push(t);
+ }
+
+ @Override
+ public void postVisit(Object3D obj) {
+ Transform3D t = transforms.pop();
+ if (!obj.hasChildren()) {
+ viewer.setModelTransform(t);
+ viewer.draw(obj);
+ }
+ }
+ }
+}
diff --git a/src/main/java/framework/physics/AngularVelocity3D.java b/src/main/java/framework/physics/AngularVelocity3D.java
new file mode 100644
index 0000000..97b1c02
--- /dev/null
+++ b/src/main/java/framework/physics/AngularVelocity3D.java
@@ -0,0 +1,85 @@
+package framework.physics;
+import javax.vecmath.AxisAngle4d;
+import javax.vecmath.Vector3d;
+
+import framework.model3D.Object3D;
+import framework.model3D.Property3D;
+
+
+public class AngularVelocity3D extends Property3D{
+ private double x;
+ private double y;
+ private double z;
+
+ public AngularVelocity3D(AngularVelocity3D w) {
+ x = w.x;
+ y = w.y;
+ z = w.z;
+ }
+
+ public AngularVelocity3D(double x,double y,double z){
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+
+ public AngularVelocity3D(){
+ x = 0.0;
+ y = 0.0;
+ z = 0.0;
+ }
+
+ public void applyTo(Object3D o){
+ ((Solid3D)o).setAngularVelocity(this);
+ }
+
+ public double getX() {
+ // TODO Auto-generated method stub
+ return this.x;
+ }
+
+ public double getY() {
+ // TODO Auto-generated method stub
+ return this.y;
+ }
+
+ public double getZ() {
+ // TODO Auto-generated method stub
+ return this.z;
+ }
+
+ public AngularVelocity3D add(double x, double y, double z){
+ this.x += x;
+ this.y += y;
+ this.z += z;
+ return this;
+ }
+
+ public AngularVelocity3D add(Vector3d v) {
+ // TODO Auto-generated method stub
+ this.x += v.x;
+ this.y += v.y;
+ this.z += v.z;
+ return this;
+ }
+
+ public Vector3d getVector3d(){
+ return new Vector3d(x,y,z);
+ }
+
+ public AxisAngle4d getAxisAngle4d() {
+ double l = getVector3d().length();
+ if (l <= 0.00001) {
+ return new AxisAngle4d(0, 0, 1.0, 0.0);
+ }
+ return new AxisAngle4d(x / l, y / l, z / l, l);
+ }
+
+ @Override
+ public Property3D clone() {
+ // TODO Auto-generated method stub
+ return new AngularVelocity3D(this);
+ }
+}
+
+
diff --git a/src/main/java/framework/physics/BoundingBoxVisitor.java b/src/main/java/framework/physics/BoundingBoxVisitor.java
new file mode 100644
index 0000000..735aa51
--- /dev/null
+++ b/src/main/java/framework/physics/BoundingBoxVisitor.java
@@ -0,0 +1,93 @@
+package framework.physics;
+import java.util.ArrayList;
+
+import javax.media.j3d.BoundingSphere;
+
+import framework.model3D.OBB;
+import framework.model3D.Object3D;
+import framework.model3D.ObjectVisitor;
+
+
+public class BoundingBoxVisitor extends ObjectVisitor {
+ private ArrayList obbList = new ArrayList