the camera allows you to get a picture from the world and display it on the screen (or process it inside the program)
please note that rendering methods may receive not the real display, but the "virtual" one you created. 3 methods should be implemented in the virtual screen: getWidth, getHeight, drawPixel
please note that when transmitting a virtual display, the camera returns colors in string format, which slows down its operation. this is done for compatibility with old software. however, if your code is ready to accept objects with the Color type, then add the "noCameraEncode" field to the table of your virtual display equal to true. The vdisplay library does this by default. in cases where CustomDraw is used with this flag, your virtual display will receive the actual value from the renderer
this can be used, for example, to save an image to disk (methods for this are already implemented in the image library)
however, if you are just going to display the image on the displays, then provide the camera with a REAL DISPLAY. since transferring the virtual display disables very important camera optimizations
if you want to use the same camera from two different locations, use the camera.fork function to create a new instance with a separate counter and viewport. you can also use camera.fork with the value true to create a copy of all the parameters (fov, step, rotation, etc.)
to connect the camera via the antenna, use cameraTunnel component
advanced render settings (default / false):
{
lampLighting = true,
shadows = true,
smoothingTerrain = true,
simpleShadows = true,
sun = true, --is the solar disk being rendered
fog = true,
reduceAccuracy = true, --allows you to use fewer display effects in fog and simpleShadows, which increases performance in some cases
constDayLightValue = nil, --you can make a constant time of day
shadowMultiplier = 0.6,
sunPercentage = 0.003, --this value is the percentage of the sun from the size of the sky
simpleShadowMin = 0.3, --the minimum brightness of an object that a simple shadow can give
simpleShadowMax = 1, --the maximum brightness of an object that a simple shadow can give
customWaterColor = nil,
customChemicalColor = nil,
customOilColor = nil,
constColor = nil, --allows you to make all objects in one color
constSkyColor = nil, --by default, it depends on the time of day
customSunColor = nil, --you can change the color of the sun
constShapeColor = nil,
customLiftColor = nil,
constTerrainColor = nil, --you can make the whole terrain one color, even blue
constCharacterColor = nil,
constJointColor = nil,
constHarvestableColor = nil, --allows all Harvestables to be the same color, instead of their real color
constAssetsColor = nil, --you can set the constant color of assets so that it is always 1 and is not determined by the material
customTerrainColor_dirt = nil,
customTerrainColor_grass = nil,
customTerrainColor_sand = nil,
customTerrainColor_stone = nil,
}
advanced render settings (true / fastmode):
{
lampLighting = false,
shadows = false,
smoothingTerrain = false,
simpleShadows = true,
sun = true, --is the solar disk being rendered
fog = true,
reduceAccuracy = true, --allows you to use fewer display effects in fog and simpleShadows, which increases performance in some cases
constDayLightValue = nil, --you can make a constant time of day
shadowMultiplier = 0.6,
sunPercentage = 0.003, --this value is the percentage of the sun from the size of the sky
simpleShadowMin = 0.3, --the minimum brightness of an object that a simple shadow can give
simpleShadowMax = 1, --the maximum brightness of an object that a simple shadow can give
customWaterColor = nil,
customChemicalColor = nil,
customOilColor = nil,
constColor = nil, --allows you to make all objects in one color
constSkyColor = nil, --by default, it depends on the time of day
customSunColor = nil, --you can change the color of the sun
constShapeColor = nil,
customLiftColor = nil,
constTerrainColor = nil, --you can make the whole terrain one color, even blue
constCharacterColor = nil,
constJointColor = nil,
constHarvestableColor = nil, --allows all Harvestables to be the same color, instead of their real color
constAssetsColor = nil, --you can set the constant color of assets so that it is always 1 and is not determined by the material
customTerrainColor_dirt = nil,
customTerrainColor_grass = nil,
customTerrainColor_sand = nil,
customTerrainColor_stone = nil,
}
methods:
{
color = smcolor,
distance = distance,
fraction = (distance / maxdist),
deepDistance = (deep methods only) works almost the same as "distance", but the values are the values of the entire ray, not just this intersection segment. exists only at the last intersection,
deepFraction = (deep methods only) works almost the same as "fraction", but the values are the values of the entire ray, not just this intersection segment. exists only at the last intersection,
uuid = uuid,
type = character/shape/harvestable/lift/joint/terrain/asset/limiter,
normalWorld = some of the information from raycast,
raydata = (unrestricted camera only and unsafe mode only or if connected to an unsafe computer from SComputers integrable) raw raycast result, allows you to get a raw handle of an object and do anything with it
}
maxdist is the maximum distance for raycast in meters.unrestricted camera features (available in powertoys):
xray camera
--this code only works on unrestricted camera from power toys
local display = getComponent("display")
display.reset()
display.clear()
display.setSkipAtNotSight(true) --in order for the picture not to be updated for those who do not look at the screen
local camera = getComponents("camera")[1]
local fov = math.rad(60)
camera.setNonSquareFov(fov * (display.getWidth() / display.getHeight()), fov)
camera.setStep(512)
function callback_loop()
if _endtick then
display.clear()
display.forceFlush()
return
end
if display.getAudience() > 0 then
camera.deepDrawCustom(display, function (x, y, intersections)
local color = sm.color.new(0, 0, 0)
local shapeIntersectionsCount = 0
for i, intersection in ipairs(intersections) do
if intersection.type == "shape" then
shapeIntersectionsCount = shapeIntersectionsCount + 1
end
end
for i, intersection in ipairs(intersections) do
if intersection.type == "shape" then
color = color + (intersection.color * (i / shapeIntersectionsCount) * 0.2)
end
end
return color
end, 4)
display.flush()
end
end
local fastmode = false
local display = getComponent("display")
display.reset()
display.clear()
display.setSkipAtNotSight(true) --in order for the picture not to be updated for those who do not look at the screen
local camera = getComponent("camera")
local fov = math.rad(60)
camera.setNonSquareFov(fov * (display.getWidth() / display.getHeight()), fov)
camera.setStep(512)
function callback_loop()
if _endtick then
display.clear()
display.forceFlush()
return
end
if display.getAudience() > 0 then --if no one is looking at the screen at all, then the camera will not work
camera.drawOverlay(display, camera.drawAdvanced, {fastmode}, function(x, y, raydata)
if not raydata then return end
if raydata.type == "shape" then
return sm.color.new(math.random(), 0, 0)
elseif raydata.type == "character" then
return sm.color.new(0, math.random(), 0)
end
end, {})
display.flush()
end
end
if you just want to get a picture on the screen, then use this code
local fastmode = false
local display = getComponent("display")
display.reset()
display.clear()
display.setSkipAtNotSight(true) --in order for the picture not to be updated for those who do not look at the screen
local camera = getComponent("camera")
local fov = math.rad(60)
camera.setNonSquareFov(fov * (display.getWidth() / display.getHeight()), fov)
camera.setStep(512)
local renderSettings = {
lampLighting = not fastmode,
shadows = not fastmode,
smoothingTerrain = not fastmode,
simpleShadows = true,
sun = true, --is the solar disk being rendered
fog = true,
reduceAccuracy = true, --allows you to use fewer display effects in fog and simpleShadows, which increases performance in some cases
constDayLightValue = nil, --you can make a constant time of day
shadowMultiplier = 0.6,
sunPercentage = 0.003, --this value is the percentage of the sun from the size of the sky
simpleShadowMin = 0.3, --the minimum brightness of an object that a simple shadow can give
simpleShadowMax = 1, --the maximum brightness of an object that a simple shadow can give
customWaterColor = nil,
customChemicalColor = nil,
customOilColor = nil,
constColor = nil, --allows you to make all objects in one color
constSkyColor = nil, --by default, it depends on the time of day
customSunColor = nil, --you can change the color of the sun
constShapeColor = nil,
customLiftColor = nil,
constTerrainColor = nil, --you can make the whole terrain one color, even blue
constCharacterColor = nil,
constJointColor = nil,
constHarvestableColor = nil, --allows all Harvestables to be the same color, instead of their real color
constAssetsColor = nil, --you can set the constant color of assets so that it is always 1 and is not determined by the material
customTerrainColor_dirt = nil,
customTerrainColor_grass = nil,
customTerrainColor_sand = nil,
customTerrainColor_stone = nil,
}
function callback_loop()
if _endtick then
display.clear()
display.forceFlush()
return
end
if display.getAudience() > 0 then --if no one is looking at the screen at all, then the camera will not work
camera.drawAdvanced(display, renderSettings)
display.flush()
end
end
render under mushrooms
--this type of render does not have an optimization that transfers the render to the client, which leads to a strong ping in multiplayer
--in general, custom render is about 35% slower than the built-in similar options
--in addition, it does not have access to some of the data that advanced render uses
--in multiplayer, this code will run about 200% slower
local colors = require("colors")
local display = getComponents("display")[1]
display.reset()
display.clear()
display.setSkipAtNotSight(true) --in order for the picture not to be updated for those who do not look at the screen
local camera = getComponents("camera")[1]
local fov = math.rad(60)
camera.setNonSquareFov(fov * (display.getWidth() / display.getHeight()), fov)
camera.setStep(512)
function callback_loop()
if _endtick then
display.clear()
display.forceFlush()
return
end
if display.getAudience() > 0 then
camera.drawCustom(display, function (x, y, raydata)
if not raydata then
return sm.color.new(0, math.random(), math.random())
elseif raydata.type == "limiter" then
return sm.color.new(math.random(), math.random(), math.random())
elseif raydata.type == "terrain" then
return sm.color.new(0, math.random(), 0)
elseif raydata.type == "asset" then
return sm.color.new(math.random(), 0, 0)
end
return sm.color.new(colors.hsvToRgb(((x + y) / 32) % 1, 1, 1)) * (raydata.color or sm.color.new(1, 1, 1))
end)
display.flush()
end
end
It's like a thermal imager.
--this type of render does not have an optimization that transfers the render to the client, which leads to a strong ping in multiplayer
--in general, custom render is about 35% slower than the built-in similar options
--in addition, it does not have access to some of the data that advanced render uses
--in multiplayer, this code will run about 200% slower
local display = getComponents("display")[1]
display.reset()
display.clear()
display.setSkipAtNotSight(true) --in order for the picture not to be updated for those who do not look at the screen
local camera = getComponents("camera")[1]
local fov = math.rad(60)
camera.setNonSquareFov(fov * (display.getWidth() / display.getHeight()), fov)
camera.setStep(512)
function callback_loop()
if _endtick then
display.clear()
display.forceFlush()
return
end
if display.getAudience() > 0 then
camera.drawCustom(display, function (x, y, raydata)
if not raydata or raydata.type == "limiter" then
return 0x000000
elseif raydata.type == "terrain" then
return 0x00164e
elseif raydata.type == "asset" then
return 0x003554
elseif raydata.type == "character" then
return 0x880200
elseif raydata.type == "shape" then
return 0x875100
end
return 0
end)
display.flush()
end
end
saving an image from the camera to disk
the saving takes place in the scimg8 format, which has an 8-bit palette
saving takes place using the image library
--this simplest camera demonstrates the operation of the "image" library
--red button - make photo
--green button - show photo
local image = require("image")
local colors = require("colors")
local imagePath = "/image.scimg8"
local display = getComponent("display")
local disk = getComponent("disk")
local camera = getComponent("camera")
if input(colors.sm.Red[2]) then
disk.clear()
local img = image.new(display.getWidth(), display.getHeight(), sm.color.new(0, 0, 0))
img:fromCameraAll(camera, "drawAdvanced")
img:save8(disk, imagePath)
display.clear("0000ff")
display.drawText(1, 1, "photo maked!")
display.forceFlush()
elseif input(colors.sm.Green[2]) then
if disk.hasFile(imagePath) then
local img = image.load(disk, imagePath)
display.clear()
img:draw(display)
display.forceFlush()
else
display.clear("0000ff")
display.drawText(1, 1, "no photo")
display.forceFlush()
end
end
function callback_loop()
if _endtick then
display.clear()
display.forceFlush()
end
end