IK Test 3
クリックで回ります。
/**
* Copyright hycro ( http://wonderfl.net/user/hycro )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/oqvNz
*/
// クリックで回ります。
package {
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Vector3D;
import flash.ui.Mouse;
import flash.ui.MouseCursor;
import net.hires.debug.Stats;
import org.papervision3d.core.geom.Lines3D;
import org.papervision3d.core.geom.renderables.Line3D;
import org.papervision3d.materials.WireframeMaterial;
import org.papervision3d.materials.special.LineMaterial;
import org.papervision3d.objects.primitives.Sphere;
import org.papervision3d.view.BasicView;
[SWF (width="465", height="465", frameRate="30", background="0xFFFFFF")]
public class IKTest3 extends BasicView {
private static const NUM_LINES:uint = 30;
private var _lines:Vector.<SegmentList3D>;
private var _lineModels:Vector.<Lines3D>;
private var _targets:Vector.<PolarCoord3D>;
private var _cameraPos:PolarCoord3D;
private var _active:Boolean = true;
public function IKTest3() {
super(465, 465);
init();
startRendering();
//addChild(new Stats({ bg: 0xFAFAFA, fps: 0x333333, ms: 0x555555, mem: 0x777777, memmax: 0x999999 } ));
}
private function init():void {
_lines = new Vector.<SegmentList3D>();
_lineModels = new Vector.<Lines3D>();
_targets = new Vector.<PolarCoord3D>();
for (var i:uint = 0; i < NUM_LINES; i++) {
var line:SegmentList3D = createLine(30, 5, new Vector3D(0, 0, 0));
var lineModel:Lines3D = createLineModel(line, 0x0);
_lines.push(line);
_lineModels.push(lineModel);
_targets.push(new PolarCoord3D(100, 0, 0));
scene.addChild(lineModel);
}
_cameraPos = new PolarCoord3D(200, 0, 0);
_cameraPos.vTheta = .01;
camera.position = _cameraPos.toNumber3D();
stage.addEventListener(MouseEvent.CLICK, onStageClick);
Mouse.cursor = MouseCursor.BUTTON;
}
private function createLine(size:uint, length:Number, origin:Vector3D):SegmentList3D {
var sl:SegmentList3D = new SegmentList3D(origin);
for (var i:uint = 0; i < size; i++) {
sl.addSegment(i % 2 ? origin : origin.add(new Vector3D(length, 0, 0)));
}
return sl;
}
private function createLineModel(line:SegmentList3D, color:Number=0xFFFFFF):Lines3D {
var material:LineMaterial = new LineMaterial(color);
var lines:Lines3D = new Lines3D(material);
for (var seg:Segment3D = line.head; seg != null; seg = seg.next) {
lines.addNewLine(1,
seg.point0.x,
seg.point0.y,
seg.point0.z,
seg.point1.x,
seg.point1.y,
seg.point1.z);
}
return lines;
}
private function updateLineModel(line:SegmentList3D, model:Lines3D):void {
var i:uint = 0;
for (var seg:Segment3D = line.head; seg != null; seg = seg.next) {
var l:Line3D = (model.lines[i++] as Line3D);
l.v0.x = seg.point0.x;
l.v0.y = seg.point0.y;
l.v0.z = seg.point0.z;
l.v1.x = seg.point1.x;
l.v1.y = seg.point1.y;
l.v1.z = seg.point1.z;
}
}
private function onStageClick(evt:Event):void {
if (!(evt.target is Stats)) {
_active = !_active;
}
}
protected override function onRenderTick(event:Event=null):void {
if (_active) {
for (var i:uint = 0; i < NUM_LINES; i++) {
_targets[i].vTheta += (Math.random() - .5) * .01;
_targets[i].vPhi += (Math.random() - .5) * .01;
_targets[i].update();
_lines[i].reach(_targets[i].toVector3D());
updateLineModel(_lines[i], _lineModels[i]);
}
} else {
_cameraPos.update();
camera.position = _cameraPos.toNumber3D();
}
super.onRenderTick(event);
}
}
}
import flash.geom.Point;
import flash.geom.Vector3D;
import org.papervision3d.core.math.Number3D;
class SegmentList3D {
private var _head:Segment3D;
private var _tail:Segment3D;
private var _origin:Vector3D;
public function SegmentList3D(origin:Vector3D) {
_origin = origin.clone();
}
public function get tail():Segment3D {
return _tail;
}
public function get head():Segment3D {
return _head;
}
public function addSegment(point:Vector3D):Segment3D {
if (_tail) {
var segment:Segment3D = new Segment3D(_tail.point1, point.clone());
segment.prev = _tail;
_tail.next = segment;
_tail = segment;
} else {
_tail = new Segment3D(_origin.clone(), point);
_head = _tail;
}
return _tail;
}
public function drag(target:Vector3D):void {
if (_tail == null) {
return;
}
_tail.point1 = target.clone();
for (var segment:Segment3D = _tail; segment != null; segment = segment.prev) {
segment.restore();
}
}
public function reach(target:Vector3D):void {
if (_tail == null) {
return;
}
_tail.point1 = target.clone();
for (var segment:Segment3D = _tail; segment != null; segment = segment.prev) {
segment.restore(1);
}
_head.point0 = _origin.clone();
for (segment = _head; segment != null; segment = segment.next) {
segment.restore(0);
}
}
}
class Segment3D {
public var point0:Vector3D;
public var point1:Vector3D;
public var next:Segment3D;
public var prev:Segment3D;
private var _originalLength:Number;
public function Segment3D(point0:Vector3D, point1:Vector3D) {
this.point0 = point0;
this.point1 = point1;
_originalLength = Vector3D.distance(point0, point1);
}
public function restore(raito:Number=1):void {
var dx:Number = point1.x - point0.x;
var dy:Number = point1.y - point0.y;
var dz:Number = point1.z - point0.z;
var m:Number = .5 - _originalLength / Vector3D.distance(point0, point1) * .5;
dx *= 2 * m;
dy *= 2 * m;
dz *= 2 * m;
point0.x += dx * raito;
point0.y += dy * raito;
point0.z += dz * raito;
point1.x -= dx * (1 - raito);
point1.y -= dy * (1 - raito);
point1.z -= dz * (1 - raito);
}
public function get length():Number {
return Vector3D.distance(point0, point1);
}
}
class PolarCoord3D {
private static const PI:Number = Math.PI;
private static const PI2:Number = 2 * Math.PI;
public static const MAX_VELOCITY_RADIUS:Number = 10;
public static const MAX_VELOCITY_THETA:Number = .1;
public static const MAX_VELOCITY_PHI:Number = .1;
private var _radius:Number;
private var _theta:Number;
private var _phi:Number;
private var _vRadius:Number = 0;
private var _vTheta:Number = 0;
private var _vPhi:Number = 0;
public function PolarCoord3D(radius:Number, theta:Number, phi:Number) {
_radius = radius;
_theta = theta;
_phi = phi;
}
public function get radius():Number {
return _radius;
}
public function set radius(value:Number):void {
_radius = value;
}
public function get theta():Number {
return _theta;
}
public function set theta(value:Number):void {
_theta = value;
if (Math.abs(_theta) > PI) {
if (_theta > 0) {
_theta -= PI2;
} else {
_theta += PI2;
}
}
}
public function get phi():Number {
return _phi;
}
public function set phi(value:Number):void {
_phi = value;
if (Math.abs(_phi) > PI) {
if (_phi > 0) {
_phi -= PI2;
} else {
_phi += PI2;
}
}
}
public function toNumber3D():Number3D {
return new Number3D(_radius * Math.cos(_theta) * Math.cos(_phi),
_radius * Math.sin(_phi),
_radius * Math.sin(_theta) * Math.cos(_phi));
}
public function toVector3D():Vector3D {
return new Vector3D(_radius * Math.cos(_theta) * Math.cos(_phi),
_radius * Math.sin(_phi),
_radius * Math.sin(_theta) * Math.cos(_phi));
}
public function update():void {
_radius += vRadius;
_theta += vTheta;
_phi += vPhi;
}
public function get vRadius():Number {
return _vRadius;
}
public function set vRadius(value:Number):void {
if (Math.abs(value) > MAX_VELOCITY_RADIUS) {
_vRadius = value > 0 ? MAX_VELOCITY_RADIUS : -MAX_VELOCITY_RADIUS;
} else {
_vRadius = value;
}
}
public function get vTheta():Number {
return _vTheta;
}
public function set vTheta(value:Number):void {
if (Math.abs(value) > MAX_VELOCITY_THETA) {
_vTheta = value > 0 ? MAX_VELOCITY_THETA : -MAX_VELOCITY_THETA;
} else {
_vTheta = value;
}
}
public function get vPhi():Number {
return _vPhi;
}
public function set vPhi(value:Number):void {
if (Math.abs(value) > MAX_VELOCITY_PHI) {
_vPhi = value > 0 ? MAX_VELOCITY_PHI : -MAX_VELOCITY_PHI;
} else {
_vPhi = value;
}
}
}