#include "ats_MayaBoid.h" #include "ats_Point.h" #include "ats_Matrix3D.h" #include "ats_MBoidGlobal.h" #include #include #include #include // 識別子が長すぎるワーニングを無効 #pragma warning (disable : 4786) using namespace ats; using namespace std; MayaBoid::MayaBoid(MDagPath& path, int tail_num, double speed, double max, double weight1, double weight2, double weight3) : Boid(max, max, tail_num, speed), m_acFnSet(6), mo_group_weight(weight1), mo_group_muki_weight(weight2), mo_kansei_weight(weight3), m_crazy(rand()) { MStatus status; MFnDagNode dag(path, &status); if ( MS::kSuccess != status ) throw MException("Failure Creating MFnDagNode in MayaBoid Constructor \n", status); // これではコネクションまで再現されない /*m_maya_obj = dg.duplicate(true, false, &status); if ( MS::kSuccess != status ) throw MException("Failure duplicate in MayaBoid Constructor\n", status); */ MString original_name(dag.name()); MString command("instance "); MStringArray result; // MEL instance 発行 status = MGlobal::executeCommand(command + original_name, result, false); if ( MS::kSuccess != status ){ throw MException("Failure instance in MayaBoid Constructor\n", status); } MSelectionList s; status = s.add(result[0]); if ( MS::kSuccess != status ) throw MException("Failure selection list add in MayaBoid Constructor\n", status); //status = s.getDagPath(0, m_dag_path, m_maya_obj); // getDagPathでは常にkNullObjが返る、なぜ? status = s.getDependNode (0, m_maya_obj); if(MS::kSuccess != status) throw MException("Failure selection list getDagPath in MayaBoid Constructor\n", status); if(MObject::kNullObj == m_maya_obj) throw MException("Failure selection list getDagPath returned null obj in MayaBoid Constructor\n", status); // DAGNodeFnSetとObjectの関連付け status = m_fn_dag_node.setObject(m_maya_obj); if ( MS::kSuccess != status ) throw MException("Failure MFnDagNode::setObject in MayaBoid Constructor\n", status); status = m_fn_dag_node.getPath(m_dag_path); if(MS::kSuccess != status) throw MException("Failure GetDagPath in MayaBoid Constructor\n", status); MakeFnSet(); } MayaBoid::~MayaBoid() { } void MayaBoid::MakeFnSet() { int attr_num = 6; vector attr(attr_num); vector attrName(attr_num); attrName[0] = "translateX"; attrName[1] = "translateY"; attrName[2] = "translateZ"; attrName[3] = "rotateX"; attrName[4] = "rotateY"; attrName[5] = "rotateZ"; //MFnAnimCurve::AnimCurveType curve_type = MFnAnimCurve::kAnimCurveTL; MStatus status; for(int i=0; i < 6; i++){ // DagNodeFnSetからアトリビュートのハンドルを取得 attr[i] = m_fn_dag_node.attribute( attrName[i], &status ); if ( MS::kSuccess != status ) { throw MException("Failure Crating attribute in MayaBoid::MakeFnSet\n", status); } MObject trans = m_dag_path.transform(&status); if ( MS::kSuccess != status ) { throw MException("Failure get dagpath transfrom in MayaBoid::MakeFnSet\n", status); } // AnimCurve関数セットからオブジェクトの作成 //if(i > 2){ curve_type = MFnAnimCurve::kAnimCurveTA; } m_acFnSet[i].create(trans, attr[i], NULL, &status); if(MS::kSuccess != status){ stringstream buf; buf << "Failure creat MFnAnimCurve in MayaBoid::MakeFnSet" << endl << "bad attribute : " << attrName[i].asChar() << endl; //<< "error code : " << error << endl; throw MException(buf.str(), status); } } } // メモ : Nearをはしょってないやつ //if(m_parent != 0 && m_near != 0){ // OK m_muki = ((m_parent->Center()-m_center)*0.03 + m_parent->Muki()*0.03 + m_muki*0.95 + m_near->GetMuki()*0.01); // メモ : Nearをはしょったやつ // m_muki = ((m_parent->Center()-m_center)*0.05 + m_parent->Muki()*0.08 + m_muki*1.1); void MayaBoid::UpdateTime(double time) { m_time = time; if(m_parent != 0){ // 中心へ + 群への協調 + 慣性 (+ 衝突回避は重いのでなし) //m_muki = ((m_parent->Center()-m_center)*0.23 + m_parent->Muki()*0.023 + m_muki*1.5); //m_muki.Normalize() *= m_speed; //0.05 0.08 1.1 m_muki = ((m_parent->Center()-m_center) * mo_group_weight + m_parent->Muki() * mo_group_muki_weight + m_muki * mo_kansei_weight); // 200回に一回狂う(笑) if(!(m_crazy++ % 200)){ const BoundingFrame& b = m_parent->GetBoundingFrame(); Point3D tmp(m_center - b.GetCenter()); m_muki = -tmp.GetNormal(); // 中心向きのベクトルを加算 } m_muki.Normalize() *= m_speed; IsCrash(); // ボックスから飛び出てれば反転 UpdateTail(); // 尾の更新 m_center += m_muki * 0.03; } } void MayaBoid::Draw() { const double PI = 3.1415926535897932384626433832795; // 時間取得 MTime tm( (double)m_time, MTime::kFilm ); // 移動 if((MS::kSuccess != m_acFnSet[0].addKeyframe(tm, m_center.X()*20)) || (MS::kSuccess != m_acFnSet[1].addKeyframe(tm, m_center.Y()*20)) || (MS::kSuccess != m_acFnSet[2].addKeyframe(tm, m_center.Z()*20))) { throw MException("Error setting the keyframe 1\n", MStatus(MS::kFailure)); } Point3D xnorm(1,0,0), ynorm(0,1,0), znorm(0,0,1); Point3D vec(m_muki); Point3D y_vec(vec); y_vec.Y(0); // Y軸回転 double y_ang = y_vec.Angle(znorm); Matrix3DD tmp; // 回転計算 if(vec.X() < 0){ tmp.RotateY(-y_ang); } else { tmp.RotateY(y_ang); } Point3D x_vec(vec*tmp); // vec*tmp : 回転を逆に辿る x_vec.X(0); double x_ang = x_vec.Angle(znorm); // X軸回転 x_ang *= -1; if(vec.X() < 0){ y_ang = PI + PI - y_ang; // ZX平面の単位Zと垂直な方向で+-のどっちか } if(vec.Y() < 0){ x_ang = PI + PI - x_ang; } // 3,4,5 = rotate x, y, z if((MS::kSuccess != m_acFnSet[3].addKeyframe(tm, x_ang)) || (MS::kSuccess != m_acFnSet[4].addKeyframe(tm, y_ang)))// || //(MS::kSuccess != m_acFnSet[5].addKeyframe(tm, 0))) { throw MException("Error setting the keyframe 2\n", MStatus(MS::kFailure)); } } bool MayaBoid::IsCrash() { // ボックスの外側にあって const BoundingFrame& b = m_parent->GetBoundingFrame(); double out = b.IsOut(m_center * 20.0); if(out > 0){ // キーフレームをつけるときに20倍してるから //m_center = ((m_center - b.GetCenter()) * 0.98) + b.GetCenter(); // ちょっと中心に寄せてやってから //m_muki *= -1; // 方向反転 Point3D tmp(m_center - b.GetCenter()); m_muki += -tmp.GetNormal() * 0.3; // 中心向きのベクトルを加算 return true; } else { m_muki += (Point(rand()%10-5,rand()%10-5,rand()%10-5)).Normalize()*0.057; //m_muki.Normalize(); return false; } } void MayaBoid::UpdateTail() { *m_tail_itr = m_center; if(m_tail_itr == m_tail.begin()){ // イテレータを逆向きに移動 m_tail_itr = m_tail.end(); // 一個ずらすもすべてコピーするも同じ m_tail_itr--; } else { m_tail_itr--; } }