예제 #1
0
파일: face.cpp 프로젝트: nikolobin/sandbox
void FaceRotate(Face & face, const float4 &r)
{
	for(auto & v : face.vertex) v = qrot(r,v);
    PlaneRotate(face.plane(), r);
	face.gu = qrot(r,face.gu);
	face.gv = qrot(r,face.gv);
	face.ot = qrot(r,face.ot);
}
예제 #2
0
파일: NewTracball.cpp 프로젝트: kudolf/Game
/*
** ドラッグ中
**   マウスのドラッグ中に実行する
*/
void trackballMotion(int x, int y)
{
  if (drag) {
    double dx, dy, a;
    
    /* マウスポインタの位置のドラッグ開始位置からの変位 */
    dx = (x - cx) * sx;
    dy = (y - cy) * sy;
    //dy = 0;
    /* マウスポインタの位置のドラッグ開始位置からの距離 */
    a = sqrt(dx * dx + dy * dy);
    
    if (a != 0.0) {
      double ar = a * SCALE * 0.5;
      double as = sin(ar) / a;
      double dq[4] = { cos(ar), dy * as, dx * as, 0.0 };
      
      /* クォータニオンを掛けて回転を合成 */
      qmul(tq, dq, cq);
      
      /* クォータニオンから回転の変換行列を求める */
      qrot(rt, tq);
    }
  }
}
예제 #3
0
int main(int argc, const char *argv[]) try
{
	std::vector<RigidBody> rbs;
	for (auto const &b : bodysizes)
	{
		auto verts = genboxverts(b);
		auto tris = calchull(verts, 8);
		rbs.push_back(RigidBody({ Shape(verts, tris) }, float3(0, 0, 0)));
	}
	rbscalemass(&rbs[0], 5.0f); // make torso heavier than limb bones
	rbs[0].position.z = 1.0f;  // lift a meter off the ground.
	DXWin mywin("Joint Drive - powered rag doll model", { 800,600 });
	std::vector<Mesh> meshes;
	for (auto &rb : rbs)
	{
		meshes.push_back(MeshSmoothish(rb.shapes[0].verts, rb.shapes[0].tris)); //  1 shape each is known
		rb.damping = 0.8f;   //rb.gravscale = 0;
	}
	for (auto &joint : joints)
	{
		rbs[joint.b0].ignore.push_back(&rbs[joint.b1]);
		rbs[joint.b1].ignore.push_back(&rbs[joint.b0]);
		rbs[joint.b1].position = rbs[joint.b0].pose() * joint.p0 - qrot(rbs[joint.b1].orientation,joint.p1);
	}

	WingMesh ground_wm = WingMeshBox({ -5, -5, -2.0f }, { 5, 5, -1.0f });
	auto ground = MeshFlatShadeTex(ground_wm.verts, WingMeshTris(ground_wm));
	ground.hack = { 0.25f, 0.75f, 0.25f, 1 };
	
	Pose camera = { { 0, -8, 0 }, normalize(float4(0.9f, 0, 0, 1)) };   // where we view the rendered scene from.
	float time = 0;             // our global clock, used to generate the circular animation for upper limbs to follow
	float torquelimit = 38.0f;  // how much torque we let each joint apply each frame

	while (mywin.WindowUp())
	{
		time += 0.06f;

		std::vector<LimitAngular> angulars;
		std::vector<LimitLinear>  linears;
		for (auto const &joint : joints)
		{
			Append(linears, ConstrainPositionNailed(&rbs[joint.b0], joint.p0, &rbs[joint.b1], joint.p1));
			Append(angulars, ConstrainAngularDrive(&rbs[joint.b0], &rbs[joint.b1], (float4(0, joint.a*cos(time), joint.a*sin(time), sqrt(1.0f - joint.a*joint.a))), torquelimit));
		}
		PhysicsUpdate(Addresses<RigidBody>(rbs), linears, angulars, { &ground_wm.verts });

		for (unsigned int i = 0; i < rbs.size(); i++)
			meshes[i].pose = rbs[i].pose();

		mywin.RenderScene(camera, Append(Addresses(meshes), std::vector<Mesh*>({ &ground })));
	}
	return 0;
}
catch (std::exception e)
{
	MessageBoxA(GetActiveWindow(), e.what(), "FAIL", 0);
	return -1;
}
예제 #4
0
파일: NewTracball.cpp 프로젝트: kudolf/Game
/*
** トラックボール処理の初期化
**   プログラムの初期化処理のところで実行する
*/
void trackballInit(void)
{
  /* ドラッグ中ではない */
  drag = 0;

  /* 単位クォーターニオン */
  cq[0] = 1.0;
  cq[1] = 0.0;
  cq[2] = 0.0;
  cq[3] = 0.0;
  
  /* 回転行列の初期化 */
  qrot(rt, cq);
}
예제 #5
0
파일: vecbench.c 프로젝트: golems/amino
int main( int argc, char **argv ) {
    (void) argc;
    (void) argv;

    // init
    srand((unsigned int)time(NULL)); // might break in 2038

    aa_test_ulimit();

    cross();
    qmul();
    qrot();
    tfmul();
    duqumul();
}
예제 #6
0
void Trackball::motion(int x, int y)
{
	if (dragged) {
		double dx, dy, a;

		dx = (x - cx) * sx;
		dy = (y - cy) * sy;

		a = sqrt(dx * dx + dy * dy);

		if (a != 0.0)
		{
			double ar = a * SCALE * 0.5;
			double as = sin(ar) / a;
			double dq[4] = { cos(ar), dy * as, dx * as, 0.0 };

			qmul(tq, dq, cq);

			qrot(rt, tq);
		}
	}
}
예제 #7
0
파일: main.cpp 프로젝트: BHCLL/blendocv
int
main(int argc, char **argv)
{


	const int seg_num = 5;
	const MT_Scalar seg_length = 15;

	const float seg_startA[3] = {0,0,0};
	const float seg_startB[3] = {0,-20,0};

	// create some segments to solve with

	// First chain
	//////////////


	IK_Segment_ExternPtr const segmentsA = new IK_Segment_Extern[seg_num]; 	
	IK_Segment_ExternPtr const segmentsB = new IK_Segment_Extern[seg_num]; 	

	IK_Segment_ExternPtr seg_it = segmentsA; 	
	IK_Segment_ExternPtr seg_itB = segmentsB; 	

	
	{

//		MT_Quaternion qmat(MT_Vector3(0,0,1),-3.141/2);
		MT_Quaternion qmat(MT_Vector3(0,0,1),0);
		MT_Matrix3x3 mat(qmat);

		seg_it->seg_start[0] = seg_startA[0];
		seg_it->seg_start[1] = seg_startA[1];
		seg_it->seg_start[2] = seg_startA[2];

		float temp[12];
		mat.getValue(temp);
 
		seg_it->basis[0] = temp[0];
		seg_it->basis[1] = temp[1];
		seg_it->basis[2] = temp[2];

		seg_it->basis[3] = temp[4];
		seg_it->basis[4] = temp[5];
		seg_it->basis[5] = temp[6];

		seg_it->basis[6] = temp[8];
		seg_it->basis[7] = temp[9];
		seg_it->basis[8] = temp[10];
 
		seg_it->length = seg_length;

		MT_Quaternion q;
		q.setEuler(0,0,0);

			
		MT_Matrix3x3 qrot(q);

		seg_it->basis_change[0] = 1;
		seg_it->basis_change[1] = 0;
		seg_it->basis_change[2] = 0;
		seg_it->basis_change[3] = 0;
		seg_it->basis_change[4] = 1;
		seg_it->basis_change[5] = 0;
		seg_it->basis_change[6] = 0;
		seg_it->basis_change[7] = 0;
		seg_it->basis_change[8] = 1;


		seg_it ++;			

		seg_itB->seg_start[0] = seg_startA[0];
		seg_itB->seg_start[1] = seg_startA[1];
		seg_itB->seg_start[2] = seg_startA[2];
 
		seg_itB->basis[0] = temp[0];
		seg_itB->basis[1] = temp[1];
		seg_itB->basis[2] = temp[2];

		seg_itB->basis[3] = temp[4];
		seg_itB->basis[4] = temp[5];
		seg_itB->basis[5] = temp[6];

		seg_itB->basis[6] = temp[8];
		seg_itB->basis[7] = temp[9];
		seg_itB->basis[8] = temp[10];
 
		seg_itB->length = seg_length;

		seg_itB->basis_change[0] = 1;
		seg_itB->basis_change[1] = 0;
		seg_itB->basis_change[2] = 0;
		seg_itB->basis_change[3] = 0;
		seg_itB->basis_change[4] = 1;
		seg_itB->basis_change[5] = 0;
		seg_itB->basis_change[6] = 0;
		seg_itB->basis_change[7] = 0;
		seg_itB->basis_change[8] = 1;


		seg_itB ++;			


	}


	int i;
	for (i=1; i < seg_num; ++i, ++seg_it,++seg_itB) {

		MT_Quaternion qmat(MT_Vector3(0,0,1),0.3);
		MT_Matrix3x3 mat(qmat);

		seg_it->seg_start[0] = 0;
		seg_it->seg_start[1] = 0;
		seg_it->seg_start[2] = 0;

		float temp[12];
		mat.getValue(temp);
 
		seg_it->basis[0] = temp[0];
		seg_it->basis[1] = temp[1];
		seg_it->basis[2] = temp[2];

		seg_it->basis[3] = temp[4];
		seg_it->basis[4] = temp[5];
		seg_it->basis[5] = temp[6];

		seg_it->basis[6] = temp[8];
		seg_it->basis[7] = temp[9];
		seg_it->basis[8] = temp[10];
 
		seg_it->length = seg_length;

		MT_Quaternion q;
		q.setEuler(0,0,0);

			
		MT_Matrix3x3 qrot(q);

		seg_it->basis_change[0] = 1;
		seg_it->basis_change[1] = 0;
		seg_it->basis_change[2] = 0;
		seg_it->basis_change[3] = 0;
		seg_it->basis_change[4] = 1;
		seg_it->basis_change[5] = 0;
		seg_it->basis_change[6] = 0;
		seg_it->basis_change[7] = 0;
		seg_it->basis_change[8] = 1;


		///////////////////////////////

		seg_itB->seg_start[0] = 0;
		seg_itB->seg_start[1] = 0;
		seg_itB->seg_start[2] = 0;
 
		seg_itB->basis[0] = temp[0];
		seg_itB->basis[1] = temp[1];
		seg_itB->basis[2] = temp[2];

		seg_itB->basis[3] = temp[4];
		seg_itB->basis[4] = temp[5];
		seg_itB->basis[5] = temp[6];

		seg_itB->basis[6] = temp[8];
		seg_itB->basis[7] = temp[9];
		seg_itB->basis[8] = temp[10];
 
		seg_itB->length = seg_length;

		seg_itB->basis_change[0] = 1;
		seg_itB->basis_change[1] = 0;
		seg_itB->basis_change[2] = 0;
		seg_itB->basis_change[3] = 0;
		seg_itB->basis_change[4] = 1;
		seg_itB->basis_change[5] = 0;
		seg_itB->basis_change[6] = 0;
		seg_itB->basis_change[7] = 0;
		seg_itB->basis_change[8] = 1;



	}

	// create the chains

	const int num_chains = 2;

	IK_Chain_ExternPtr chains[num_chains];

	chains[0] = IK_CreateChain();
	chains[1] = IK_CreateChain();

	// load segments into chain

	IK_LoadChain(chains[0],segmentsA,seg_num);
	IK_LoadChain(chains[1],segmentsB,seg_num);

	// make and install a mouse handler

	MEM_SmartPtr<MyGlutMouseHandler> mouse_handler (MyGlutMouseHandler::New());
	GlutMouseManager::Instance()->InstallHandler(mouse_handler);

	mouse_handler->SetChain(chains,num_chains);

	// make and install a keyhandler
	MEM_SmartPtr<MyGlutKeyHandler> key_handler (MyGlutKeyHandler::New());
	GlutKeyboardManager::Instance()->InstallHandler(key_handler);

	// instantiate the drawing class	

	MEM_SmartPtr<ChainDrawer> drawer (ChainDrawer::New());
	GlutDrawManager::Instance()->InstallDrawer(drawer);

	drawer->SetMouseHandler(mouse_handler);
	drawer->SetChain(chains,num_chains);
	drawer->SetKeyHandler(key_handler);

	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
	glutCreateWindow("ik");
	glutDisplayFunc(GlutDrawManager::Draw);
	glutMouseFunc(GlutMouseManager::Mouse);
	glutMotionFunc(GlutMouseManager::Motion);
	glutKeyboardFunc(GlutKeyboardManager::HandleKeyboard);

	init(MT_Vector3(-50,-50,-50),MT_Vector3(50,50,50));
	glutMainLoop();
	return 0;             /* ANSI C requires main to return int. */
}
예제 #8
0
void TurretShape::_updateNodes(const Point3F& rot)
{
   EulerF xRot(rot.x, 0.0f, 0.0f);
   EulerF zRot(0.0f, 0.0f, rot.z);

   // Set heading
   S32 node = mDataBlock->headingNode;
   if (node != -1)
   {
      MatrixF* mat = &mShapeInstance->mNodeTransforms[node];
      Point3F defaultPos = mShapeInstance->getShape()->defaultTranslations[node];
      Quat16 defaultRot = mShapeInstance->getShape()->defaultRotations[node];

      QuatF qrot(zRot);
      qrot *= defaultRot.getQuatF();
      qrot.setMatrix( mat );      
      mat->setColumn(3, defaultPos);
   }

   // Set pitch
   node = mDataBlock->pitchNode;
   if (node != -1)
   {
      MatrixF* mat = &mShapeInstance->mNodeTransforms[node];
      Point3F defaultPos = mShapeInstance->getShape()->defaultTranslations[node];
      Quat16 defaultRot = mShapeInstance->getShape()->defaultRotations[node];

      QuatF qrot(xRot);
      qrot *= defaultRot.getQuatF();
      qrot.setMatrix( mat );    
      mat->setColumn(3, defaultPos);
   }

   // Now the mirror direction nodes, if any
   for (U32 i=0; i<TurretShapeData::NumMirrorDirectionNodes; ++i)
   {
      node = mDataBlock->pitchNodes[i];
      if (node != -1)
      {
         MatrixF* mat = &mShapeInstance->mNodeTransforms[node];
         Point3F defaultPos = mShapeInstance->getShape()->defaultTranslations[node];
         Quat16 defaultRot = mShapeInstance->getShape()->defaultRotations[node];         

         QuatF qrot(xRot);
         qrot *= defaultRot.getQuatF();
         qrot.setMatrix( mat );    
         mat->setColumn(3, defaultPos);
      }

      node = mDataBlock->headingNodes[i];
      if (node != -1)
      {
         MatrixF* mat = &mShapeInstance->mNodeTransforms[node];
         Point3F defaultPos = mShapeInstance->getShape()->defaultTranslations[node];
         Quat16 defaultRot = mShapeInstance->getShape()->defaultRotations[node];

         QuatF qrot(zRot);
         qrot *= defaultRot.getQuatF();
         qrot.setMatrix( mat );      
         mat->setColumn(3, defaultPos);
      }
   }

   mShapeInstance->setDirty(TSShapeInstance::TransformDirty);
}
예제 #9
0
int main(int argc, char *argv[]) try
{
	std::cout << "TestDQ\n";
	Pose camera = { { 0, 0, 8 }, { 0, 0, 0, 1 } };
	bool showaxis = true;
	float3 focuspoint(0, 0, 0);
	float3 mousevec_prev;
	float4 model_orientation(0, 0, 0, 1);
	Pose p0 = { { -3, 0, 0 }, { 0, 0, 0, 1 } };
	Pose p1 = { {  3, 0, 0 }, { 0, 0, sqrtf(0.5f),sqrtf(0.5f) } };
	float dt = 0.01f, t = 0;
	Pose *selected = NULL;
	std::vector<float4> planes = { { 1, 0, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 1, 0 }, { -1, 0, 0, 0 }, { 0, -1, 0, 0 }, { 0, 0, -1, 0 } };
	for (auto &p : planes)
		p.w = -0.25f;

	GLWin glwin("Dual Quaternion Pose Interpolation");
	glwin.keyboardfunc = [&](int key, int, int)
	{
		showaxis = key == 'a' != showaxis;
	};
	while (glwin.WindowUp())
	{
		t = t + dt;  // advance our global time    t is in 0..1
		if (t > 1.0f)
			t = 0.0f;

		Pose pt  = dqinterp(p0,p1,t);     // And here we show our dual quaterion usage

		// some extras to help visualize the axis of rotation, not the best math to get the result, but oh well
		float4 aq = qmul(dot(p0.orientation, p1.orientation) < 0 ? -p1.orientation : p1.orientation, qconj(p0.orientation));
		float3 axis = normalize(aq.xyz()*(aq.w < 0 ? -1.0f : 1.0f));  // direction of the axis of rotation
		float3 axisp = cross(axis, p1.position - p0.position) / 2.0f * sqrtf(1/dot(aq.xyz(),aq.xyz())-1);  // origin projected onto the axis of rotation
		// user interaction: 
		float3 ray = qrot(camera.orientation, normalize(glwin.MouseVector));   // for mouse selection
		float3 v1 = camera.position + ray*100.0f;
		if (!glwin.MouseState)  // note that we figure out what is being selected only when the mouse is up
		{
			selected = NULL;
			for (Pose *p : { &p0, &p1 })
			{
				if (auto h = ConvexHitCheck(planes, *p, camera.position, v1))
				{
					selected = p;
					v1 = h.impact;
				}
			}
		}
		else // if (glwin.MouseState)  
		{
			if (selected)
				selected->orientation = qmul(VirtualTrackBall(camera.position, selected->position, qrot(camera.orientation, mousevec_prev), qrot(camera.orientation, glwin.MouseVector)), selected->orientation);
			else
				camera.orientation = qmul(camera.orientation, qconj(VirtualTrackBall(float3(0, 0, 1), float3(0, 0, 0), mousevec_prev, glwin.MouseVector))); // equation is non-typical we are orbiting the camera, not rotating the object
		}
		camera.position = focuspoint + qzdir(camera.orientation)*magnitude(camera.position - focuspoint);
		camera.position -= focuspoint;
		camera.position *= powf(1.1f, (float)glwin.mousewheel);
		camera.position += focuspoint;
		mousevec_prev = glwin.MouseVector;

		// Render the scene
		glPushAttrib(GL_ALL_ATTRIB_BITS); 
		glViewport(0, 0, glwin.Width, glwin.Height); // Set up the viewport
		glClearColor(0.1f, 0.1f, 0.15f, 1);
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
		glMatrixMode(GL_PROJECTION);
		glPushMatrix(); glLoadIdentity();
		gluPerspective(glwin.ViewAngle, (double)glwin.Width / glwin.Height, 0.25, 250);
		glMatrixMode(GL_MODELVIEW);
		glPushMatrix(); glLoadIdentity();
		glMultMatrixf(camera.Inverse().Matrix());

		glDisable(GL_LIGHTING); 
		glAxis();  
		glGridxy(4.0f);
		if (showaxis)
		{
			glPushAttrib(GL_ALL_ATTRIB_BITS);
			glLineWidth(3.0f);
			glBegin(GL_LINES);
			glColor3f(1, 1, 1);
			for (auto p : { p0.position, p1.position, pt.position ,axisp})
				glVertex3fv(p - axis*0.5f), glVertex3fv(p + axis*0.5f);  // note the comma
			glEnd();
			glPopAttrib();
			glColor3f(1, 1, 0);
			glBegin(GL_LINES);
			glVertex3fv(axisp + axis*dot(axis, p0.position)), glVertex3fv(axisp + axis*dot(axis, p1.position));
			glVertex3fv(axisp + axis*dot(axis, p0.position)), glVertex3fv(p0.position);
			glVertex3fv(axisp + axis*dot(axis, p1.position)), glVertex3fv(p1.position);
			glVertex3fv(axisp + axis*dot(axis, pt.position)), glVertex3fv(pt.position);
			glEnd();
		}

		glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_COLOR_MATERIAL);
		for (auto p : { p0, p1, pt })
			glcolorbox(0.25f, p);

		glPopMatrix();  //should be currently in modelview mode
		glMatrixMode(GL_PROJECTION);
		glPopMatrix();
		glMatrixMode(GL_MODELVIEW);
		glPopAttrib();// Restore state

		glwin.PrintString({ 0, 0 }, "ESC to quit.");
		glwin.PrintString({ 0, 1 }, "'a' show axis (%s)", showaxis ? "on" : "off");
		glwin.PrintString({ 0, 2 }, "%selected: %s", glwin.MouseState?"S":"s", (selected) ? ((selected==&p0)?"box0":"box1") : "none");
		glwin.SwapBuffers();
	}
	std::cout << "\n";
	return 0;
}
catch (std::exception e)
{
	std::cerr << e.what() << "\n";
}
예제 #10
0
int main(int argc, const char *argv[]) try
{
	std::vector<Joint> joints;
	std::vector<RigidBody> rbs;
	std::map<std::string,unsigned int> rbindex;
	auto xml = XMLParseFile("./default_hand.chr");  // replace string with whatever model you want to test.   uses xml variation of John Ratcliff's easy mesh (ezm) file format.
	auto const &skx = xml.child("model").child("skeleton");
	for (auto const &b : skx.children)
	{
		rbindex[b.attribute("name")] = rbs.size();
		auto verts = ArrayImport<float3>(b.child("verts").body);
		auto tris = calchull(verts, verts.size());
		float3 pos = StringTo<float3>(b.attribute("position"));
		int parent = (b.hasAttribute("parent")) ? (int)rbindex[b.attribute("parent")] : -1;
		rbs.push_back(RigidBody({ Shape(verts,tris) }, pos + ((parent>=0)?rbs[parent].position-rbs[parent].com:float3(0,0,0))));
		if (parent>=0)
			joints.push_back({ parent, (int)rbs.size() - 1, pos, float3(0,0,0), StringTo<float3>(b.child("jointlimitmin").body), StringTo<float3>(b.child("jointlimitmax").body) });
	}
	rbscalemass(&rbs[0], 3.0f);
	rbscalemass(&rbs[1], 5.0f);

	DXWin mywin("DX testing articulated rigged model", { 800,600 });
	std::vector<Mesh> meshes;
	for (auto &rb : rbs)
	{
		meshes.push_back(MeshSmoothish(rb.shapes[0].verts, rb.shapes[0].tris)); //  1 shape each is known
		rb.damping = 0.8f;
		//rb.gravscale = 0;
	}
	for (auto &joint : joints)
	{
		rbs[joint.rbi0].ignore.push_back(&rbs[joint.rbi1]);
		rbs[joint.rbi1].ignore.push_back(&rbs[joint.rbi0]);
		joint.p0 -= rbs[joint.rbi0].com;
		joint.p1 -= rbs[joint.rbi1].com;
	}
	for (auto &ja : joints) for (auto &jb : joints) if (ja.rbi0 == jb.rbi0 && ja.rbi1 != jb.rbi1)  // ignore siblings 
	{
		rbs[ja.rbi1].ignore.push_back(&rbs[jb.rbi1]);
		rbs[jb.rbi1].ignore.push_back(&rbs[ja.rbi1]);
	}
	for (auto &ja : joints) for (auto &jb : joints) if (ja.rbi1 == jb.rbi0 )  // ignore grandparents 
	{
		rbs[ja.rbi0].ignore.push_back(&rbs[jb.rbi1]);
		rbs[jb.rbi1].ignore.push_back(&rbs[ja.rbi0]);
	}

	std::vector<float3> groundpoints = { { -5.0f, -5.0f, -5.0f }, { 5.0f, -5.0f, -5.0f }, { 5.0f, 10.0f, -5.0f }, { -5.0f, 10.0f, -5.0f }, { -5.0f, -5.0f, -10.0f }, { 5.0f, -5.0f, -10.0f }, { 5.0f, 10.0f, -10.0f }, { -5.0f, 10.0f, -10.0f } };
	Mesh ground = MeshSmoothish(groundpoints, { { 0, 1, 2 }, { 2, 3,0 } });
	ground.hack = { 1, 1, 0 ,1};
	WingMesh cube_wm = WingMeshCube(0.025f);
	auto mesh_cube = MeshFlatShadeTex(cube_wm.verts, WingMeshTris(cube_wm));   
	mesh_cube.hack = { 0, 1, 0, 1 };

	Pose camera = { { 0, -10, 0 }, normalize(float4(1, 0, 0, 1)) };
	RigidBody *selected = NULL;
	float3 spoint=camera * float3(0,0,-10);
	float3 rbpoint;
	
	struct Pin{ float3 w; RigidBody* rb; float3 p; };
	std::vector<Pin> pins;   
	
	mywin.keyboardfunc = [&](int key, int, int)
	{
		if (key == 'g') for (auto &rb : rbs) rb.gravscale = 1.0f - rb.gravscale;
		if (key == 'p' && selected)
			Append<Pin>(pins, { spoint, selected, rbpoint });
	};

	while (mywin.WindowUp())
	{
		float3 ray = qrot(camera.orientation, normalize(mywin.MouseVector));
		if (!selected)
		{
			for (auto &rb : rbs)
			{
				float3 v1 = camera.position + ray*100.0f;
				if (auto h=ConvexHitCheck(Planes(rb.shapes[0].verts, rb.shapes[0].tris),rb.pose(),camera.position,v1))
				{
					v1 = h.impact;
					selected = &rb;
					spoint = h.impact;
					rbpoint = rb.pose().inverse()*h.impact;
				}
			}
		}
		spoint = camera.position + ray * length(spoint - camera.position)*powf(1.025f, (float)mywin.mousewheel);
		mesh_cube.pose.position = spoint;
		if (!mywin.MouseState)
			selected = NULL;

		std::vector<LimitAngular> angulars;
		std::vector<LimitLinear>  linears;
		for (auto const &joint : joints)
		{
			Append(linears, ConstrainPositionNailed(&rbs[joint.rbi0], joint.p0, &rbs[joint.rbi1], joint.p1));
			Append(angulars, ConstrainAngularRange(&rbs[joint.rbi0], &rbs[joint.rbi1], { 0, 0, 0, 1 }, joint.jointlimitmin, joint.jointlimitmax));
		}
		if (selected)
			Append(linears, ConstrainPositionNailed(NULL, spoint, selected, rbpoint));
		for(auto &p:pins)
			Append(linears, ConstrainPositionNailed(NULL, p.w,p.rb,p.p));
		PhysicsUpdate(Addresses(rbs), linears, angulars, { &groundpoints });

		for (unsigned int i = 0; i < rbs.size(); i++)
		{
			meshes[i].pose = rbs[i].pose();
		}

		mywin.RenderScene(camera, Append(Addresses(meshes),std::vector<Mesh*>({ &ground, &mesh_cube })));
	}
}
catch (std::exception e)
{
	MessageBoxA(GetActiveWindow(), e.what(), "FAIL", 0);
	return -1;
}
예제 #11
0
// arcball function to do the arcball routine in mouse move
void arcball (rbt &O_frame_in_eye, rbt &O_frame, rbt &new_O_frame, rbt &S_frame, rbt &inv_S_frame, 
			  int g_width, int g_height, double old_x, double old_y, double new_x, 
			  double new_y, int g_manip_object) {
	// temp variables
	double dx, dy, dz, mag;
	bool out_sphere;
	coords3 v1, v2, a;
	qrot rot, q1, q2;
	rbt Q;

	// first get the center of the arcball
	coords3 center = O_frame_in_eye.translation;

	// now set up the projection matrix and variables to hold GetScreenSpaceCircle
	matrix4 projmat = MakeProjection(FRUST_FOVY, (float)g_width/(float)g_height, FRUST_NEAR, FRUST_FAR);
	coords3 screencenter;
	double screenrad;
	//get the center and radius in pixles
	GetScreenSpaceCircle(center, arcballradius, projmat, g_width, g_height, screencenter, screenrad);
	
	// VECTOR 1 - OLD POINT
	dx = old_x - screencenter.x;
	dy = old_y - screencenter.y;
	mag = (double)sqrt(dx*dx + dy*dy);
	out_sphere = (mag > screenrad);
	// if the point is out of the sphere, clamp to edge
	if(out_sphere == true) {
		//normalize dx and dy to clamp dz to 0
		dx = (dx / mag);
		dy = (dy / mag);
		dz = 0.0;
	} else {
		//solve for z (in X^2 + Y^2 + Z^2 = r^2)
		dz = (double)sqrt(screenrad*screenrad - (dx*dx) - (dy*dy));
		//normalize
		mag = (double)sqrt(dx*dx + dy*dy + dz*dz); 
		dx = dx / mag;
		dy = dy / mag;
		dz = dz / mag;
	}
	v1.SetCoords(dx,dy,dz);		//and we have our vector

	// VECTOR 2 - NEW POINT
	dx = (double)new_x - screencenter.x;
	dy = (double)new_y - screencenter.y;
	mag = (double)sqrt(dx*dx + dy*dy);
	out_sphere = (mag > screenrad);
	// if the point is out of the sphere, clamp to edge
	if(out_sphere == true) {
		//normalize dx and dy to clamp dz to 0
		dx = dx / mag;
		dy = dy / mag;
		dz = 0.0;
	} else {
		//solve for z (in X^2 + Y^2 + Z^2 = r^2)
		dz = (double)sqrt(screenrad*screenrad - (dx*dx) - (dy*dy));
		//normalize
		mag = (double)sqrt(dx*dx + dy*dy + dz*dz); 
		dx = dx / mag;
		dy = dy / mag;
		dz = dz / mag;
	}
	v2.SetCoords(dx,dy,dz);		//and we have our vector

	// find the qrot (from class notes it is [0, v1].[0, v0] hence w = 0) and therefore the rbt Q
	q1 = qrot(v1.x, v1.y, v1.z, 0.0);
	q2 = qrot(v2.x, v2.y, v2.z, 0.0);
	
	if (g_manip_object == 2)
		rot = q1*q2;
	else 
		rot = q2 * q1;	
	Q = rbt(rot);

	// CARRY OUT THE O' = SQS^(-1)O ROUTINE
	new_O_frame = S_frame * Q * inv_S_frame * O_frame;
}
예제 #12
0
/**
 * @brief Generates a optimised point cloud from a collection of processed keyframes using sparse bundle adjustment.
 * @param allFrames A vector containing keyframes which have been completely processed.
 * @param outputCloud The cloud generated from the keyframes.
 */
