I just completed a class definition of a gage with a circular dial with a “bar” that progresses clockwise as the value increases.
The mesh and shader technique originated as a function that defined 180 degrees of a dial and was the work of someone else. I redefined it as a class that would display a full 360 degrees and added additional graphics.
When I try and display four such dials on the screen at the same time the program crashes within two to three minutes.
QUESTION: Is the mesh/shader technique too taxing on the system, is there an inherent bug with mesh/shader or am I doing something wrong?
I’m running all this on a 3rd gen iPad (32Gigs with 2.5Gigs available), OS ver 9.3.5 using a version of Codea that has not been updated in forever due to the age of the iPad.
Thank you for any tips or solutions to this problem.
-- SpaceX-type dials using Mesh and Shader
-- Version 4
-- NOTE: Code is best viewed in landscape mode.
supportedOrientations(LANDSCAPE_ANY) -- preferred orientation
displayMode(STANDARD)
function setup()
X = WIDTH/2
Y = HEIGHT/2
backColor = color(40,40,50)
FPS,MAX,MIN = 0,0,200 -- For frames-per-second calc.
parameter.number("spdFrac", 0, 1, 0)
--[[
parameter.number("altFrac", 0, 1, 0)
parameter.number("tempFrac", 0, 1, 0)
parameter.number("pressFrac", 0, 1, 0)
--]]
-- NOTE: If dial radii and colors are all identical then
-- define them here ahead of Speedo variable defs.
dialRad = 150
secondColor = color(127, 127, 127, 255)
primeColor = color(0,255,0)
-- Speedo definitions:
-- "speed"
title = "Speed"
spdMax = 500
speedLoc = vec2(200,HEIGHT-200)
--speedLoc = vec2(X,Y) -- for testing
rad = dialRad
c1 = secondColor
c2 = primeColor
speed = Speedo(title,rad,c1,c2)
--[[
-- "altitude"
title = "Altitude"
altMax = 10000
altitudeLoc = vec2(WIDTH-200,HEIGHT-200)
--rad = dialRad
--c1 = secondColor
--c2 = primeColor
altitude = Speedo(title,rad,c1,c2)
-- "temp"
title = "Temp"
tempMax = 212
tempLoc = vec2(200,200)
--rad = dialRad
--c1 = secondColor
--c2 = primeColor
temp = Speedo(title,rad,c1,c2)
-- "pressure"
title = "Pressure"
pressMax = 500
pressLoc = vec2(WIDTH-200, 200)
--rad = dialRad
--c1 = secondColor
--c2 = primeColor
pressure = Speedo(title,rad,c1,c2)
--]]
end -- end of setup()
function draw()
background(backColor)
-- massage speed-data
spdVal = spdMax*spdFrac
ea1 = (360*spdFrac-180)*-1
sa2 = ea1
pushMatrix()
translate(speedLoc.x,speedLoc.y)
speed:draw(spdVal,ea1,sa2)
popMatrix()
--[[
-- massage altitude-data
altVal = altMax*altFrac
ea1 = (360*altFrac-180)*-1
sa2 = ea1
pushMatrix()
translate(altitudeLoc.x,altitudeLoc.y)
altitude:draw(altVal,ea1,sa2)
popMatrix()
-- massage temp-data
tempVal = tempMax*tempFrac
ea1 = (360*tempFrac-180)*-1
sa2 = ea1
pushMatrix()
translate(tempLoc.x,tempLoc.y)
temp:draw(tempVal,ea1,sa2)
popMatrix()
-- massage altitude-data
pressVal = pressMax*pressFrac
ea1 = (360*pressFrac-180)*-1
sa2 = ea1
pushMatrix()
translate(pressLoc.x,pressLoc.y)
pressure:draw(pressVal,ea1,sa2)
popMatrix()
--]]
MaxMin() -- frames-per-sec calculation
end
function MaxMin()
-- Calculate frames-per-second
FPS = 1/DeltaTime
if FPS > MAX then
MAX = FPS
elseif FPS < MIN then
MIN = FPS
end
fill(255, 255, 255, 255/2)
fontSize(20)
text(string.format("FPS = %.0f", FPS,FPS), X, 60)
text(string.format("MAX = %.0f", MAX,MAX), X, 40)
text(string.format("MIN = %.0f", MIN,MIN), X, 20)
end
Speedo = class()
-- Mesh m1 and m2 definition by others but the rest is by Scotty.
-- Speedo is my term for any type of dial that looks like it belongs on a SpaceX-type display.
function Speedo:init(title, rad, c1, c2)
-- incoming args:
self.title = title
self.rad = rad
self.c1 = c1
self.c2 = c2
-- gage loc
self.x = 0
self.y = 0
-- range of gage
self.sa1 = -180
self.ea2 = 180
-- for min/max lines
self.maxAng = 185
self.minAng = -185
-- min/max flags
self.minFlag = 0
self.maxFlag = 0
-- min/max values
self.minValue = 0
self.maxValue = 0
end
function Speedo:draw(val,ea1,sa2)
self.val = val
self.ea1 = ea1
self.sa2 = sa2 - .1 -- NOTE: Without subtracting a small amount from sa2 the
-- resulting dial is displayed fully lite up when dial value is
-- at zero. This remedies that condition.
local m1 = mesh()
local m2 = mesh()
local sWidth = self.rad * .25
local size = (1 - sWidth/self.rad) * 0.5
if c1 == nil then c1 = color(background()) end
-- Secondary, or background, mesh
m1:addRect(self.x, self.y, self.rad * 2, self.rad * 2)
m1.shader = shader("Patterns:Arc")
m1.shader.size = size -- size
m1.shader.color = self.c1 -- color
m1.shader.a1 = math.rad(self.sa1) -- start angle
m1.shader.a2 = math.rad(self.ea1) -- end angle
m1:draw()
-- Primary mesh
m2:addRect(self.x, self.y, self.rad * 2, self.rad * 2)
m2.shader = shader("Patterns:Arc")
m2.shader.size = size
m2.shader.color = self.c2
m2.shader.a1 = math.rad(self.sa2)
m2.shader.a2 = math.rad(self.ea2)
m2:draw()
-- Ellipses
pushStyle()
stroke(self.c2)
strokeWidth(self.rad*.015) -- 1.5% of dial rad
noFill()
ellipseMode(CENTER)
ellipse(self.x,self.y, (self.rad*2+sWidth/2.25)+strokeWidth())
ellipse(self.x,self.y, (self.rad*2-sWidth*2.25))
-- Text
fill(c2)
fill(69, 255, 0, 77)
fontSize(sWidth)
text(self.title, self.x,self.y+sWidth/2)
text(string.format("%.0f",self.val), self.x,self.y-sWidth/2)
-- min-max values
fontSize(sWidth/2)
fill(38, 0, 255, 255)
text(string.format("Max = %.0f",self.maxValue), self.x,self.y+sWidth*2)
fill(255, 0, 0, 255)
text(string.format("Min = %.0f",self.minValue), self.x,self.y-sWidth*2)
fontSize(sWidth)
-- Rotatable value line with max/min value.
-- 180 is the "low point" of dial while -180 is the "high point".
-- This seems backwards but that is how the dial was designed.
if self.ea1 < self.maxAng then -- high-point is increasing
self.maxAng = self.ea1 -- save max angle
self.maxValue = self.val -- save max value
if self.ea1 == self.maxAng then
self.maxFlag = 1
end
elseif self.ea1 > self.maxAng then -- value decreasing from high point
self.maxFlag = 0
self.minFlag = 1
end
if self.maxFlag == 0 then
if self.ea1 > self.minAng then -- low-point is decreasing
self.minAng = self.ea1 -- save min angle
self.minValue = self.val -- save min value
end
end
lineCapMode(SQUARE)
strokeWidth(strokeWidth()*1.5)
-- Display max line
pushMatrix()
stroke(0, 0, 255, 255)
rotate(self.maxAng+180)
line(self.x-self.rad, self.y, self.x-self.rad+sWidth, self.y)
popMatrix()
-- Display "value" line
pushMatrix()
stroke(0, 128, 0, 255)
rotate(self.ea1+180)
line(self.x-self.rad, self.y, self.x-self.rad+sWidth, self.y)
popMatrix()
-- Display "Zero" line
stroke(0, 0, 0, 255)
line(self.x-self.rad, self.y, self.x-self.rad+sWidth, self.y)
-- Display min line
if self.minFlag == 1 then
pushMatrix()
stroke(255, 0, 0, 255)
rotate(self.minAng+180)
line(self.x-self.rad, self.y, self.x-self.rad+sWidth, self.y)
popMatrix()
end
--[[
-- Display values for testing only:
fontSize(20)
fill(255, 255, 255, 255)
vLoc = self.rad/2
vInc = 25
vLoc = vLoc-vInc
text("ea1 = " ..string.format("%.f",self.ea1), self.x, self.y+vLoc)
vLoc = vLoc-vInc
text("minAng = " ..string.format("%.f",self.minAng), self.x, self.y+vLoc)
vLoc = vLoc-vInc
text("maxAng = " ..string.format("%.f",self.maxAng), self.x, self.y+vLoc)
vLoc = vLoc-vInc
text("minFlag = "..self.minFlag, self.x, self.y+vLoc)
vLoc = vLoc-vInc
text("maxFlag = "..self.maxFlag, self.x, self.y+vLoc)
--]]
popStyle()
end