Camera Update vs Scene Render

Hi,

We have a working code for fitting the shape to the arcrotatecamera perfectly, however, in order to update the camera radius and set the target it appears to have a render which is in our case expensive to make for some cases. I wonder if its possible to update the camera without having a render.


var extends = new BABYLON.Vector3(2.54, 2.54, 2.44)

var points= []
var offset= 0.1
points.push(new BABYLON.Vector3(-offset, 0.0, -offset))
points.push(new BABYLON.Vector3(-offset, 2.44, -offset))
points.push(new BABYLON.Vector3(-offset, 0.0, 2.54 + offset))
points.push(new BABYLON.Vector3(-offset, 2.44, 2.54 + offset))
points.push(new BABYLON.Vector3(2.54 + offset, 0.0, 2.54 + offset))
points.push(new BABYLON.Vector3(2.54 + offset, 2.44, 2.54 + offset))
points.push(new BABYLON.Vector3(2.54 + offset, 0.0, 0.0 - offset))
points.push(new BABYLON.Vector3(2.54 + offset, 2.44, 0.0 - offset))

function fit() {

  amount = 100
  let i = 0
  sensitivity = 2
  failamount = 1
  consecutivefails = 0
  maxfails = amount / 2

  camera = arcCamera

  starttarget = camera.target
  startradius = camera.radius

  camera.radius = 71.6366 / 2
  lastworkingradius = 71.6366
  initialtarget = new BABYLON.Vector3(extends.x / 2, extends.y / 2, extends.z / 2)
  lastworkingtarget = initialtarget
  camera.setTarget(initialtarget, false, false, true)

  maxfailedradius = 1.2

  while (i <= amount) {
    fit = center(camera) // 0, 1, -1

    if (fit == 0) {
      break
    } else {
      if (fit == 1) {
        lastworkingradius = camera.radius
        lastworkingtarget = camera.target
        sensitivity = failamount == 1 ? 2 : Math.pow(2, failamount - 1)
        camera.radius -= camera.radius / sensitivity
        failamount = Math.max(1, failamount - 1)
        i++
        consecutivefails = 0
      } else {
        failamount++
        camera.radius = lastworkingradius
        camera.target = lastworkingtarget
        _ = center(camera)
        sensitivity = Math.pow(2, failamount)
        camera.radius -= camera.radius / sensitivity
        consecutivefails++
      }
    }

    if (failamount > maxfails + 1 || consecutivefails > 10) {
      camera.radius = lastworkingradius
      camera.target = lastworkingtarget
      _ = center(camera)
      break
    }
  }

  endtarget = camera.target
  endradius = camera.radius
  camera.setTarget(starttarget, false, false, true)
  camera.radius = startradius

  //animatefit(arcCamera, endtarget, endradius)
}

function center(camera) {
  scene.updateTransformMatrix()
  
  tolerance = 4
  
  dims = getroomdims()
  minx = dims[0]
  maxx = dims[1]
  miny = dims[2]
  maxy = dims[3]
  x = maxx - minx
  y = maxy - miny
  
  diffxl = minx
  diffxr = canvas.width - maxx
  diffyt = miny
  diffyb = canvas.height - maxy
  
  fit = 2
  canfit = canvas.width > x && canvas.height > y
  
  console.log("diffxl: " + diffxl)
  console.log("diffxr: " + diffxr)
  console.log("diffyt: " + diffyt)
  console.log("diffyb: " + diffyb)
  console.log("canfit: " + canfit)
  
  if (x / canvas.width > y / canvas.height) {
    if (diffxl >= 0 && diffxl <= tolerance && diffxr >= 0 && diffxr <= tolerance) {
      fit = 0
    } else if (canfit) {
      fit = 1
    } else if (!canfit) {
      fit = -1
    }
  } else {
    if (diffyb >= 0 && diffyb <= tolerance && diffyt >= 0 && diffyt <= tolerance) {
      fit = 0
    } else if (canfit) {
      fit = 1
    } else if (!canfit) {
      fit = -1
    }
  }
  
  centerx = minx + x / 2
  centery = miny + y / 2
  
  targetpos2d = BABYLON.Vector3.Project(
    camera.target, //vector to project
    BABYLON.Matrix.Identity(), //world matrix
    scene.getTransformMatrix(), //transform matrix
    { x: 0, y: 0, width: canvas.width, height: canvas.height } //viewport
  )
  
  targetunprojected = new BABYLON.Vector3(centerx, centery, targetpos2d.z)
  val = BABYLON.Vector3.Unproject(
    targetunprojected,
    engine.getRenderWidth(),
    engine.getRenderHeight(),
    BABYLON.Matrix.Identity(),
    scene.getViewMatrix(),
    scene.getProjectionMatrix()
  )
  if (fit != -1) {
    camera.setTarget(val, false, false, true)
  }
  scene.render()
  return fit
  }

function getdims() {
  minx = 9999
  miny = 9999
  maxx = -9999
  maxy = -9999

  for (var i = 0; i < wallpoints.length; i++) {
    pos2D = BABYLON.Vector3.Project(
      points[i], //vector to project
      BABYLON.Matrix.Identity(), //world matrix
      scene.getTransformMatrix(), //transform matrix
      { x: 0, y: 0, width: canvas.width, height: canvas.height } //viewport
    )

    if (pos2D.x < minx) {
      minx = pos2D.x
    }
    if (pos2D.y < miny) {
      miny = pos2D.y
    }

    if (pos2D.x > maxx) {
      maxx = pos2D.x 
    }
    if (pos2D.y > maxy) {
      maxy = pos2D.y
    }
  }

  x = maxx - minx
  y = maxy - miny

  diffxl = minx
  diffxr = canvas.width - maxx
  diffyt = miny
  diffyb = canvas.height - maxy
  return [minx, maxx, miny, maxy]
}

The scene is only rendered when you call scene.render, so you can control it. However if you update the camera and don’t render, you won’t see any difference on the image.

Hi @carolhmj,

Thanks for your reply. I was wondering if the projection of points could be calculated without having a render

It can, you just need to ensure you’re calling update on the camera matrices yourself