void utils::calculateSBACloud(std::vector<KeyframeContainer>& allFrames,boost::shared_ptr<pcl::PointCloud<pcl::PointXYZRGB> >& outputCloud)
{
	sba::SysSBA bundleAdjuster;
	//set the verbosity of the bundle adjuster
#ifndef NDEBUG
	bundleAdjuster.verbose=100;
#else
	bundleAdjuster.verbose=0;
#endif

	//a list of keypoints that already have been added to the SBA system
	std::vector<std::pair<int,uint> > addedPoints; //(frameID,keypointIndex)
	//maps frame IDs to frame index in the vector
	std::map<int,uint> ID2Ind;
	for(uint f=0;f<allFrames.size();++f) ID2Ind[allFrames[f].ID]=f;
	//maps the frame vector index to the node vector index
	std::map<uint,int> fInd2NInd;

	//count the number of 2D/3D-points and camera nodes if in debug mode
#ifndef NDEBUG
	uint nrP3D=0;
	uint nrP2D=0;
	uint nrC=0;
#endif

	//add every valid frame as a camera node to the sba system
	for(uint f=0;f<allFrames.size();++f)
	{
		if(!allFrames[f].invalid)
		{
			//get rotation and translation from the projection matrix
			Eigen::Matrix3d rot;
			cv::Mat_<double> cvT;
			Eigen::Vector4d t;
			//get rotation
			for(int x=0;x<3;++x) for(int y=0;y<3;++y) rot(x,y)=allFrames[f].projectionMatrix(x,y);
			//solve for translation
			cv::solve(allFrames[f].projectionMatrix(cv::Range(0,3),cv::Range(0,3)),allFrames[f].projectionMatrix(cv::Range(0,3),cv::Range(3,4)),cvT);
			//save translation
			for(int x=0;x<3;++x) t(x)=-cvT(x,0);
			t(3)=1.0;

			//convert rotation to quaternion
			Eigen::Quaterniond qrot(rot);
			qrot.normalize();

			//convert camera calibration matrix
			frame_common::CamParams cameraParameters;
			cameraParameters.fx=allFrames[f].cameraCalibration(0,0);
			cameraParameters.fy=allFrames[f].cameraCalibration(1,1);
			cameraParameters.cx=allFrames[f].cameraCalibration(0,2);
			cameraParameters.cy=allFrames[f].cameraCalibration(1,2);
			cameraParameters.tx=0.0;

			//add the frame as a camera node
			fInd2NInd[f]=bundleAdjuster.addNode(t,qrot,cameraParameters,false);
#ifndef NDEBUG
			++nrC;
#endif
		}
		else
			fInd2NInd[f]=-1;
	}

	//add the points to the correct nodes
	for(uint f=0;f<allFrames.size();++f)
	{
		if(!allFrames[f].invalid)
		{
			//add the points
			for(uint m=0;m<allFrames[f].matches.size();++m)
			{
				std::pair<int,uint> myP(allFrames[f].ID,m);
				bool goodToAdd=!utils::vectorContainsElement(addedPoints,myP);

				//point hasn't been added yet
				if(goodToAdd)
				{
					//check if the point has valid depth information
					float depth=allFrames[f].depthImg.image.at<float>(allFrames[f].keypoints[m].pt.y,allFrames[f].keypoints[m].pt.x);
					if(isnan(depth)==0)
					{
						//find the largest completely connected component emanating from this point (clique)
						std::vector<std::pair<int,uint> > pointsComplete;
						pointsComplete.push_back(std::pair<int,uint>(allFrames[f].ID,m));
						//check all matches of the point if they haven't been added yet and their frame is valid
						for(uint o=0;o<allFrames[f].matches[m].size();++o)
						{
							std::pair<int,uint> newElement(allFrames[f].matches[m][o].first.val[0],allFrames[f].matches[m][o].first.val[1]);
							if(!utils::vectorContainsElement(addedPoints,newElement) && !allFrames[ID2Ind[newElement.first]].invalid)
								pointsComplete.push_back(newElement);
						}

						//weed out all points that are not completely connected
						while(pointsComplete.size()>1)
						{
							//find the point with the fewest connections (if the component is completely connected all points have the same number of connections)
							uint minCorrespondences=pointsComplete.size();
							uint worstInd=0;
							for(uint i=0;i<pointsComplete.size();++i)
							{
								//count the number of connections that this point has
								uint fInd=ID2Ind[pointsComplete[i].first];
								uint myCorr=0;
								for(uint q=0;q<allFrames[fInd].matches.size();++q)
									for(uint r=0;r<allFrames[fInd].matches[q].size();++r)
									{
										std::pair<int,uint> tmpElement(allFrames[fInd].matches[q][r].first.val[0],allFrames[fInd].matches[q][r].first.val[1]);
										if(utils::vectorContainsElement(pointsComplete,tmpElement))
											++myCorr;
									}

								//save this point if it is the current worst
								if(myCorr<minCorrespondences)
								{
									minCorrespondences=myCorr;
									worstInd=i;
								}
							}

							//if the worst point has not the maximal number of connections erase it, else break as all points have the maximal number of connections
							if(minCorrespondences<pointsComplete.size()-1)
							{
								pointsComplete.erase(pointsComplete.begin()+worstInd);
							}
							else
								break;
						}

						//now pointsComplete contains the clique if the clique has more than one isolated point, write the points to the system
						if(pointsComplete.size()>1)
						{
							//calculate the 3D point and add it to the system
							cv::Mat_<double> p2D(2,1,0.0);
							p2D(0,0)=allFrames[f].keypoints[m].pt.x;
							p2D(1,0)=allFrames[f].keypoints[m].pt.y;
							cv::Mat_<double> p3D=reprojectImagePointTo3D(p2D,allFrames[f].cameraCalibration,allFrames[f].projectionMatrix,depth);
							Eigen::Vector4d newPoint;
							for(uint x=0;x<4;++x) newPoint(x)=p3D(x,0);
							int pointIndex=bundleAdjuster.addPoint(newPoint);
#ifndef NDEBUG
							++nrP3D;
#endif
							//add all image points corresponding to the 3D point to the system
							for(uint i=0;i<pointsComplete.size();++i)
							{
								uint fInd=ID2Ind[pointsComplete[i].first];
								Eigen::Vector2d imgPoint;
								imgPoint(0)=allFrames[fInd].keypoints[pointsComplete[i].second].pt.x;
								imgPoint(1)=allFrames[fInd].keypoints[pointsComplete[i].second].pt.y;
								bundleAdjuster.addMonoProj(fInd2NInd[fInd],pointIndex,imgPoint);
#ifndef NDEBUG
								++nrP2D;
#endif
							}
						}
					}
				}
			}
		}
	}

#ifndef NDEBUG
	ROS_INFO("C: %u;3D: %u;2D: %u",nrC,nrP3D,nrP2D);
#endif

	//remove bad tracks
	bundleAdjuster.calcCost();
	bundleAdjuster.removeBad(2);
	bundleAdjuster.reduceTracks();

	//run 100 iterations of sba
	bundleAdjuster.doSBA(100,1e-3, SBA_SPARSE_CHOLESKY);

	//save the new projective matrix calculated with sba
	for(uint f=0;f<allFrames.size();++f)
		if(!allFrames[f].invalid)
			for(int x=0;x<3;++x) for(int y=0;y<4;++y) allFrames[f].projectionMatrix(x,y)=bundleAdjuster.nodes[fInd2NInd[f]].w2n(x,y);

	//generate the point cloud from the new projection matrices
	utils::generateCloud(allFrames,*outputCloud);
}