[openwonderland-avatars] r1290 committed - Fix for avatar collision issue

1 view
Skip to first unread message

openwonderl...@googlecode.com

unread,
Sep 2, 2014, 2:55:02 AM9/2/14
to openwonder...@googlegroups.com
Revision: 1290
Author: abhishek...@wishtreetech.com
Date: Tue Sep 2 06:54:49 2014 UTC
Log: Fix for avatar collision issue
https://code.google.com/p/openwonderland-avatars/source/detail?r=1290

Modified:
/trunk/src/imi/character/avatar/AvatarController.java
/trunk/src/imi/character/statemachine/GameContext.java
/trunk/src/imi/character/statemachine/corestates/IdleState.java

=======================================
--- /trunk/src/imi/character/avatar/AvatarController.java Mon Mar 19
18:34:12 2012 UTC
+++ /trunk/src/imi/character/avatar/AvatarController.java Tue Sep 2
06:54:49 2014 UTC
@@ -1,3 +1,7 @@
+/**
+ * Copyright (c) 2014, WonderBuilders, Inc., All Rights Reserved
+ */
+
/**
* Open Wonderland
*
@@ -42,18 +46,27 @@
import imi.character.CharacterController;
import imi.collision.CollisionController;
import imi.collision.TransformUpdateManager;
+
+import com.jme.intersection.CollisionData;
+import org.jdesktop.mtgame.CollisionDetails;
+import org.jdesktop.mtgame.JMECollisionDetails;
+import com.jme.math.Triangle;
+import com.jme.scene.TriMesh;
+
import imi.scene.PMatrix;
import imi.scene.PTransform;
import imi.scene.polygonmodel.PPolygonModelInstance;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
-import javax.swing.JFrame;
import org.jdesktop.mtgame.CollisionInfo;
import org.jdesktop.mtgame.PickDetails;
import org.jdesktop.mtgame.PickInfo;
import org.jdesktop.wonderland.common.ExperimentalAPI;

+import java.util.Timer;
+import java.util.TimerTask;
+
/**
* Concrete character controller.
* Controls the avatar according to internal and external actions.
@@ -66,6 +79,19 @@
@ExperimentalAPI
public class AvatarController extends CharacterController
{
+ protected class SetCollidingTask extends TimerTask
+ {
+ private AvatarController aController = null;
+
+ SetCollidingTask(AvatarController controller) {
+ this.aController = controller;
+ }
+
+ public void run() {
+ this.aController.setColliding(false);
+ }
+ }
+
/** The avatar being controller **/
private Avatar avatar = null;
/** True if initialization has completed **/
@@ -109,6 +135,11 @@

private PMatrix currentRot = new PMatrix();

+ /** Timer and task for calling setColliding() to prevent dead
reckoning to be used during collisions **/
+ private Timer collisionTimer = new Timer();
+ private SetCollidingTask collisionTask = null;
+ private long collisionTimerDelay = 1000;
+
/** Collision Controller **/
private CollisionController collisionController = null;

@@ -142,6 +173,7 @@
initalized = true;
}

+ //collisionTask = new SetCollidingTask(this);
// Diagnostic / Debug output

Logger.getLogger(AvatarController.class.getName()).log(Level.INFO, "GOT
BODY " + body);
}
@@ -282,11 +314,7 @@
velocity.multLocal(scale);

// Apply Velocity
- Vector3f position =
body.getTransform().getLocalMatrix(false).getTranslation();
- if (bReverseHeading)
- position.addLocal(velocity.mult(-deltaTime));
- else
- position.addLocal(velocity.mult(deltaTime));
+ Vector3f position =
applyVelocity(body.getTransform().getLocalMatrix(false).getTranslation(),
deltaTime);

if (Float.isNaN(position.x)) {
if (!nanReported) {
@@ -363,31 +391,49 @@
}
}

