-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
252 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# osci3d- | ||
simple 3d oscilloscope for pure data based on pdlua with gui extensions | ||
|
||
Please check https://github.com/ben-wes/osci3d- for the latest source! | ||
|
||
![GitHub Image](osci3d~.png) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
#N canvas 324 80 867 747 12; | ||
#X declare -lib pdlua -path pdlua; | ||
#X obj 80 75 declare -lib pdlua -path pdlua; | ||
#X msg 504 122 zoom \$1; | ||
#X msg 340 202 grid \$1; | ||
#X obj 340 178 tgl 19 1 empty empty empty 0 -10 0 12 #fcfcfc #000000 #000000 1 1; | ||
#X obj 507 75 hsl 162 19 0.1 10 1 0 empty empty empty -2 -10 0 12 #fcfcfc #000000 #000000 0 1; | ||
#X floatatom 504 99 5 0 0 0 - - - 0; | ||
#X obj 507 162 hsl 162 19 1 64 1 0 empty empty empty -2 -10 0 12 #fcfcfc #000000 #000000 0 1; | ||
#X floatatom 504 186 5 0 0 0 - - - 0; | ||
#X msg 504 209 interval \$1; | ||
#X obj 507 249 hsl 162 19 2 1024 0 0 empty empty empty -2 -10 0 12 #fcfcfc #000000 #000000 0 1; | ||
#X floatatom 504 273 5 0 0 0 - - - 0; | ||
#X msg 504 296 buffer \$1; | ||
#X obj 507 336 hsl 162 19 1 10 0 0 empty empty empty -2 -10 0 12 #fcfcfc #000000 #000000 0 1; | ||
#X floatatom 504 360 5 0 0 0 - - - 0; | ||
#X msg 504 383 stroke \$1; | ||
#X obj 507 423 hsl 162 19 0 2 0 0 empty empty empty -2 -10 0 12 #fcfcfc #000000 #000000 0 1; | ||
#X floatatom 504 447 5 0 0 0 - - - 0; | ||
#X msg 504 470 perspective \$1; | ||
#X msg 273 202 reset; | ||
#X obj 208 266 osc~ 149.1; | ||
#X obj 80 218 osc~ 49.3; | ||
#X obj 144 242 osc~ 99.2; | ||
#X obj 80 291 osci3d~ 200; | ||
#X msg 340 75 color 0 60 120; | ||
#X obj 507 509 hsl 162 19 64 480 0 0 empty empty empty -2 -10 0 12 #fcfcfc #000000 #000000 0 1; | ||
#X floatatom 504 533 5 0 0 0 - - - 0; | ||
#X msg 504 556 resize \$1; | ||
#X text 76 499 initialized with [osci3d~ 200]; | ||
#X text 76 539 optional argument for initial size; | ||
#X msg 340 140 background 32 32 32; | ||
#X msg 340 99 color 180 255 0; | ||
#X connect 1 0 22 3; | ||
#X connect 2 0 22 3; | ||
#X connect 3 0 2 0; | ||
#X connect 4 0 5 0; | ||
#X connect 5 0 1 0; | ||
#X connect 6 0 7 0; | ||
#X connect 7 0 8 0; | ||
#X connect 8 0 22 3; | ||
#X connect 9 0 10 0; | ||
#X connect 10 0 11 0; | ||
#X connect 11 0 22 3; | ||
#X connect 12 0 13 0; | ||
#X connect 13 0 14 0; | ||
#X connect 14 0 22 3; | ||
#X connect 15 0 16 0; | ||
#X connect 16 0 17 0; | ||
#X connect 17 0 22 3; | ||
#X connect 18 0 22 3; | ||
#X connect 19 0 22 2; | ||
#X connect 20 0 22 0; | ||
#X connect 21 0 22 1; | ||
#X connect 23 0 22 3; | ||
#X connect 24 0 25 0; | ||
#X connect 25 0 26 0; | ||
#X connect 26 0 22 3; | ||
#X connect 29 0 22 3; | ||
#X connect 30 0 22 3; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,186 @@ | ||
local osci3d = pd.Class:new():register("osci3d~") | ||
|
||
function osci3d:initialize(sel, atoms) | ||
self.SIZE = type(atoms[1]) == "number" and atoms[1] or 480 | ||
self.inlets = {SIGNAL, SIGNAL, SIGNAL, DATA} | ||
self:reset() | ||
self.signalIndex = 1 | ||
self.cameraDistance = 6 | ||
self.gridLines = self:createGrid(-2, 2, 0.5) | ||
|
||
self:set_size(self.SIZE, self.SIZE) | ||
return true | ||
end | ||
|
||
function osci3d:reset() | ||
self.BUFFERSIZE = 512 | ||
self:set_buffer() | ||
self.SAMPLING_INTERVAL = 8 | ||
self.DRAW_GRID = 1 | ||
self.STROKE_WIDTH = 1 | ||
self.ZOOM = 1 | ||
self.COLOR = {Colors.foreground} | ||
self.BACKGROUND = {Colors.background} | ||
self.PERSPECTIVE = 1 | ||
self.rotationAngleX, self.rotationAngleY = 0, 0 | ||
self.rotationStartAngleX, self.rotationStartAngleY = 0, 0 | ||
end | ||
|
||
function osci3d:postinitialize() | ||
self.clock = pd.Clock:new():register(self, "tick") | ||
self.clock:delay(20) | ||
end | ||
|
||
function osci3d:finalize() | ||
self.clock:destruct() | ||
end | ||
|
||
function osci3d:tick() | ||
self:repaint() | ||
self.clock:delay(20) | ||
end | ||
|
||
function osci3d:createGrid(minVal, maxVal, step) | ||
local grid = {} | ||
for i = minVal, maxVal, step do | ||
table.insert(grid, {{i, 0, minVal}, {i, 0, maxVal}}) | ||
table.insert(grid, {{minVal, 0, i}, {maxVal, 0, i}}) | ||
end | ||
return grid | ||
end | ||
|
||
function osci3d:mouse_down(x, y) | ||
self.dragStartX, self.dragStartY = x, y | ||
end | ||
|
||
function osci3d:mouse_up(x, y) | ||
self.rotationStartAngleX, self.rotationStartAngleY = self.rotationAngleX, self.rotationAngleY | ||
end | ||
|
||
function osci3d:mouse_drag(x, y) | ||
self.rotationAngleY = self.rotationStartAngleY + ((x-self.dragStartX) / 50) | ||
self.rotationAngleX = self.rotationStartAngleX - ((y-self.dragStartY) / 50) | ||
end | ||
|
||
function osci3d:perform(in1, in2, in3) | ||
for i = 1, #in1, self.SAMPLING_INTERVAL do | ||
-- circular buffer | ||
self.signal[self.signalIndex] = {in1[i], in2[i], in3[i]} | ||
self.signalIndex = (self.signalIndex % self.BUFFERSIZE) + 1 | ||
end | ||
end | ||
|
||
function osci3d:paint(g) | ||
g.set_color(table.unpack(self.BACKGROUND)) | ||
g.fill_all() | ||
|
||
-- draw ground grid | ||
if self.DRAW_GRID == 1 then | ||
g.set_color(192, 192, 192) | ||
for i = 1, #self.gridLines do | ||
local lineFrom, lineTo = table.unpack(self.gridLines[i]) | ||
|
||
-- apply rotation to grid lines | ||
lineFrom = self:rotateY(lineFrom, self.rotationAngleY) | ||
lineFrom = self:rotateX(lineFrom, self.rotationAngleX) | ||
lineTo = self:rotateY(lineTo , self.rotationAngleY) | ||
lineTo = self:rotateX(lineTo , self.rotationAngleX) | ||
|
||
local startX, startY = self:projectVertex(lineFrom, self.ZOOM) | ||
local endX, endY = self:projectVertex( lineTo, self.ZOOM) | ||
if lineFrom[3] > -self.cameraDistance and lineTo[3] > -self.cameraDistance then | ||
g.draw_line(startX, startY, endX, endY, 1) | ||
end | ||
end | ||
end | ||
|
||
for i = 1, self.BUFFERSIZE do | ||
local offsetIndex = (i + self.signalIndex-2) % self.BUFFERSIZE + 1 | ||
local rotatedVertex = self:rotateY(self.signal[offsetIndex], self.rotationAngleY) | ||
self.rotatedSignal[i] = self:rotateX(rotatedVertex, self.rotationAngleX) | ||
end | ||
|
||
g.set_color(table.unpack(self.COLOR)) | ||
local p = path.start(self:projectVertex(self.rotatedSignal[1], self.ZOOM)) | ||
for i = 2, self.BUFFERSIZE do | ||
p:line_to(self:projectVertex(self.rotatedSignal[i], self.ZOOM)) | ||
end | ||
g.stroke_path(p, self.STROKE_WIDTH) | ||
end | ||
|
||
function osci3d:rotateY(vertex, angle) | ||
local x, y, z = table.unpack(vertex) | ||
local cosTheta = math.cos(angle) | ||
local sinTheta = math.sin(angle) | ||
local newX = x * cosTheta - z * sinTheta | ||
local newZ = x * sinTheta + z * cosTheta | ||
return {newX, y, newZ} | ||
end | ||
|
||
function osci3d:rotateX(vertex, angle) | ||
local x, y, z = table.unpack(vertex) | ||
local cosTheta = math.cos(angle) | ||
local sinTheta = math.sin(angle) | ||
local newY = y * cosTheta - z * sinTheta | ||
local newZ = y * sinTheta + z * cosTheta | ||
return {x, newY, newZ} | ||
end | ||
|
||
function osci3d:projectVertex(vertex) | ||
local scale = self.cameraDistance / (self.cameraDistance + vertex[3] * self.PERSPECTIVE) | ||
local screenX = self.SIZE / 2 + (vertex[1] * scale * self.ZOOM * self.SIZE * 0.25) | ||
local screenY = self.SIZE / 2 - (vertex[2] * scale * self.ZOOM * self.SIZE * 0.25) | ||
return screenX, screenY | ||
end | ||
|
||
function osci3d:set_buffer() | ||
self.signal = {} | ||
self.rotatedSignal = {} | ||
-- fill ring buffer | ||
for i = 1, self.BUFFERSIZE do | ||
self.signal[i] = {0, 0, 0} | ||
self.rotatedSignal[i] = {0, 0, 0} | ||
end | ||
end | ||
|
||
function osci3d:in_4_zoom(x) | ||
self.ZOOM = x[1] | ||
end | ||
|
||
function osci3d:in_4_grid(x) | ||
self.DRAW_GRID = x[1] | ||
end | ||
|
||
function osci3d:in_4_resize(x) | ||
self.SIZE = math.max(64, x[1]) | ||
self:set_size(self.SIZE, self.SIZE) | ||
end | ||
|
||
function osci3d:in_4_buffer(x) | ||
self.BUFFERSIZE = math.max(2, math.floor(x[1])) | ||
self:set_buffer() | ||
end | ||
|
||
function osci3d:in_4_interval(x) | ||
self.SAMPLING_INTERVAL = math.max(1, math.floor(x[1])) | ||
end | ||
|
||
function osci3d:in_4_stroke(x) | ||
self.STROKE_WIDTH = math.max(1, x[1]) | ||
end | ||
|
||
function osci3d:in_4_perspective(x) | ||
self.PERSPECTIVE = x[1] | ||
end | ||
|
||
function osci3d:in_4_reset() | ||
self:reset() | ||
end | ||
|
||
function osci3d:in_4_color(x) | ||
self.COLOR = {x[1], x[2], x[3]} | ||
end | ||
|
||
function osci3d:in_4_background(x) | ||
self.BACKGROUND = {x[1], x[2], x[3]} | ||
end |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.