001: /*
002: * Apollo - Motion capture and animation system
003: * Copyright (c) 2005 Apollo
004: *
005: * This program is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU General Public License
007: * as published by the Free Software Foundation; either version 2
008: * of the License, or (at your option) any later version.
009: *
010: * This program is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
013: * GNU General Public License for more details.
014: *
015: * You should have received a copy of the GNU General Public License
016: * along with this program; if not, write to the Free Software
017: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
018: *
019: * http://www.gnu.org/copyleft/gpl.html
020: *
021: * @author Giovane.Kuhn - brain@netuno.com.br
022: *
023: */
024: package org.apollo.trackmodel;
025:
026: import java.util.ArrayList;
027: import java.util.List;
028:
029: import javax.vecmath.Vector3d;
030:
031: import org.apollo.bvh.Joint;
032: import org.apollo.datamodel.EffectingVideo;
033: import org.apollo.datamodel.Marker;
034: import org.apollo.datamodel.TrackingFrame;
035: import org.apollo.datamodel.TrackingJoint;
036: import org.apollo.datamodel.TrackingVideo;
037:
038: /**
039: * Class calculate global position for joints accepted by the model plan
040: * and that has markers in the frame, cause of this is called truth calculator
041: */
042: public final class MarkerBasedPositioner extends AbstractPositioner {
043:
044: /** Cache with effecting video markers */
045: private final MarkerCache markerCache;
046:
047: public MarkerBasedPositioner(EffectingVideo effectVideo,
048: TrackingVideo video) {
049: super (video);
050: this .markerCache = new MarkerCache(effectVideo);
051: }
052:
053: public synchronized void track(TrackingFrame frame) {
054: this .actualTrackFrame = frame;
055: modelRoot.visit(this );
056: }
057:
058: public boolean accept(Joint node) {
059: // analyze just joint accepted by the plan
060: if (!plan.getModelVisitor().accept(node)) {
061: return false;
062: }
063:
064: // cannot exists tracking joint for current node
065: TrackingJoint tnode = actualTrackFrame.getTrackingJoint(node
066: .getName());
067: if (tnode != null) {
068: return true;
069: }
070:
071: // first tracking joint
072: TrackingJoint firstTrackJoint = firstTrackFrame
073: .getTrackingJoint(node.getName());
074: assert firstTrackJoint != null;
075:
076: // calculate truth position
077: if (!firstTrackJoint.isSimulated()) {
078: tnode = calculate(node, firstTrackJoint);
079: }
080:
081: // if succed on creating a new tracking joint
082: if (tnode != null) {
083: tnode.setName(firstTrackJoint.getName());
084: actualTrackFrame.addTrackingJoint(tnode);
085: }
086:
087: return true;
088: }
089:
090: /**
091: * Calculate position for new tracking joint,
092: * based on its linked markers
093: * @param node Model joint to calculate
094: * @param firstJoint Tracking joint at first frame
095: * @return New tracking joint
096: */
097: private TrackingJoint calculate(Joint node, TrackingJoint firstJoint) {
098:
099: // fill a list with joint linked markers at current frame
100: List<Marker> markersInFrame = new ArrayList<Marker>();
101: for (Marker m : firstJoint.getMarkers()) {
102: Marker temp = markerCache.getMarker(actualTrackFrame
103: .getSequence(), m.getColor());
104: if (temp == null) {
105: continue;
106: }
107: markersInFrame.add(temp);
108: }
109:
110: // try to find unidentified markers near the model joint
111: if (markersInFrame.isEmpty()) {
112:
113: // TODO this code will be made by the position simulator, I hope
114: return null;
115: }
116:
117: // simulate missing some markers
118: if (markersInFrame.size() != firstJoint.getMarkers().size()) {
119: // TODO code this logic
120: }
121:
122: // calculate from all markers
123: // TODO improve below code
124: // using just one marker ?!?!?
125:
126: // actual marker
127: Marker actualMarker = markersInFrame.get(0);
128: Vector3d actualMarkerVec = plan.transformVector(actualMarker
129: .getVector3d());
130:
131: // first marker
132: Marker firstMarker = markerCache.getMarker(0, actualMarker
133: .getColor());
134: Vector3d firstMarkerVec = plan.transformVector(firstMarker
135: .getVector3d());
136:
137: // get model and first frame vector
138: Vector3d firstVec = firstJoint.getVector3d();
139:
140: // calculate offset between frames
141: Vector3d offsetVec = new Vector3d();
142: offsetVec.sub(actualMarkerVec, firstMarkerVec);
143:
144: // calculate new global coordinates
145: Vector3d retVec = new Vector3d();
146: retVec.add(firstVec, offsetVec);
147:
148: // create new tracking joint
149: TrackingJoint ret = new TrackingJoint();
150: ret.setName(node.getName());
151:
152: // TODO one axis is fixed, this can be improved
153: ret.setVector3d(firstJoint.fillUnspecifiedCoordinates(retVec));
154: return ret;
155: }
156: }
|