- // now that all position updates have been applied, check for
- // collision at the current position. If there is no collision
- // controller, collision status may be set externally
- if (collisionController != null) {
- if (collisionCheck(position, currentRot) &&
- collisionController.isCollisionResponseEnabled())
- {
- setColliding(true);
- } else {
- setColliding(false);
+ Vector3f correction = new Vector3f();
+ // Check for collisions and if necessary apply correction to
velocity
+ if(collisionController != null &&
collisionController.isCollisionResponseEnabled()
&& !velocity.equals(Vector3f.ZERO)) {
+ correction = collisionCheck(previousPos, position, currentRot,
velocity);
+
+ // If no collision was found, try again in movement mid point
+ if(correction.equals(Vector3f.ZERO)) {
+ Vector3f midPos =
previousPos.add(position.subtract(previousPos).divide(2.0f));
+ correction = collisionCheck(previousPos, midPos,
currentRot, velocity);
+ }
+
+ if(!correction.equals(Vector3f.ZERO)) {
+ velocity.addLocal(correction);
+ setCollidingInternal();
}
}

- // apply collision if one was detected
- if (isColliding()) {
- position.set(previousPos);
- currentRot.set(previousRot);
+ // Apply velocity again if collision was detected
+ if (isColliding())
+ {
+ position = applyVelocity(previousPos, deltaTime);

- // no change in height
- gravityHeight = getHeight();
+ // Apply new gravity
+ if(collisionController != null &&
collisionController.isGravityEnabled())
+ gravityHeight = calculateHeight(position);
+ else {
+
avatar.getJScene().setExternalKidsRootPosition(previousPos,
previousRot.getRotationJME());
+ return;
+ }
}

// update final height
setHeight(gravityHeight);

+ // update the position.y
+ if (gravityHeight != 0.0F) {
+ if (gravityHeight > this.gravityAcc.y) {
+ position.y -= this.gravityAcc.y;
+ } else {
+ position.y -= gravityHeight;
+ }
+ }
+
TransformUpdateManager transformUpdateManager =
(TransformUpdateManager)
avatar.getWorldManager().getUserData(TransformUpdateManager.class);
if(bUseTransformUpdateManager && transformUpdateManager != null)
{
@@ -438,27 +484,85 @@
return 0f;
}

- private boolean collisionCheck(Vector3f potentialPos, PMatrix
potentialRot) {
- boolean collision = false;
+ ////// Checks for collision and returns velocity correction if found
+ private Vector3f collisionCheck(Vector3f previousPos, Vector3f
potentialPos, PMatrix potentialRot, Vector3f currentVel) {
Spatial collisionGraph = collisionController.getCollisionGraph();
collisionGraph.setLocalTranslation(potentialPos.x, potentialPos.y,
potentialPos.z);
collisionGraph.setLocalRotation(potentialRot.getRotationJME());
collisionGraph.updateGeometricState(0, true);

+ float coefRestitution = 0.0f;
+ Vector3f correction = new Vector3f();
+
+
// For high quality avatars need to transform the boxes that
enclose the body parts
// int jointIndex = skeleton.getSkinnedMeshJointIndex(jointName)
gets the int index of a joint (cache the jointIndex, recompute if avatar
changes)
// SkinnedMeshJoint specificJoint =
skeleton.getSkinnedMeshJoint(jointIndex);
// specificJoint.getTransform().getWorldMatrix(false)

CollisionInfo collisionInfo =
collisionController.getCollisionSystem().findAllCollisions(collisionGraph,
true);
- if (collisionInfo.size() != 0) {
- collision = true;
-// System.err.println("OUCH ! "+tris.size());
-// TriMesh mesh =
(TriMesh)tcr.getCollisionData(i).getSourceMesh();
- //computeCollisionResponse(position, potentialPos,
rotatedFwdDirection, triData2, walkInc);
+ if(collisionInfo.size() > 0) {
notifyCollisionListeners(collisionInfo);
+ Vector3f normal = new Vector3f();
+
+ // Get normals for all collisions detected
+ for(int index = 0; index < collisionInfo.size(); index++) {
+ CollisionDetails details = collisionInfo.get(index);
+ CollisionData data = ((JMECollisionDetails)
details).getPickData();
+
+ if(data != null) {
+ normal.addLocal(getCollisionNormal(data));
}
- return collision;
+ }
+
+ normal.normalizeLocal();
+
+ float normalVelMag = normal.dot(currentVel);
+
+ // Moving away from the collision
+ if(normalVelMag > 0) {
+ return correction;
+ }
+
+ Vector3f normalVel = normal.mult(normalVelMag);
+ correction = normalVel.mult(-(1 + coefRestitution));
+ }
+
+ return correction;
+ }
+
+ private Vector3f getCollisionNormal(CollisionData data) {
+ Vector3f normal = new Vector3f();
+
+ TriMesh mesh = (TriMesh) data.getTargetMesh();
+ Triangle[] triangles = mesh.getMeshAsTriangles(null);
+ ArrayList<Integer> triIndex = data.getTargetTris();
+
+ for(Integer i : triIndex) {
+ Triangle t = triangles[i];
+ t.calculateNormal();
+
+ Vector3f n =
data.getTargetMesh().getLocalRotation().mult(t.getNormal());
+ n.y = 0;
+
+ float dot = n.dot(velocity.normalize());
+
+ if(dot <= 0)
+ normal.addLocal(n);
+ }
+
+ return normal.normalizeLocal();
+ }
+
+ ////// Applies current velocity to given position
+ private Vector3f applyVelocity(Vector3f position, float deltaTime)
+ {
+ if (bReverseHeading)
+ position.addLocal(velocity.mult(-deltaTime));
+ else
+ position.addLocal(velocity.mult(deltaTime));
+
+ return position;
}

public void addCollisionListener(AvatarCollisionListener listener) {
@@ -507,6 +611,19 @@
protected synchronized void setColliding(boolean colliding) {
this.bColliding = colliding;
}
+
+ protected synchronized void setCollidingInternal() {
+ if(!isColliding()) {
+ setColliding(true);
+ }
+
+ if(collisionTask != null) {
+ collisionTask.cancel();
+ }
+
+ collisionTask = new SetCollidingTask(this);
+ collisionTimer.schedule(collisionTask, collisionTimerDelay);
+ }

public Vector3f getGravity() {
return gravity;
@@ -698,4 +815,8 @@
{
return bUseTransformUpdateManager;
}
+
+ public boolean isGravityEnable() {
+ return this.collisionController.isGravityEnabled();
+ }
}
=======================================
--- /trunk/src/imi/character/statemachine/GameContext.java Mon Jun 27
19:03:18 2011 UTC
+++ /trunk/src/imi/character/statemachine/GameContext.java Tue Sep 2
06:54:49 2014 UTC
@@ -1,3 +1,7 @@
+/**
+ * Copyright (c) 2014, WonderBuilders, Inc., All Rights Reserved
+ */
+
/**
* Open Wonderland
*
@@ -38,6 +42,7 @@
import imi.character.CharacterController;
import imi.character.behavior.CharacterBehaviorManager;
import imi.character.statemachine.GameState.Action;
+import imi.character.statemachine.corestates.transitions.FlyToIdle;
import imi.scene.animation.AnimationListener.AnimationMessageType;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -129,7 +134,13 @@

Object bool = null;
try {
- bool = method.invoke(state, transition.getStateMessageArgs());
+ //fix for the page down issue.
+ if(transition instanceof FlyToIdle) {
+ transition.setStateMessageArgs(transition.toString());
+ bool = method.invoke(state,
transition.getStateMessageArgs());
+ } else {
+ bool = method.invoke(state,
transition.getStateMessageArgs());
+ }
} catch (IllegalAccessException ex) {
logger.log(Level.SEVERE, null, ex);
} catch (IllegalArgumentException ex) {
=======================================
--- /trunk/src/imi/character/statemachine/corestates/IdleState.java Mon Jun
27 19:03:18 2011 UTC
+++ /trunk/src/imi/character/statemachine/corestates/IdleState.java Tue
Sep 2 06:54:49 2014 UTC
@@ -1,3 +1,7 @@
+/**
+ * Copyright (c) 2014, WonderBuilders, Inc., All Rights Reserved
+ */
+
/**
* Open Wonderland
*
@@ -76,9 +80,15 @@
*/
public boolean toIdle(Object data)
{
- if (context.getController().getVelocityScalar() <
velocityThreshhold)
+ // fix for page down issue.
+ if(data!=null &&
((AvatarController)context.getController()).isGravityEnable()) {
return true;
- return false;
+ } else {
+ if (context.getController().getVelocityScalar() <
velocityThreshhold) {
+ return true;
+ }
+ return false;
+ }
}

private void takeAction(float deltaTime)
Reply all
Reply to author
Forward
0 new messages