📄 jointcontroller.java
字号:
* @param start
* The starting frame number.
* @param end
* The ending frame number.
*/
public void setTimes(int start, int end) {
if (start < 0
|| start > end
|| movementInfo.get(movementInfo.size() - 1).time < end
/ FPS) {
String message = "Malformed times: start="
+ start
+ " end="
+ end
+ " start limit: 0 End limit: "
+ movementInfo.get(movementInfo.size() - 1).time
* FPS;
throw new JmeException(message);
}
setMinTime(start / FPS);
setMaxTime(end / FPS);
curTime = getMinTime();
curTimePoint = 1;
movingForward = true;
}
/**
* Used with update(float). <code>updateData</code> moves every normal and
* vertex acording to its jointIndex
*/
private void updateData() {
for (int currentGroup = 0; currentGroup < movingMeshes.size(); currentGroup++) {
JointMesh updatingGroup = movingMeshes
.get(currentGroup);
int currentBoneIndex;
FloatBuffer verts = updatingGroup.getVertexBuffer();
FloatBuffer normals = updatingGroup.getNormalBuffer();
int j;
for (j = 0; j < updatingGroup.jointIndex.length; j++) {
currentBoneIndex = updatingGroup.jointIndex[j];
if (currentBoneIndex == -1) continue;
unSyncbeginPos.set(updatingGroup.originalVertex[j]);
BufferUtils.setInBuffer(jointMovements[currentBoneIndex]
.multPoint(unSyncbeginPos), verts, j);
unSyncbeginPos.set(updatingGroup.originalNormal[j]);
BufferUtils.setInBuffer(jointMovements[currentBoneIndex]
.multNormal(unSyncbeginPos), normals, j);
}
if (j != 0) {
if (updatePerFrame) updatingGroup.updateModelBound();
}
}
}
/**
* Used with update(float) to combine joints with their inverse to properly
* translate points.
*/
private void combineWithInverse() {
for (int i = 0; i < numJoints; i++)
jointMovements[i].multLocal(inverseChainMatrix[i], unSyncbeginPos);
}
/**
* Processes a JointController by filling holes and creating inverse
* matrixes. Should only be called once per JointController object lifetime
*/
public void processController() {
if (movementInfo.size() == 1) { // IE no times were added or only time 0
// was added
movementInfo.add(0, new PointInTime(0));
}
setMinTime(movementInfo.get(0).time);
setMaxTime(movementInfo.get(movementInfo.size() - 1).time);
curTime = getMinTime();
invertWithParents();
fillHoles();
}
/**
* If true, the model's bounding volume will be updated every frame. If
* false, it will not.
*
* @param update
* The new update model volume per frame value.
*/
public void setModelUpdate(boolean update) {
updatePerFrame = update;
}
/**
* Returns true if the model's bounding volume is being updated every frame.
*
* @return True if bounding volume is updating.
*/
public boolean getModelUpdate() {
return updatePerFrame;
}
/**
* Inverts joints with their parents. Only called once per JointController
* lifetime during processing.
*/
private void invertWithParents() {
for (int i = 0; i < numJoints; i++) {
inverseChainMatrix[i] = new TransformMatrix(localRefMatrix[i]);
inverseChainMatrix[i].inverse();
if (parentIndex[i] != -1)
inverseChainMatrix[i].multLocal(
inverseChainMatrix[parentIndex[i]], unSyncbeginPos);
}
}
/**
* Called with update to create the needed joint transforms for that point
* in time.
*
* @param changeAmnt
* The % diffrence (from 0-1) between two points in time
*/
private void createJointTransforms(float changeAmnt) {
PointInTime now = movementInfo.get(curTimePoint);
PointInTime then = movementInfo.get(curTimePoint - 1);
for (int index = 0; index < numJoints; index++) {
int theParentIndex = parentIndex[index];
unSyncbeginAngle.set(then.jointRotation[index]);
unSyncbeginPos.set(then.jointTranslation[index]);
unSyncbeginAngle.slerp(now.jointRotation[index], changeAmnt);
unSyncbeginPos.interpolate(now.jointTranslation[index], changeAmnt);
tempUnSyncd.set(unSyncbeginAngle, unSyncbeginPos);
jointMovements[index].set(localRefMatrix[index]);
jointMovements[index].multLocal(tempUnSyncd, unSyncbeginPos);
if (theParentIndex != -1) {
tempUnSyncd.set(jointMovements[index]);
jointMovements[index].set(jointMovements[theParentIndex]);
jointMovements[index].multLocal(tempUnSyncd, unSyncbeginPos);
}
}
}
/**
* Fills null rotations and translations for any joint at any point in time.
*/
private void fillHoles() {
fillRots();
fillTrans();
}
/**
* Gives every PointInTime for every joint a valid rotation.
*/
private void fillRots() {
for (int joint = 0; joint < numJoints; joint++) {
// 1) Find first non-null rotation of joint <code>joint</code>
int start;
for (start = 0; start < movementInfo.size(); start++) {
if (movementInfo.get(start).jointRotation[joint] != null)
break;
}
if (start == movementInfo.size()) { // if they are all null then
// fill with identity
for (int i = 0; i < movementInfo.size(); i++)
movementInfo.get(i).jointRotation[joint] = new Quaternion();
continue; // we're done with this joint so lets continue
}
if (start != 0) { // if there -are- null elements at the begining,
// then fill with first non-null
unSyncbeginAngle
.set(movementInfo.get(start).jointRotation[joint]);
for (int i = 0; i < start; i++)
movementInfo.get(i).jointRotation[joint] = new Quaternion(
unSyncbeginAngle);
}
int lastgood = start;
boolean allGood = true;
for (int i = start + 2; i < movementInfo.size(); i++) {
if (movementInfo.get(i).jointRotation[joint] != null) {
fillQuats(joint, lastgood, i); // fills gaps
lastgood = i;
allGood = false;
}
}
if (!allGood && lastgood != movementInfo.size() - 1) { // fills tail
movementInfo.get(movementInfo.size() - 1).jointRotation[joint] = new Quaternion(
movementInfo.get(lastgood).jointRotation[joint]);
fillQuats(joint, lastgood, movementInfo.size() - 1); // fills
// tail
}
}
}
/**
* Gives every PointInTime for every joint a valid translation.
*/
private void fillTrans() {
for (int joint = 0; joint < numJoints; joint++) {
// 1) Find first non-null translation of joint <code>joint</code>
int start;
for (start = 0; start < movementInfo.size(); start++) {
if (movementInfo.get(start).jointTranslation[joint] != null)
break;
}
if (start == movementInfo.size()) { // if they are all null then
// fill with identity
for (int i = 0; i < movementInfo.size(); i++)
movementInfo.get(i).jointTranslation[joint] = new Vector3f(
0, 0, 0);
continue; // we're done with this joint so lets continue
}
if (start != 0) { // if there -are- null elements at the begining,
// then fill with first non-null
unSyncbeginPos
.set(movementInfo.get(start).jointTranslation[joint]);
for (int i = 0; i < start; i++)
movementInfo.get(i).jointTranslation[joint] = new Vector3f(
unSyncbeginPos);
}
int lastgood = start;
boolean allGood = true;
for (int i = start + 2; i < movementInfo.size(); i++) {
if (movementInfo.get(i).jointTranslation[joint] != null) {
fillPos(joint, lastgood, i); // fills gaps
lastgood = i;
allGood = false;
}
}
if (!allGood && lastgood != movementInfo.size() - 1) { // fills tail
movementInfo.get(movementInfo.size() - 1).jointTranslation[joint] = new Vector3f(
movementInfo.get(lastgood).jointTranslation[joint]);
fillPos(joint, lastgood, movementInfo.size() - 1); // fills tail
}
}
}
/**
* Interpolates missing quats that weren't specified to the JointController.
*
* @param jointIndex
* Index of the joint that has missing quats
* @param startRotIndex
* Begining index of a valid non-null quat
* @param endRotIndex
* Ending index of a valid non-null quat
*/
private void fillQuats(int jointIndex, int startRotIndex, int endRotIndex) {
unSyncbeginAngle
.set(movementInfo.get(startRotIndex).jointRotation[jointIndex]);
for (int i = startRotIndex + 1; i < endRotIndex; i++) {
movementInfo.get(i).jointRotation[jointIndex] = new Quaternion(
unSyncbeginAngle);
movementInfo.get(i).jointRotation[jointIndex]
.slerp(
movementInfo.get(endRotIndex).jointRotation[jointIndex],
((float) i - startRotIndex)
/ (endRotIndex - startRotIndex));
}
}
/**
* Interpolates missing vector that weren't specified to the
* JointController.
*
* @param jointIndex
* Index of the joint that has missing vector
* @param startPosIndex
* Begining index of a valid non-null vector
* @param endPosIndex
* Ending index of a valid non-null vector
*/
private void fillPos(int jointIndex, int startPosIndex, int endPosIndex) {
unSyncbeginPos
.set(movementInfo.get(startPosIndex).jointTranslation[jointIndex]);
for (int i = startPosIndex + 1; i < endPosIndex; i++) {
movementInfo.get(i).jointTranslation[jointIndex] = new Vector3f(
unSyncbeginPos);
movementInfo.get(i).jointTranslation[jointIndex]
.interpolate(
movementInfo.get(endPosIndex).jointTranslation[jointIndex],
((float) i - startPosIndex)
/ (endPosIndex - startPosIndex));
}
}
/**
* Adds a jointmesh for this JointController to consider animating.
*
* @param child
* Child JointMesh to consider
*/
public void addJointMesh(JointMesh child) {
movingMeshes.add(child);
}
public void write(JMEExporter e) throws IOException {
super.write(e);
OutputCapsule capsule = e.getCapsule(this);
capsule.write(numJoints, "numJoints", 0);
capsule.writeSavableArrayList(movementInfo, "movementInfo", new ArrayList<PointInTime>());
capsule.write(parentIndex, "parentIndex", new int[numJoints]);
capsule.write(localRefMatrix, "localRefMatrix", new TransformMatrix[numJoints]);
capsule.write(FPS, "FPS", 0);
capsule.writeSavableArrayList(movingMeshes, "movingMeshes", new ArrayList<JointMesh>());
capsule.write(jointMovements, "jointMovements", new TransformMatrix[numJoints]);
capsule.write(skipRate, "skipRate", 0);
capsule.write(updatePerFrame, "updatePerFrame", false);
capsule.write(movingForward, "movingForward", false);
}
@SuppressWarnings("unchecked")
public void read(JMEImporter e) throws IOException {
super.read(e);
InputCapsule capsule = e.getCapsule(this);
numJoints = capsule.readInt("numJoints", 0);
movementInfo = capsule.readSavableArrayList("movementInfo", new ArrayList<PointInTime>());
parentIndex = capsule.readIntArray("parentIndex", new int[numJoints]);
Savable[] savs = capsule.readSavableArray("localRefMatrix", new TransformMatrix[numJoints]);
if (savs == null)
localRefMatrix = null;
else {
localRefMatrix = new TransformMatrix[savs.length];
for (int x = 0; x < savs.length; x++) {
localRefMatrix[x] = (TransformMatrix)savs[x];
}
}
savs = capsule.readSavableArray("jointMovements", new TransformMatrix[numJoints]);
if (savs == null)
jointMovements = null;
else {
jointMovements = new TransformMatrix[savs.length];
for (int x = 0; x < savs.length; x++) {
jointMovements[x] = (TransformMatrix)savs[x];
}
}
FPS = capsule.readFloat("FPS", 0);
movingMeshes = capsule.readSavableArrayList("movingMeshes", new ArrayList<JointMesh>());
skipRate = capsule.readFloat("skipRate", 0);
updatePerFrame = capsule.readBoolean("updatePerFrame", false);
movingForward = capsule.readBoolean("movingForward", false);
inverseChainMatrix = new TransformMatrix[numJoints];
for (int i = 0; i < numJoints; i++) {
inverseChainMatrix[i] = new TransformMatrix();
}
processController();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -