<commit_before>import nimx.context
import nimx.types
import nimx.image
import nimx.render_to_image
import nimx.portable_gl
import nimx.animation
import nimx.window
import nimx.view_event_handling
import nimx.view_event_handling_new

import tables
import rod_types
import node
import component.camera

import ray
export Viewport
export SceneView


proc `camera=`*(v: SceneView, c: Camera) =
    v.mCamera = c

template rootNode*(v: SceneView): Node2D = v.mRootNode

proc `rootNode=`*(v: SceneView, n: Node2D) =
    if not v.mRootNode.isNil:
        v.mRootNode.nodeWillBeRemovedFromSceneView()
    v.mRootNode = n
    n.nodeWasAddedToSceneView(v)

proc camera*(v: SceneView): Camera =
    if v.mCamera.isNil:
        let nodeWithCamera = v.rootNode.findNode(proc (n: Node2D): bool = not n.componentIfAvailable(Camera).isNil)
        if not nodeWithCamera.isNil:
            v.mCamera = nodeWithCamera.componentIfAvailable(Camera)
    result = v.mCamera

template viewMatrix(v: SceneView): Matrix4 = v.mCamera.node.worldTransform.inversed

proc prepareFramebuffer(v: SceneView, i: var SelfContainedImage, sz: Size) =
    if i.isNil:
        echo "Creating buffer"
        i = imageWithSize(sz)
        i.flipVertically()
    elif i.size != sz:
        echo "Recreating buffer"
        i = imageWithSize(sz)
        i.flipVertically()

proc prepareFramebuffers(v: SceneView) =
    v.numberOfNodesWithBackCompositionInCurrentFrame = v.numberOfNodesWithBackComposition
    if v.numberOfNodesWithBackComposition > 0:
        let gl = currentContext().gl
        let vp = gl.getViewport()
        let sz = newSize(vp[2].Coord, vp[3].Coord)
        v.prepareFramebuffer(v.mActiveFrameBuffer, sz)
        v.prepareFramebuffer(v.mBackupFrameBuffer, sz)
        v.mScreenFramebuffer = gl.boundFramebuffer()
        gl.bindFramebuffer(v.mActiveFrameBuffer, false)
        gl.clearWithColor(0, 0, 0, 0)

proc getViewProjectionMatrix*(v: SceneView): Matrix4 =
    let cam = v.camera
    doAssert(not cam.isNil)
    v.viewMatrixCached = v.viewMatrix
    var projTransform : Transform3D
    cam.getProjectionMatrix(v.bounds, projTransform)
    result = projTransform * v.viewMatrixCached

template getViewMatrix*(v: SceneView): Matrix4 {.deprecated.} = v.getViewProjectionMatrix()

proc swapCompositingBuffers*(v: SceneView)

method draw*(v: SceneView, r: Rect) =
    if v.rootNode.isNil: return

    let c = currentContext()
    v.prepareFramebuffers()

    c.withTransform v.getViewProjectionMatrix():
        v.rootNode.recursiveDraw()

    if v.numberOfNodesWithBackCompositionInCurrentFrame > 0:
        # When some compositing nodes are optimized away, we have
        # to blit current backup buffer to the screen.
        v.numberOfNodesWithBackCompositionInCurrentFrame = 1
        v.swapCompositingBuffers()

proc rayWithScreenCoords*(v: SceneView, coords: Point): Ray =
    result.origin = v.camera.node.translation
    let x = (2.0 * coords.x) / v.bounds.width - 1.0
    let y = 1.0 - (2.0 * coords.y) / v.bounds.height
    let rayClip = newVector4(x, y, -1, 1)

    var proj : Transform3D
    v.mCamera.getProjectionMatrix(v.bounds, proj)

    proj.inverse()
    var rayEye = proj * rayClip
    rayEye[2] = -1
    rayEye[3] = 0

    var viewMat = v.mCamera.node.worldTransform
<commit_msg>fix ray with world camera coordinates<commit_after>import nimx.context
import nimx.types
import nimx.image
import nimx.render_to_image
import nimx.portable_gl
import nimx.animation
import nimx.window
import nimx.view_event_handling
import nimx.view_event_handling_new

import tables
import rod_types
import node
import component.camera

import ray
export Viewport
export SceneView


proc `camera=`*(v: SceneView, c: Camera) =
    v.mCamera = c

template rootNode*(v: SceneView): Node2D = v.mRootNode

proc `rootNode=`*(v: SceneView, n: Node2D) =
    if not v.mRootNode.isNil:
        v.mRootNode.nodeWillBeRemovedFromSceneView()
    v.mRootNode = n
    n.nodeWasAddedToSceneView(v)

proc camera*(v: SceneView): Camera =
    if v.mCamera.isNil:
        let nodeWithCamera = v.rootNode.findNode(proc (n: Node2D): bool = not n.componentIfAvailable(Camera).isNil)
        if not nodeWithCamera.isNil:
            v.mCamera = nodeWithCamera.componentIfAvailable(Camera)
    result = v.mCamera

template viewMatrix(v: SceneView): Matrix4 = v.mCamera.node.worldTransform.inversed

proc prepareFramebuffer(v: SceneView, i: var SelfContainedImage, sz: Size) =
    if i.isNil:
        echo "Creating buffer"
        i = imageWithSize(sz)
        i.flipVertically()
    elif i.size != sz:
        echo "Recreating buffer"
        i = imageWithSize(sz)
        i.flipVertically()

proc prepareFramebuffers(v: SceneView) =
    v.numberOfNodesWithBackCompositionInCurrentFrame = v.numberOfNodesWithBackComposition
    if v.numberOfNodesWithBackComposition > 0:
        let gl = currentContext().gl
        let vp = gl.getViewport()
        let sz = newSize(vp[2].Coord, vp[3].Coord)
        v.prepareFramebuffer(v.mActiveFrameBuffer, sz)
        v.prepareFramebuffer(v.mBackupFrameBuffer, sz)
        v.mScreenFramebuffer = gl.boundFramebuffer()
        gl.bindFramebuffer(v.mActiveFrameBuffer, false)
        gl.clearWithColor(0, 0, 0, 0)

proc getViewProjectionMatrix*(v: SceneView): Matrix4 =
    let cam = v.camera
    doAssert(not cam.isNil)
    v.viewMatrixCached = v.viewMatrix
    var projTransform : Transform3D
    cam.getProjectionMatrix(v.bounds, projTransform)
    result = projTransform * v.viewMatrixCached

template getViewMatrix*(v: SceneView): Matrix4 {.deprecated.} = v.getViewProjectionMatrix()

proc swapCompositingBuffers*(v: SceneView)

method draw*(v: SceneView, r: Rect) =
    if v.rootNode.isNil: return

    let c = currentContext()
    v.prepareFramebuffers()

    c.withTransform v.getViewProjectionMatrix():
        v.rootNode.recursiveDraw()

    if v.numberOfNodesWithBackCompositionInCurrentFrame > 0:
        # When some compositing nodes are optimized away, we have
        # to blit current backup buffer to the screen.
        v.numberOfNodesWithBackCompositionInCurrentFrame = 1
        v.swapCompositingBuffers()

proc rayWithScreenCoords*(v: SceneView, coords: Point): Ray =
    result.origin = v.camera.node.localToWorld(newVector3())
    let x = (2.0 * coords.x) / v.bounds.width - 1.0
    let y = 1.0 - (2.0 * coords.y) / v.bounds.height
    let rayClip = newVector4(x, y, -1, 1)

    var proj : Transform3D
    v.mCamera.getProjectionMatrix(v.bounds, proj)

    proj.inverse()
    var rayEye = proj * rayClip
    rayEye[2] = -1
    rayEye[3] = 0

    var viewMat = v.mCamera.node.worldTransform

{'fraction_non_alphanumeric': 0.09771592799878989, 'fraction_numerical': 0.009832098018454092, 'mean_word_length': 3.4796747967479673, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2435761', 'n_tokens_mistral': 2271, 'n_tokens_neox': 2162, 'n_words': 497}