void setLookAtM(float rm[MATRIX_SIZE], float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ) { // See the OpenGL GLUT documentation for gluLookAt for a description // of the algorithm. We implement it in a straightforward way: float fx = centerX - eyeX; float fy = centerY - eyeY; float fz = centerZ - eyeZ; // Normalize f float rlf = 1.0f / length(fx, fy, fz); fx *= rlf; fy *= rlf; fz *= rlf; // compute s = f x up (x means "cross product") float sx = fy * upZ - fz * upY; float sy = fz * upX - fx * upZ; float sz = fx * upY - fy * upX; // and normalize s float rls = 1.0f / length(sx, sy, sz); sx *= rls; sy *= rls; sz *= rls; // compute u = s x f float ux = sy * fz - sz * fy; float uy = sz * fx - sx * fz; float uz = sx * fy - sy * fx; rm[0] = sx; rm[1] = ux; rm[2] = -fx; rm[3] = 0.0f; rm[4] = sy; rm[5] = uy; rm[6] = -fy; rm[7] = 0.0f; rm[8] = sz; rm[9] = uz; rm[10] = -fz; rm[11] = 0.0f; rm[12] = 0.0f; rm[13] = 0.0f; rm[14] = 0.0f; rm[15] = 1.0f; translateM(rm, -eyeX, -eyeY, -eyeZ); }
math::Matrix<float, 4, 4> Arrow3d::CalculateTransform(ScreenBase const & screen, float dz) const { double arrowScale = VisualParams::Instance().GetVisualScale() * kArrowSize; if (screen.isPerspective()) { static double const kLog2 = log(2.0); double const kMaxZoom = scales::UPPER_STYLE_SCALE + 1.0; double const zoomLevel = my::clamp(fabs(log(screen.GetScale()) / kLog2), kArrow3dMinZoom, kMaxZoom); double const t = (zoomLevel - kArrow3dMinZoom) / (kMaxZoom - kArrow3dMinZoom); arrowScale *= (kArrow3dScaleMin * (1.0 - t) + kArrow3dScaleMax * t); } double const scaleX = arrowScale * 2.0 / screen.PixelRect().SizeX(); double const scaleY = arrowScale * 2.0 / screen.PixelRect().SizeY(); double const scaleZ = screen.isPerspective() ? (0.002 * screen.GetDepth3d()) : 1.0; m2::PointD const pos = screen.GtoP(m_position); double const dX = 2.0 * pos.x / screen.PixelRect().SizeX() - 1.0; double const dY = 2.0 * pos.y / screen.PixelRect().SizeY() - 1.0; math::Matrix<float, 4, 4> scaleM = math::Identity<float, 4>(); scaleM(0, 0) = scaleX; scaleM(1, 1) = scaleY; scaleM(2, 2) = scaleZ; math::Matrix<float, 4, 4> rotateM = math::Identity<float, 4>(); rotateM(0, 0) = cos(m_azimuth + screen.GetAngle()); rotateM(0, 1) = -sin(m_azimuth + screen.GetAngle()); rotateM(1, 0) = -rotateM(0, 1); rotateM(1, 1) = rotateM(0, 0); math::Matrix<float, 4, 4> translateM = math::Identity<float, 4>(); translateM(3, 0) = dX; translateM(3, 1) = -dY; translateM(3, 2) = dz; math::Matrix<float, 4, 4> modelTransform = rotateM * scaleM * translateM; if (screen.isPerspective()) return modelTransform * math::Matrix<float, 4, 4>(screen.Pto3dMatrix()); return modelTransform; }
static void setLookAtM(float* rm, int rmOffset, float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ) { float fx = centerX - eyeX; float fy = centerY - eyeY; float fz = centerZ - eyeZ; float rlf = 1.0f /std::sqrt(fx*fx + fy*fy +fz*fz); fx *= rlf; fy *= rlf; fz *= rlf; float sx = fy * upZ - fz * upY; float sy = fz * upX - fx * upZ; float sz = fx * upY - fy * upX; float rls = 1.0f /std::sqrt(sx*sx + sy*sy +sz*sz); sx *= rls; sy *= rls; sz *= rls; float ux = sy * fz - sz * fy; float uy = sz * fx - sx * fz; float uz = sx * fy - sy * fx; rm[rmOffset + 0] = sx; rm[rmOffset + 1] = ux; rm[rmOffset + 2] = -fx; rm[rmOffset + 3] = 0.0f; rm[rmOffset + 4] = sy; rm[rmOffset + 5] = uy; rm[rmOffset + 6] = -fy; rm[rmOffset + 7] = 0.0f; rm[rmOffset + 8] = sz; rm[rmOffset + 9] = uz; rm[rmOffset + 10] = -fz; rm[rmOffset + 11] = 0.0f; rm[rmOffset + 12] = 0.0f; rm[rmOffset + 13] = 0.0f; rm[rmOffset + 14] = 0.0f; rm[rmOffset + 15] = 1.0f; translateM(rm, rmOffset, -eyeX, -eyeY, -eyeZ); }
/* ============= R_SetupGL ============= */ void R_SetupGL (void) { float screenaspect; float yfov; int i; extern int glwidth, glheight; int x, x2, y2, y, w, h; // // set up viewpoint // glMatrixMode(GL_PROJECTION); glLoadIdentity (); x = r_refdef.vrect.x * glwidth/vid.width; x2 = (r_refdef.vrect.x + r_refdef.vrect.width) * glwidth/vid.width; y = (vid.height-r_refdef.vrect.y) * glheight/vid.height; y2 = (vid.height - (r_refdef.vrect.y + r_refdef.vrect.height)) * glheight/vid.height; // fudge around because of frac screen scale if (x > 0) x--; if (x2 < glwidth) x2++; if (y2 < 0) y2--; if (y < glheight) y++; w = x2 - x; h = y - y2; if (envmap) { x = y2 = 0; w = h = 256; } glViewport (glx + x, gly + y2, w, h); screenaspect = (float)r_refdef.vrect.width/r_refdef.vrect.height; // yfov = 2*atan((float)r_refdef.vrect.height/r_refdef.vrect.width)*180/M_PI; MYgluPerspective (r_refdef.fov_y, screenaspect, 4, 4096); if (mirror) { if (mirror_plane->normal[2]) glScalef (1, -1, 1); else glScalef (-1, 1, 1); glCullFace(GL_BACK); } else glCullFace(GL_FRONT); glMatrixMode(GL_MODELVIEW); #ifdef DO_OWN_MATRIX_MATH float mv[16]; setIdentityM(mv, 0); rotateM(mv, -90, 1, 0, 0); // put Z going up rotateM(mv, 90, 0, 0, 1); // put Z going up rotateM(mv, -r_refdef.viewangles[2], 1, 0, 0); rotateM(mv, -r_refdef.viewangles[0], 0, 1, 0); rotateM(mv, -r_refdef.viewangles[1], 0, 0, 1); translateM(mv, 0, -r_refdef.vieworg[0], -r_refdef.vieworg[1], -r_refdef.vieworg[2]); glLoadMatrixf(mv); memcpy(r_world_matrix, mv, sizeof(r_world_matrix)); #else glLoadIdentity (); glRotatef (-90, 1, 0, 0); // put Z going up glRotatef (90, 0, 0, 1); // put Z going up glRotatef (-r_refdef.viewangles[2], 1, 0, 0); glRotatef (-r_refdef.viewangles[0], 0, 1, 0); glRotatef (-r_refdef.viewangles[1], 0, 0, 1); glTranslatef (-r_refdef.vieworg[0], -r_refdef.vieworg[1], -r_refdef.vieworg[2]); #ifdef USE_OPENGLES static qboolean initialized; static qboolean haveGL_OES_matrix_get; static qboolean haveGL_OES_query_matrix; #if 0 if (! initialized) { const char* extensions = (const char*) glGetString(GL_EXTENSIONS); haveGL_OES_matrix_get = strstr(extensions, "GL_OES_matrix_get") != NULL; haveGL_OES_query_matrix = strstr(extensions, "GL_OES_query_matrix") != NULL; initialized = true; } if (haveGL_OES_query_matrix) { GLfixed mantissa[16]; GLint exponent[16]; glQueryMatrixxOES( mantissa, exponent ); for(int i = 0; i < 16; i++) { r_world_matrix[i] = scalbnf(mantissa[i], exponent[i]-16); } } else if (haveGL_OES_matrix_get) { glGetIntegerv (MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES, (GLint*) r_world_matrix); } else #endif { // No way to get the world matix, set to identity memset(r_world_matrix, 0, sizeof(r_world_matrix)); for(i = 0; i < 16; i += 5) { r_world_matrix[i] = 1.0f; } } #else glGetFloatv (GL_MODELVIEW_MATRIX, r_world_matrix); #endif #endif // DO_OWN_MATRIX_MATH // // set drawing parms // if (gl_cull.value) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE); glDisable(GL_BLEND); glDisable(GL_ALPHA_TEST); glEnable(GL_DEPTH_TEST); }
void Arrow3d::Render(ScreenBase const & screen, ref_ptr<dp::GpuProgramManager> mng) { // Unbind current VAO, because glVertexAttributePointer and glEnableVertexAttribute can affect it. GLFunctions::glBindVertexArray(0); ref_ptr<dp::GpuProgram> prg = mng->GetProgram(gpu::ARROW_3D_PROGRAM); prg->Bind(); if (!m_isInitialized) { Build(prg); m_isInitialized = true; } dp::ApplyState(m_state, prg); static double const kLog2 = log(2.0); double const kMaxZoom = scales::UPPER_STYLE_SCALE + 1.0; double const zoomLevel = my::clamp(fabs(log(screen.GetScale()) / kLog2), kArrow3dMinZoom, kMaxZoom); double const t = (zoomLevel - kArrow3dMinZoom) / (kMaxZoom - kArrow3dMinZoom); double const arrowScale = kArrow3dScaleMin * (1.0 - t) + kArrow3dScaleMax * t; double const scaleX = m_pixelWidth * arrowScale * 2.0 / screen.PixelRect().SizeX() / kArrowSizeX; double const scaleY = m_pixelHeight * arrowScale * 2.0 / screen.PixelRect().SizeY() / kArrowSizeY; double const scaleZ = scaleX; m2::PointD const pos = screen.GtoP(m_position); double const dX = 2.0 * pos.x / screen.PixelRect().SizeX() - 1.0; double const dY = 2.0 * pos.y / screen.PixelRect().SizeY() - 1.0; math::Matrix<float, 4, 4> scaleM = math::Identity<float, 4>(); scaleM(0, 0) = scaleX; scaleM(1, 1) = scaleY; scaleM(2, 2) = scaleZ; math::Matrix<float, 4, 4> rotateM = math::Identity<float, 4>(); rotateM(0, 0) = cos(m_azimuth + screen.GetAngle()); rotateM(0, 1) = -sin(m_azimuth + screen.GetAngle()); rotateM(1, 0) = -rotateM(0, 1); rotateM(1, 1) = rotateM(0, 0); math::Matrix<float, 4, 4> translateM = math::Identity<float, 4>(); translateM(3, 0) = dX; translateM(3, 1) = -dY; math::Matrix<float, 4, 4> modelTransform = rotateM * scaleM * translateM; modelTransform = modelTransform * math::Matrix<float, 4, 4>(screen.Pto3dMatrix()); dp::UniformValuesStorage uniforms; uniforms.SetMatrix4x4Value("m_transform", modelTransform.m_data); dp::ApplyUniforms(uniforms, prg); GLFunctions::glBindBuffer(m_bufferId, gl_const::GLArrayBuffer); GLFunctions::glEnableVertexAttribute(m_attributePosition); GLFunctions::glVertexAttributePointer(m_attributePosition, 3, gl_const::GLFloatType, false, 0, 0); GLFunctions::glBindBuffer(m_bufferNormalsId, gl_const::GLArrayBuffer); GLFunctions::glEnableVertexAttribute(m_attributeNormal); GLFunctions::glVertexAttributePointer(m_attributeNormal, 3, gl_const::GLFloatType, false, 0, 0); GLFunctions::glDrawArrays(gl_const::GLTriangles, 0, m_vertices.size() / 3); prg->Unbind(); GLFunctions::glBindBuffer(0, gl_const::GLArrayBuffer); }