/** * Returns a matrix corresponding to degrees rotation about an axis. * @param angle The angle in degrees to rotate in the xy-plane. * @param axis A vector representing the axis of rotation. * @return A new rotation matrix. */ gmMatrix4 gmMatrix4::rotate(double angle, const gmVector3& axis) { gmMatrix4 m_; double length = axis.length(); double a = axis[0] / length; double b = axis[1] / length; double c = axis[2] / length; double aa = a * a; double bb = b * b; double cc = c * c; double sine = sin(gmRadians(angle)); double cosine = cos(gmRadians(angle)); double omcos = 1 - cosine; m_[0][0] = aa + (1 - aa) * cosine; m_[1][1] = bb + (1 - bb) * cosine; m_[2][2] = cc + (1 - cc) * cosine; m_[0][1] = a * b * omcos + c * sine; m_[0][2] = a * c * omcos - b * sine; m_[1][0] = a * b * omcos - c * sine; m_[1][2] = b * c * omcos + a * sine; m_[2][0] = a * c * omcos + b * sine; m_[2][1] = b * c * omcos - a * sine; m_[0][3] = m_[1][3] = m_[2][3] = m_[3][0] = m_[3][1] = m_[3][2] = 0; m_[3][3] = 1; return m_; }
LRESULT CLX3DViewer::OnKeyDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { #if 0 int nVirtKey = (int) wParam; // virtual-key code int lKeyData = lParam; // key data m_nKeyRepeat++; int repeatCount = m_nKeyRepeat;//lKeyData & 0xffff; LONG bCtrl = (GetAsyncKeyState(VK_CONTROL) & (1<<15)); LONG bShift = (GetAsyncKeyState(VK_SHIFT) & (1<<15)); double moveX = 0; double moveZ = 0; double rotateX = 0; double rotateY = 0; double rotateZ = 0; double rotate = 0.4 + 0.2*(repeatCount-1); if (rotate > 2) rotate = 2; BOOL bRunning = bShift; double speed = bRunning? 4: 2; switch (nVirtKey) { case VK_UP: { if (bCtrl) { rotateX = -rotate; } else { moveZ -= speed; } } break; case VK_DOWN: { if (bCtrl) { rotateX = rotate; } else { moveZ += speed; } } break; case VK_LEFT: { if (bCtrl) { moveX -= speed; } else { rotateY = rotate; } } break; case VK_RIGHT: { if (bCtrl) { moveX += speed; } else { rotateY = -rotate; } } break; } CLViewpoint* pViewpoint = static_cast<CLViewpoint*>(m_viewpointStack[0]); CLSFRotation* orientation = static_cast<CLSFRotation*>(pViewpoint->m_orientation); CLSFVec3f* position = static_cast<CLSFVec3f*>(pViewpoint->m_position); // Orientation if (rotateY != 0 || rotateX != 0 || rotateZ != 0) { /* float x = orientation->m_value.m_v[0]; float y = orientation->m_value.m_v[1]; float z = orientation->m_value.m_v[2]; float angle = orientation->m_value.m_a; */ Quat4d q = orientation->m_value.AxisAngleToQuaternion();//x, y, z, angle); q.CombineQuaternion(/*x, y, z, angle,*/ gmRadians(rotateZ), gmRadians(rotateY), gmRadians(rotateX)); orientation->m_value = q.QuaternionToAxisAngle();//x, y, z, angle); /* orientation->m_value.m_v[0] = x; orientation->m_value.m_v[1] = y; orientation->m_value.m_v[2] = z; orientation->m_value.m_a = angle; */ orientation->m_value.m_v.normalize(); } // Position { gmMatrix4 repos = gmMatrix4::identity(); repos *= gmMatrix4::rotate(gmDegrees(orientation->m_value.m_a), -orientation->m_value.m_v); repos *= gmMatrix4::translate(moveX, 0, moveZ); repos *= gmMatrix4::rotate(gmDegrees(orientation->m_value.m_a), -orientation->m_value.m_v).inverse(); position->m_value = repos.transform(position->m_value); } FireViewChange(); #endif return 0; }
LRESULT CLX3DViewer::OnMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { CPoint point; point.x = (short)LOWORD(lParam); point.y = (short)HIWORD(lParam); if (m_dragging == 1) { m_slider.OnMouseMove(point); UpdateWindow(); double position = m_slider.GetPos(); CComQIPtr<ILMediaSeeking> seeking = m_filterGraph; seeking->Seek(position); } #if 0 if (m_dragging) { CPoint offset = point - m_startpoint; if (m_dragging == 1) // change XY position { CLViewpoint* pViewpoint = static_cast<CLViewpoint*>(m_viewpointStack[0]); CLSFRotation* orientation = static_cast<CLSFRotation*>(pViewpoint->m_orientation); CLSFVec3f* position = static_cast<CLSFVec3f*>(pViewpoint->m_position); double moveY = (double)-offset.y/20; double moveX = (double)offset.x/20; gmMatrix4 repos = gmMatrix4::identity(); repos *= gmMatrix4::rotate(gmDegrees(orientation->m_value.m_a), -orientation->m_value.m_v); repos *= gmMatrix4::translate(moveX, moveY, 0); repos *= gmMatrix4::rotate(gmDegrees(orientation->m_value.m_a), -orientation->m_value.m_v).inverse(); position->m_value = repos.transform(m_initialPosition); FireViewChange(); } else if (m_dragging == 2) // change XZ position { CLViewpoint* pViewpoint = static_cast<CLViewpoint*>(m_viewpointStack[0]); CLSFRotation* orientation = static_cast<CLSFRotation*>(pViewpoint->m_orientation); CLSFVec3f* position = static_cast<CLSFVec3f*>(pViewpoint->m_position); double moveX = (double)offset.x/20; double moveZ = (double)offset.y/20; gmMatrix4 repos = gmMatrix4::identity(); repos *= gmMatrix4::rotate(gmDegrees(orientation->m_value.m_a), -orientation->m_value.m_v); repos *= gmMatrix4::translate(moveX, 0, moveZ); repos *= gmMatrix4::rotate(gmDegrees(orientation->m_value.m_a), -orientation->m_value.m_v).inverse(); position->m_value = repos.transform(m_initialPosition); FireViewChange(); } else if (m_dragging == 3) { double r = 600; // 360 double rotateY = (double)offset.x*360/r; double rotateX = (double)offset.y*360/r; CLViewpoint* pViewpoint = static_cast<CLViewpoint*>(m_viewpointStack[0]); CLSFRotation* orientation = static_cast<CLSFRotation*>(pViewpoint->m_orientation); CLSFVec3f* position = static_cast<CLSFVec3f*>(pViewpoint->m_position); // Orientation if (rotateY != 0 || rotateX != 0) { /* float x = m_initialOrientation.m_v[0]; float y = m_initialOrientation.m_v[1]; float z = m_initialOrientation.m_v[2]; float angle = m_initialOrientation.m_a; */ Quat4d q = m_initialOrientation.AxisAngleToQuaternion(/*x, y, z, angle*/); q.CombineQuaternion(/*x, y, z, angle,*/ 0, gmRadians(rotateY), gmRadians(rotateX)); orientation->m_value = q.QuaternionToAxisAngle();//Quat4d(x, y, z, angle)); /* orientation->m_value.m_v[0] = x; orientation->m_value.m_v[1] = y; orientation->m_value.m_v[2] = z; orientation->m_value.m_a = angle; */ orientation->m_value.m_v.normalize(); } // Position { // Rotate position around centerOfRotation gmMatrix4 repos = gmMatrix4::identity(); repos *= gmMatrix4::rotate(gmDegrees(orientation->m_value.m_a), -orientation->m_value.m_v); repos *= gmMatrix4::rotate(rotateY, gmVector3(0,1,0)); repos *= gmMatrix4::rotate(gmDegrees(orientation->m_value.m_a), -orientation->m_value.m_v).inverse(); position->m_value = repos.transform(m_initialPosition); } // Position { // Rotate position around centerOfRotation gmMatrix4 repos = gmMatrix4::identity(); repos *= gmMatrix4::rotate(gmDegrees(orientation->m_value.m_a), -orientation->m_value.m_v); repos *= gmMatrix4::rotate(rotateX, gmVector3(1,0,0)); repos *= gmMatrix4::rotate(rotateY, gmVector3(0,1,0)); repos *= gmMatrix4::rotate(gmDegrees(orientation->m_value.m_a), -orientation->m_value.m_v).inverse(); position->m_value = repos.transform(m_initialPosition); } FireViewChange(); } } else { CRect client; GetClientRect(&client); int w = client.right; int h = client.bottom; // wglMakeCurrent(hdc, m_hrc); double winx = point.x; double winy = client.bottom-point.y-1; GLint viewport[4] = { 0, 0, w, h }; GLuint selectBuf[512]; glSelectBuffer(512, selectBuf); glRenderMode(GL_SELECT); glInitNames(); glPushName(0); { CLViewpoint* pViewpoint = NULL; if (m_viewpointStack.GetSize() > 0) { pViewpoint = static_cast<CLViewpoint*>(m_viewpointStack[0]); } else { // hmm... } // glViewport(m_viewR[view].left, m_viewR[view].top, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPickMatrix(winx, winy, 3, 3, viewport); // glLoadMatrixd(projm); // double fov; if (pViewpoint) { CLSFFloat* fieldOfView = static_cast<CLSFFloat*>(pViewpoint->m_fieldOfView); fov = fieldOfView->m_value; } else { fov = M_PI/4; } gluPerspective(gmDegrees(fov), (GLfloat)w / (GLfloat)h, 1.0, 10000.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); //glLoadMatrixf((float*)modelm); CX3DDrawContext xdc; #if 0 // NavigationInfo { BOOL headlight; if (m_navigationinfoStack.GetSize() > 0) { CLNavigationInfo* pNavigationInfo = static_cast<CLNavigationInfo*>(m_navigationinfoStack[0]); headlight = static_cast<CLSFBool*>(pNavigationInfo->m_headlight)->m_v; } else { // Default values headlight = TRUE; } glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); if (TRUE)//TRUE/*bAnyLights*/) { } if (headlight) { GLfloat light_direction[4] = { 0, 0, 1, 0}; // directional GLfloat color[4] = {1, 1, 1, 1}; GLfloat ambient[4] = {0, 0, 0, 1}; glEnable(GL_LIGHT0+xdc.m_nLight); glLightfv(GL_LIGHT0+xdc.m_nLight, GL_POSITION, light_direction); glLightfv(GL_LIGHT0+xdc.m_nLight, GL_AMBIENT, ambient); glLightfv(GL_LIGHT0+xdc.m_nLight, GL_DIFFUSE, color); glLightfv(GL_LIGHT0+xdc.m_nLight, GL_SPECULAR , color); xdc.m_nLight++; } } #endif if (pViewpoint) { CLSFRotation* orientation = static_cast<CLSFRotation*>(pViewpoint->m_orientation); CLSFVec3f* position = static_cast<CLSFVec3f*>(pViewpoint->m_position); gmVector3t<float> norientation = orientation->m_value.m_v; norientation.normalize(); glRotate(gmDegrees(orientation->m_value.m_a), -norientation); glTranslate(-position->m_value); } else { // TODO glTranslatef(0, 0, -180); } glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); if (m_scene) { CComQIPtr<CLRenderImplImpl> render = static_cast<CLSAIScene*>(m_scene)->m_root; if (render) { render->Draw(&xdc); } } glFlush(); } GLint hits = glRenderMode(GL_RENDER); if (hits > 0) { MessageBeep(-1); GLuint* ptr = selectBuf; GLuint names = *ptr++; float z1 = *ptr++ / 0x7fffffff; float z2 = *ptr++ / 0x7fffffff; double winz = z2; double modelMatrix[16]; double projMatrix[16]; glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix); glGetDoublev(GL_PROJECTION_MATRIX, projMatrix); double objx, objy, objz; gluUnProject(winx, winy, winz, modelMatrix, projMatrix, viewport, &objx, &objy, &objz); for (int n = 0; n < names; n++) { } } } #endif return 0; }