简体   繁体   中英

Passing a vec3 to glm::lookAt appears to modify it

I have encountered a situation where passing a glm::vec3 to the glm::lookAt function appears to modify it.

The following code is about shadow frustum calculation in a C++ / OpenGL game engine. The problem arises in the glm::lookAt function, at the end.

void Shadows::updateFrustumBoundingBox()
{

  // Here we convert main camera frustum coordinates in light view space
  std::array<glm::vec3,8> points = {
    // Near plane points
    lightView * glm::vec4(cameraPtr->ntl, 1.0),
    lightView * glm::vec4(cameraPtr->ntr, 1.0),
    lightView * glm::vec4(cameraPtr->nbl, 1.0),
    lightView * glm::vec4(cameraPtr->nbr, 1.0),
    // Far plane points
    lightView * glm::vec4(cameraPtr->ftl, 1.0),
    lightView * glm::vec4(cameraPtr->ftr, 1.0),
    lightView * glm::vec4(cameraPtr->fbl, 1.0),
    lightView * glm::vec4(cameraPtr->fbr, 1.0)};

  // Here we find the shadow bounding box dimensions
  bool first = true;
  for (int i=0; i<7; ++i)
  {
    glm::vec3* point = &points[i];

    if (first)
    {
            minX = point->x;
            maxX = point->x;
            minY = point->y;
            maxY = point->y;
            minZ = point->z;
            maxZ = point->z;
      first = false;
    }

        if (point->x > maxX)
            maxX = point->x;
    else if (point->x < minX)
            minX = point->x;

        if (point->y > maxY)
            maxY = point->y;
    else if (point->y < minY)
            minY = point->y;

        if (point->z > maxZ)
            maxZ = point->z;
    else if (point->z < minZ)
            minZ = point->z;
  }

  frustumWidth = maxX - minX;
  frustumHeight = maxY - minY;
  frustumLength = maxZ - minZ;

  // Here we find the bounding box center, in light view space
  float x = (minX + maxX) / 2.0f;
  float y = (minY + maxY) / 2.0f;
  float z = (minZ + maxZ) / 2.0f;
  glm::vec4 frustumCenter = glm::vec4(x, y, z, 1.0f);

  // Here we convert the bounding box center in world space
  glm::mat4 invertedLight = glm::mat4(1.0f);
  invertedLight = glm::inverse(lightView);
  frustumCenter = invertedLight * frustumCenter;

  // Here we define the light projection matrix (shadow frustum dimensions)
  lightProjection = glm::ortho(
    -frustumWidth/2.0f, // left
    frustumWidth/2.0f, // right
    -frustumHeight/2.0f, // down
    frustumHeight/2.0f, // top
    0.01f, // near
    SHADOW_DISTANCE); // far


  // Here we define the light view matrix (shadow frustum position and orientation)
  lightDirection = glm::normalize(lightDirection);
  target =  glm::vec3(0.0f, 100.0f, 200.0f) + lightDirection;

  lightView = glm::lookAt(
                  // Shadow box center
                     glm::vec3(0.0f, 100.0f, 200.0f), // THIS LINE
                  // glm::vec3(frustumCenter), // ALTERNATIVELY, THIS LINE. Here I convert it as a vec3 because it is a vec4

                  // Light orientation
                  target,

                  // Up vector
                  glm::vec3( 0.0f, 1.0f,  0.0f));

  cout << "frustumCenter: " << frustumCenter.x << " " << frustumCenter.y << " " << frustumCenter.z << endl;

  // Final matrix calculation
  lightSpaceMatrix = lightProjection * lightView;
}

As is, the first glm::lookAt parameter is glm::vec3(0.0f, 100.0f, 200.0f), and it works correctly. The glm::vec4 frustumCenter variable isn't used by glm::lookAt, and outputs correct values each frame.

frustumCenter: 573.41 -93.2823 -133.848 1

But if I change the first glm::lookAt parameter to "glm::vec3(frustumCenter)":

frustumCenter: nan nan nan nan

How can it be?

I have encountered a situation where passing a glm::vec3 to the glm::lookAt function appears to modify it."

I don't think so. You use frustumCenter to caclucalte lightView , but before you do that, you use lightView to calculate frustumCenter : frustumCenter = invertedLight * frustumCenter;

So my educated guess on what happens here is:

The lightView matrix is not properly initialized / initialized to a singular matrix (like all zeros). As such, the inverse will be not defined, resulting in frustumCenter becoming all NaN , which in turn results in lightView becoming all NaN .

But if you not use frustumCenter in the first iteration, lightView will be properly initialized, and frustumCenter will be calculated to a sane value in the next iteration.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM