-- current render target and camera local rendertarget = octane.render.getRenderTargetNode() local camera = rendertarget:getInputNode(octane.P_CAMERA) -- camera transform local pos = camera:getPinValue(octane.P_POSITION) local target = camera:getPinValue(octane.P_TARGET) local up = octane.vec.normalized(camera:getPinValue(octane.P_UP)) local Z = octane.vec.normalized(octane.vec.sub(target, pos)) local X = octane.vec.normalized(octane.vec.cross(up, Z)) local Y = octane.vec.normalized(octane.vec.cross(Z, X)) matrix = { {X[1], Y[1], Z[1], pos[1]}, {X[2], Y[2], Z[2], pos[2]}, {X[3], Y[3], Z[3], pos[3]}, } -- field of view, lens shift and resolution local resolution = rendertarget:getInputNode(octane.P_FILM_SETTINGS):getPinValue(octane.P_RESOLUTION) local uvmatrix = {} local projType = octane.NT_PROJ_PERSPECTIVE if camera.type == octane.NT_CAM_PANORAMIC then local fov = { camera:getPinValue(octane.P_FOVX), camera:getPinValue(octane.P_FOVY) } matrix = octane.matrix.mul(matrix, octane.matrix.makeRotY(math.pi)) uvmatrix = octane.matrix.makeScale({-fov[1] / 360, fov[2] / 180, 1}) projType = octane.NT_PROJ_SPHERICAL else local ortho = camera:getPinValue(octane.P_ORTHOGRAPHIC) local w = 0 if ortho then w = camera:getPinValue(octane.P_SCALE) / 2 projType = octane.NT_PROJ_LINEAR else local fov = camera:getPinValue(octane.P_FOV) w = math.tan(math.rad(fov / 2)) end local shift = camera:getPinValue(octane.P_LENS_SHIFT) local h = w * resolution[2] / resolution[1] matrix = octane.matrix.mul(matrix, octane.matrix.makeScale{-w, h, 1}) uvmatrix = octane.matrix.makeTranslation{shift[1], shift[2], 0} end -- get selected texture or material node, and apply transform function project(tex, type, keepPosition) proj = octane.node.create{ type = type, pinOwnerNode = tex, pinOwnerId = octane.P_PROJECTION, } octane.node.create{ type = octane.NT_TRANSFORM_VALUE, pinOwnerNode = tex, pinOwnerId = octane.P_TRANSFORM, } local matrix2 = matrix if not keepPosition then matrix2[1][4] = 0 matrix2[2][4] = 0 matrix2[3][4] = 0 end tex:setPinValue(octane.P_TRANSFORM, uvmatrix) proj:setPinValue(octane.P_TRANSFORM, matrix2) proj:setPinValue(octane.P_POSITION_TYPE, 1) -- world space = 1 end -- node.getPinInfo raises an error when the pin doesn't exist. function hasPin(n, pin) local r = pcall(n.getPinInfo, n, pin) return r end function hasProjection(n) return hasPin(n, octane.P_PROJECTION) and hasPin(n, octane.P_TRANSFORM) end local foundtex = false for _, n in ipairs(octane.project.getSelection()) do if hasProjection(n) then foundtex = true project(n, projType, true) elseif n:getProperties().outputType == octane.PT_MATERIAL then for i = 1, n:getPinCount() do local m = nil pcall(function() m = n:getInputNodeIx(i) end) if m ~= nil and hasProjection(m) then foundtex = true project(m, projType, true) end end elseif n:getProperties().type == octane.NT_ENV_TEXTURE then for i = 1, n:getPinCount() do local m = nil pcall(function() m = n:getInputNodeIx(i) end) if m ~= nil and hasProjection(m) then foundtex = true project(m, projType, false) end end end end if foundtex then octane.changemanager.update() else error("You have to select an image texture node, material or environment node.") end