We are about to switch to a new forum software. Until then we have removed the registration on this forum.
In Python, when we assign a value to a variable, it's assumed to be local
to its function, unless we declare it as global
. :-B
https://Py.Processing.org/reference/globals.html
def setup():
global font
font = createFont('Numbers.ttf', width/62, True)
But in case 'Numbers.ttf' is the only font you're gonna need in your whole sketch, you can simply use textFont() right there within setup(): :ar!
def setup():
textFont(createFont('Numbers.ttf', width/62, True))
No need for any global
font variable at all this time! :)>-
I've just started trying python mode, so I'm probably missing something very obvious, but essentially, my problem is that I can't seem to set the font. The code that pertains to my font looks something like this:
def setup (): font = createFont ("Numbers.ttf", width / 62)
def draw (): textFont (font, width / 62)
However, this gives me an error saying that font is not defined. I assumed that I couldn't use font outside of setup, so I tried putting "font = None" at the beginning, so that it would be a global variable, but then it just says that a null font was passed to textFont. I also can't put "font = createFont ("Numbers.ttf", width / 62)" at the beginning, because it must be in setup, and putting textFont in setup doesn't seem to work either. What am I doing wrong?
Hmm. For most people -- especially in a community with beginners in one or more languages -- I think it is better that they be really clear and not assume they have internalized Java operator precedence. Especially in a community with Java, JavaScript, Python, Ruby, and R flavors et cetera.
Here are operator precedence descriptions for ~60 languages, and while the whole extended C family is mostly the same on the basics, gotchas abound....
Bonus code golf game: Operator precedence: How wrong can I be?
Processing has several modes Android, Java, Python, Javascript etc, G4P only works in Java mode.
What do you mean by 'mode'?
Please note that we have moved to a new forum
Hi @solub -- I'm happy to answer on the new forum, but your updates on that thread haven't given me a concrete question. You've said things like "I think I’m getting closer…" and "I’m still stuck with the PeasyCam part" but I didn't know how to answer that. I know that your overall goal is "I want this code to work," but something more concrete would be helpful. I am familiar with PeasyCam.
That said, I'm also not experienced with GLSL Shaders. You are at the intersection of two minority communities in Processing -- few people know Python mode, fewer people know PShader, and fewest know both. This may be why you aren't getting a lot of uptake. If you break parts of it into narrower problems more people might have the experience to address it.
Posting the question back here since it seems I won't get any help on the new forum (?).
As some of you may already know I'm trying to make a Depth of Field effect in Python mode. I've recently stumbled onto this thread where I could get hold of a Proscene DOF demo sketch based on the following shaders:
depth.glsl
uniform float maxDepth;
void main() {
float depth = gl_FragCoord.z / gl_FragCoord.w;
gl_FragColor = vec4(vec3(1.0 - depth/maxDepth), 1.0);
}
dof.glsl
uniform sampler2D texture;
varying vec4 vertexture;
varying vec4 vertTexCoord;
uniform sampler2D tDepth;
uniform float maxBlur; // max blur amount
uniform float aperture; // aperture - bigger values for shallower depth of field
uniform float focus;
uniform float aspect;
void main() {
vec2 vUv = vertTexCoord.st;
vec2 aspectcorrect = vec2( 1.0, aspect );
vec4 depth1 = texture2D( tDepth, vUv );
float factor = depth1.x - focus;
vec2 dofblur = vec2 ( clamp( factor * aperture, -maxBlur, maxBlur ) );
vec2 dofblur9 = dofblur * 0.9;
vec2 dofblur7 = dofblur * 0.7;
vec2 dofblur4 = dofblur * 0.4;
vec4 col = vec4( 0.0 );
col += texture2D( texture, vUv.xy );
col += texture2D( texture, vUv.xy + ( vec2( 0.0, 0.4 ) * aspectcorrect ) * dofblur );
col += texture2D( texture, vUv.xy + ( vec2( 0.15, 0.37 ) * aspectcorrect ) * dofblur );
col += texture2D( texture, vUv.xy + ( vec2( 0.29, 0.29 ) * aspectcorrect ) * dofblur );
col += texture2D( texture, vUv.xy + ( vec2( -0.37, 0.15 ) * aspectcorrect ) * dofblur );
col += texture2D( texture, vUv.xy + ( vec2( 0.40, 0.0 ) * aspectcorrect ) * dofblur );
col += texture2D( texture, vUv.xy + ( vec2( 0.37, -0.15 ) * aspectcorrect ) * dofblur );
col += texture2D( texture, vUv.xy + ( vec2( 0.29, -0.29 ) * aspectcorrect ) * dofblur );
col += texture2D( texture, vUv.xy + ( vec2( -0.15, -0.37 ) * aspectcorrect ) * dofblur );
col += texture2D( texture, vUv.xy + ( vec2( 0.0, -0.4 ) * aspectcorrect ) * dofblur );
col += texture2D( texture, vUv.xy + ( vec2( -0.15, 0.37 ) * aspectcorrect ) * dofblur );
col += texture2D( texture, vUv.xy + ( vec2( -0.29, 0.29 ) * aspectcorrect ) * dofblur );
col += texture2D( texture, vUv.xy + ( vec2( 0.37, 0.15 ) * aspectcorrect ) * dofblur );
col += texture2D( texture, vUv.xy + ( vec2( -0.4, 0.0 ) * aspectcorrect ) * dofblur );
col += texture2D( texture, vUv.xy + ( vec2( -0.37, -0.15 ) * aspectcorrect ) * dofblur );
col += texture2D( texture, vUv.xy + ( vec2( -0.29, -0.29 ) * aspectcorrect ) * dofblur );
col += texture2D( texture, vUv.xy + ( vec2( 0.15, -0.37 ) * aspectcorrect ) * dofblur );
col += texture2D( texture, vUv.xy + ( vec2( 0.15, 0.37 ) * aspectcorrect ) * dofblur9 );
col += texture2D( texture, vUv.xy + ( vec2( -0.37, 0.15 ) * aspectcorrect ) * dofblur9 );
col += texture2D( texture, vUv.xy + ( vec2( 0.37, -0.15 ) * aspectcorrect ) * dofblur9 );
col += texture2D( texture, vUv.xy + ( vec2( -0.15, -0.37 ) * aspectcorrect ) * dofblur9 );
col += texture2D( texture, vUv.xy + ( vec2( -0.15, 0.37 ) * aspectcorrect ) * dofblur9 );
col += texture2D( texture, vUv.xy + ( vec2( 0.37, 0.15 ) * aspectcorrect ) * dofblur9 );
col += texture2D( texture, vUv.xy + ( vec2( -0.37, -0.15 ) * aspectcorrect ) * dofblur9 );
col += texture2D( texture, vUv.xy + ( vec2( 0.15, -0.37 ) * aspectcorrect ) * dofblur9 );
col += texture2D( texture, vUv.xy + ( vec2( 0.29, 0.29 ) * aspectcorrect ) * dofblur7 );
col += texture2D( texture, vUv.xy + ( vec2( 0.40, 0.0 ) * aspectcorrect ) * dofblur7 );
col += texture2D( texture, vUv.xy + ( vec2( 0.29, -0.29 ) * aspectcorrect ) * dofblur7 );
col += texture2D( texture, vUv.xy + ( vec2( 0.0, -0.4 ) * aspectcorrect ) * dofblur7 );
col += texture2D( texture, vUv.xy + ( vec2( -0.29, 0.29 ) * aspectcorrect ) * dofblur7 );
col += texture2D( texture, vUv.xy + ( vec2( -0.4, 0.0 ) * aspectcorrect ) * dofblur7 );
col += texture2D( texture, vUv.xy + ( vec2( -0.29, -0.29 ) * aspectcorrect ) * dofblur7 );
col += texture2D( texture, vUv.xy + ( vec2( 0.0, 0.4 ) * aspectcorrect ) * dofblur7 );
col += texture2D( texture, vUv.xy + ( vec2( 0.29, 0.29 ) * aspectcorrect ) * dofblur4 );
col += texture2D( texture, vUv.xy + ( vec2( 0.4, 0.0 ) * aspectcorrect ) * dofblur4 );
col += texture2D( texture, vUv.xy + ( vec2( 0.29, -0.29 ) * aspectcorrect ) * dofblur4 );
col += texture2D( texture, vUv.xy + ( vec2( 0.0, -0.4 ) * aspectcorrect ) * dofblur4 );
col += texture2D( texture, vUv.xy + ( vec2( -0.29, 0.29 ) * aspectcorrect ) * dofblur4 );
col += texture2D( texture, vUv.xy + ( vec2( -0.4, 0.0 ) * aspectcorrect ) * dofblur4 );
col += texture2D( texture, vUv.xy + ( vec2( -0.29, -0.29 ) * aspectcorrect ) * dofblur4 );
col += texture2D( texture, vUv.xy + ( vec2( 0.0, 0.4 ) * aspectcorrect ) * dofblur4 );
gl_FragColor = col / 41.0;
gl_FragColor.a = 1.0;
}
What I'd like is to be able to use those shaders using the PeasyCam library instead of the Proscene dependency.
In the sketch below I'm testing the shaders on a point cloud. I’m drawing the points on the scene
PGraphics and then passing it through 2 other PGraphics (canvas
and buf
). In theory it should work but I’m still stuck with the PeasyCam part at the very end of the script.
If I write:
cam.getState().apply(canvas)
: I get a DoF effect BUT on a 2D canvascam.getState().apply(scene)
: I get a 3D canvas BUT without a DoF effectAny help would be really appreciated.
add_library('peasycam')
liste = []
def setup():
global depthShader, dofShader, cam, canvas, buf, scene
size(900, 900, P3D)
cam = PeasyCam(this, 900)
cam.setMaximumDistance(width)
for e in range(100):
liste.append(PVector(random(width), random(height), random(width)))
depthShader = loadShader("depth.glsl")
dofShader = loadShader("dof.glsl")
depthShader.set("maxDepth", cam.getDistance())
dofShader.set("aspect", width / float(height))
dofShader.set("maxBlur", 0.015)
dofShader.set("aperture", 0.02)
canvas = createGraphics(width, height, P3D)
canvas.shader(depthShader)
buf = createGraphics(width, height, P3D)
buf.shader(dofShader)
scene = createGraphics(width, height, P3D)
frameRate(1000)
def draw():
scene.beginDraw()
scene.background(255)
scene.stroke(0)
scene.strokeWeight(10)
for e in liste:
scene.point(e.x-width/2, e.y-height/2, e.z-height/2)
scene.endDraw()
canvas.beginDraw()
canvas.image(scene, 0, 0)
canvas.endDraw()
buf.beginDraw()
dofShader.set("focus", map(mouseX, 0, width, -0.5, 1.5))
dofShader.set("tDepth", canvas)
buf.image(scene, 0, 0)
buf.endDraw()
cam.beginHUD()
image(buf, 0, 0)
cam.endHUD()
cam.getState().apply(scene)
Hello! I was wondering if it was possible to run like a processing sketch (or maybe even something more simplified) within a processing sketch. I put this under Python mode since that is what I am currently using but if it is possible I don't care what mode is required... Anyway, I know that the open() can be used to open applications in a new window, but as I said, is it possible to run a processing sketch within a processing sketch? Hope this is enough information... Thanks for reading!
@GotoLoop: Yes. Discourse does not ignore any language suffix, it only supports specific ones (and they are case sensitive): the py
label does not work, but python
label does work (or at least, it is recognized by highlight.js and tags the html).
@kfrajer: Unfortunately I don't think the plan is to migrate the forum -- I think the plan is to start a new forum with brand new accounts and only new posts. For that reason old user bookmarks must be saved (not exported, just save the bookmark list pages with your private account to html) before they become inaccessible when the forum goes static (no account login) sometime in the coming weeks. I've seen that there is a Vanilla-Discourse forum migration tool, but from looking at the guides it looks like it is a batch migration tool -- I don't not sure it can be used to migrate individual account bookmark data.
Edit: it looks like you want want: ```python, which creates:
Each language highlighting can have alias for it. :)>-
And <pre lang=py></pre>
is what I actually use for posting Python Mode sketches here. B-)
And as I've already mentioned, GitHub also recognizes ```py for Python code. ;)
I've created a new post at:
https://discourse.processing.org/t/forum-line-numbers-on-code/225
...for discussion of this. Discourse uses highlight.js, so the question is if it has an override, and if Discourse's markdown parser correctly passes that through.
Edit: it looks like you want want: ```python
, which creates:
<pre><code class='lang-python'></code></pre>
Besides no double-click to select code block for copy & the lack of line numbering, we can't select which programming language the code block belongs to. ~X(
In this forum, I can use <pre lang=py></pre>
if I wanted a Python color highlighting. $-)
On GitHub, I'd go w/
```py
for Python or ```pde
for Processing. \m/
But Discourse seems to completely ignore the language suffix after the ```
. :(
Here's my Python Mode attempt. However, it's not working yet, it's just pitch black! :-&
This statement crashes the sketch: geombuffer.update(pg_render)
within resizeScreen().
Even when following exactly what it does, it doesn't seem to render anything. :o3
public void update(PGraphics3D pg_src){
resize(pg_src.width, pg_src.height);
pg_geom.beginDraw();
updateMatrices(pg_src);
pg_geom.blendMode(PConstants.REPLACE);
pg_geom.clear();
pg_geom.shader(shader);
pg_geom.noStroke();
scene_display.display(pg_geom);
pg_geom.endDraw();
}
So I'm at loss about it! Sorry. X_X Try finding help on diwi or jdf. ^#(^
"""
* Depth of Field (DoF) (1.20)
* Thomas Diewald (diwi) (2017-Oct-07)
* GitHub.com/diwi/PixelFlow/blob/master/examples/Miscellaneous/
* DepthOfField_Demo/DepthOfField_Demo.java
* Refactor by GoToLoop (v1.4.2) (2018-May-18) (PDE v3.3.5)
* Forum.Processing.org/two/discussion/27905/
* converting-java-code-to-python#Item_20
"""
add_library('PixelFlow')
add_library('peasycam')
from com.jogamp.opengl import GL2
from processing.opengl import PGL
from java.util import Formatter, Locale
from jarray import zeros
formatter = Formatter(Locale.ENGLISH)
POSITION = 'position: (%8.2f, %8.2f, %8.2f)\n'
ROTATION = 'rotation: (%8.2f, %8.2f, %8.2f)\n'
LOOK__AT = 'look-at: (%8.2f, %8.2f, %8.2f)\n'
DISTANCE = 'distance: (%8.2f)\n'
TITLE = __file__[:-5] + ' [fps %6.2f]'
BB_SIZE = 800
BB_OFFSET = BB_SIZE >> 2
BB_TOTAL = BB_SIZE + BB_OFFSET
BB_COORD, BB_DIAM = -BB_TOTAL, BB_TOTAL << 1
XMIN, XMAX = -BB_SIZE, BB_SIZE
YMIN, YMAX = -BB_SIZE, BB_SIZE
ZMIN, ZMAX = 0, BB_SIZE
BOX_DIAM = BB_OFFSET + BB_OFFSET/20
SPH_MIN_D, SPH_MAX_D = BB_OFFSET >> 2, BB_OFFSET >> 1
BOXES, SPHERES = 50, 50
BOX_RANGE, SPH_RANGE = tuple(range(BOXES)), tuple(range(SPHERES))
CROSS_S, ZFAR = 10, 6000
MULT_BLUR, FPS = 30, 60
BLUR_POW, RAD60 = pow(MULT_BLUR, 1/3.0), 60*DEG_TO_RAD
BASE_COL, CROSS_COL = 0x80FFFFFF, 0xd0FFFFFF
SEED, FIXED_SEED = 0, False
FULLSCREEN, RESIZABLE = False, False
apply_dof, alt_render = False, False
resized = zeros(1, 'z')
cube_smooth, cube_facets = DwCube(4), DwCube(2)
shp_scene = pg_render = pg_dof = pg_tmp = None
def settings():
if FULLSCREEN: fullScreen(P3D)
else: size(this.displayWidth*9/10, this.displayHeight*9/10, P3D)
noSmooth()
def setup():
frameRate(FPS); cursor(CROSS)
global surf, canv
surf, canv = this.surface, this.graphics
if RESIZABLE: surf.resizable = True
surf.setLocation(this.displayWidth - width >> 1, 8)
global peasy
peasy = PeasyCam(this, -4.083, -6.096, 7, 2000)
peasy.setRotations(1.085, -.477, 2.91)
global context, dw_filter, dof, param, geombuffer, magnifier
context = DwPixelFlow(this)
dw_filter = DwFilter.get(context)
context.print(); context.printGL()
dof = DepthOfField(context)
param = dof.param
param.mult_blur = MULT_BLUR
class SceneDisplay(DwSceneDisplay):
def display(_, canvas): displayScene(canvas)
geombuffer = DwScreenSpaceGeometryBuffer(context, SceneDisplay())
mag_h = height/3
magnifier = DwMagnifier(this, 4, 0, height - mag_h, mag_h, mag_h)
def draw():
setTitle(); resizeScreen(); displaySceneWrap(pg_render)
dw_filter.gamma.apply(pg_render, pg_render)
apply_dof and applyDoF()
renderScene()
def keyPressed():
global apply_dof, alt_render, shp_scene
k = chr(keyCode) if key != CODED else keyCode
if k == 'P' or k == BACKSPACE: noLoop() if this.looping else loop()
elif k == 'C' or k == CONTROL: printCam()
elif k == ' ': apply_dof ^= True
elif k == SHIFT: alt_render ^= True
elif k == ENTER or k == RETURN: shp_scene = None
def applyDoF():
geom = geombuffer.pg_geom
dw_filter.gaussblur.apply(geom, geom, pg_tmp, BLUR_POW)
param.focus_pos[0] = map(mouseX + .5, 0, width, 00, 1)
param.focus_pos[1] = map(mouseY + .5, 0, height, 1, 0)
dof.apply(pg_render, pg_dof, geombuffer)
dw_filter.copy.apply(pg_dof, pg_render)
def renderScene():
pg = geombuffer.pg_geom if alt_render else pg_render
magnifier.apply(pg, mouseX, mouseY)
magnifier.displayTool()
DwUtils.beginScreen2D(canv)
# peasy.beginHUD()
blendMode(REPLACE); image(pg, 0, 0)
magnifier.display(pg, 0, height - magnifier.h)
fpx = param.focus_pos[0] * width
fpy = (1 - param.focus_pos[1]) * height
blendMode(EXCLUSION); strokeCap(PROJECT); stroke(CROSS_COL)
line(fpx - CROSS_S, fpy, fpx + CROSS_S, fpy)
line(fpx, fpy - CROSS_S, fpx, fpy + CROSS_S)
blendMode(BLEND)
# peasy.endHUD()
DwUtils.endScreen2D(canv)
def resizeScreen():
global pg_render, pg_dof, pg_tmp
w = width; h = height
perspective(RAD60, float(w)/h, 2, ZFAR)
peasy.feed()
happened = resized[0] = False
pg_render = DwUtils.changeTextureSize(this, pg_render, w, h, 8, resized)
happened |= resized[0]
resized[0] = False
pg_dof = DwUtils.changeTextureSize(this, pg_dof, w, h, 0, resized)
happened |= resized[0]
resized[0] = False
pg_tmp = DwUtils.changeTextureSize(this, pg_tmp, w, h, 0, resized,
GL2.GL_RGBA16F, GL2.GL_RGBA, GL2.GL_FLOAT)
# geombuffer.update(pg_render)
happened |= geombuffer.resize(pg_render.width, pg_render.height)
geombuffer.pg_geom.beginDraw()
# geombuffer.updateMatrices(pg_render)
DwUtils.copyMatrices(pg_render, geombuffer.pg_geom)
geombuffer.pg_geom.blendMode(REPLACE)
geombuffer.pg_geom.clear()
geombuffer.pg_geom.shader(geombuffer.shader)
geombuffer.pg_geom.noStroke()
geombuffer.scene_display.display(geombuffer.pg_geom)
geombuffer.pg_geom.endDraw()
return happened | resized[0]
def displaySceneWrap(canvas):
DwUtils.copyMatrices(canv, canvas)
canvas.beginDraw()
canvas.background(2)
displayScene(canvas)
canvas.endDraw()
def displayScene(canvas):
canvas.directionalLight(255, 255, 255, 200, 600, 400)
canvas.directionalLight(255, 255, 255, -200, -600, -400)
canvas.ambientLight(64, 64, 64)
if canvas is geombuffer.pg_geom:
canvas.background(-1)
canvas.pgl.clearColor(1, 1, 1, ZFAR)
canvas.pgl.clear(PGL.COLOR_BUFFER_BIT)
global shp_scene
if not shp_scene: shp_scene = makeShape()
canvas.shape(shp_scene)
def makeShape():
scene = createShape(GROUP)
FIXED_SEED and randomSeed(SEED)
with pushStyle():
colorMode(HSB, 360, 1, 1); noStroke()
for i in BOX_RANGE:
px = random(XMIN, XMAX); py = random(YMIN, YMAX)
sx = random(BOX_DIAM, BOX_DIAM); sy = random(BOX_DIAM, BOX_DIAM)
sz = random(ZMIN, ZMAX)
fill(random(-45, 45), 1, random(.1, 1))
shp_box = createShape(BOX, sx, sy, sz)
shp_box.translate(px, py, sz*.5)
scene.addChild(shp_box)
for i in SPH_RANGE:
px = random(XMIN, XMAX); py = random(YMIN, YMAX)
pz = random(ZMIN, ZMAX); rr = random(SPH_MIN_D, SPH_MAX_D)
fill(random(205, 245), 1, random(.1, 1))
shp_sphere = createShape(PShape.GEOMETRY)
shp_sphere.scale(rr); shp_sphere.translate(px, py, pz)
scene.addChild(shp_sphere)
DwMeshUtils.createPolyhedronShape(shp_sphere, cube_smooth, 1, 4, True)\
if i&1 else\
DwMeshUtils.createPolyhedronShape(shp_sphere, cube_facets, 1, 4, False)
fill(BASE_COL)
scene.addChild(createShape(RECT, BB_COORD, BB_COORD, BB_DIAM, BB_DIAM))
return scene
def clearFormatter(f): f.out().setLength(0)
def setTitle():
clearFormatter(formatter)
surf.title = formatter.format(TITLE, frameRate).toString()
def printCam():
pos = peasy.position; rot = peasy.rotations
lat = peasy.getLookAt(); dis = peasy.distance
clearFormatter(formatter)
print formatter.\
format(POSITION, *pos).format(ROTATION, *rot).\
format(LOOK__AT, *lat).format(DISTANCE, dis)
Hi @solub! It took a long time, but I've just finished refactoring "Depth_of_Field.pde". #:-S
Now that I've reorganized this sketch, I'm ready to convert it to a ".pyde" file. :)>-
Just w8 a lil' more. Stay w/ the latest ".pde" file for now: :-\"
/**
* Depth of Field (DoF) (1.20)
* Thomas Diewald (diwi) (2017-Oct-07)
* GitHub.com/diwi/PixelFlow/blob/master/examples/Miscellaneous/
* DepthOfField_Demo/DepthOfField_Demo.java
* Refactor by GoToLoop (v1.4.2) (2018-May-18) (PDE v3.3.5)
* Forum.Processing.org/two/discussion/27905/converting-java-code-to-python#Item_18
*/
import com.thomasdiewald.pixelflow.java.DwPixelFlow;
import com.thomasdiewald.pixelflow.java.geometry.DwIndexedFaceSetAble;
import com.thomasdiewald.pixelflow.java.geometry.DwCube;
import com.thomasdiewald.pixelflow.java.geometry.DwMeshUtils;
import com.thomasdiewald.pixelflow.java.imageprocessing.filter.DepthOfField;
import com.thomasdiewald.pixelflow.java.imageprocessing.filter.DwFilter;
import com.thomasdiewald.pixelflow.java.render.skylight.DwSceneDisplay;
import com.thomasdiewald.pixelflow.java.render.skylight.DwScreenSpaceGeometryBuffer;
import com.thomasdiewald.pixelflow.java.utils.DwMagnifier;
import com.thomasdiewald.pixelflow.java.utils.DwUtils;
import peasy.PeasyCam;
import com.jogamp.opengl.GL2;
import static java.util.Locale.ENGLISH;
import java.util.Formatter;
final Formatter formatter = new Formatter(ENGLISH);
static final String POSITION = "position: (%8.2f, %8.2f, %8.2f)\n";
static final String ROTATION = "rotation: (%8.2f, %8.2f, %8.2f)\n";
static final String LOOK__AT = "look-at: (%8.2f, %8.2f, %8.2f)\n";
static final String DISTANCE = "distance: (%8.2f)\n";
final String TITLE = getClass().getName() + " [fps %6.2f]";
static final int BB_SIZE = 800, BB_OFFSET = BB_SIZE >> 2;
static final int BB_TOTAL = BB_SIZE + BB_OFFSET;
static final int BB_COORD = -BB_TOTAL, BB_DIAM = BB_TOTAL << 1;
static final int XMIN = -BB_SIZE, XMAX = BB_SIZE;
static final int YMIN = -BB_SIZE, YMAX = BB_SIZE;
static final int ZMIN = 0, ZMAX = BB_SIZE;
static final int BOX_DIAM = BB_OFFSET + BB_OFFSET/20;
static final int SPH_MIN_D = BB_OFFSET >> 2, SPH_MAX_D = BB_OFFSET >> 1;
static final int BOXES = 50, SPHERES = 50;
static final int CROSS_S = 10, ZFAR = 6000;
static final int MULT_BLUR = 30, BLUR_POW = (int) pow(MULT_BLUR, 1/3.0);
static final float RAD60 = 60*DEG_TO_RAD, FPS = 60;
static final color BASE_COL = 0x80FFFFFF, CROSS_COL = 0xd0FFFFFF;
static final long SEED = 0;
static final boolean FIXED_SEED = false;
static final boolean FULLSCREEN = false, RESIZABLE = false;
boolean apply_dof = false, alt_render = false;
final boolean[] resized = new boolean[1];
final DwIndexedFaceSetAble cube_smooth = new DwCube(4), cube_facets = new DwCube(2);
PGraphics3D pg_render, pg_dof, pg_tmp;
PShape shp_scene;
PeasyCam peasy;
DwPixelFlow context;
DwFilter dw_filter;
DepthOfField dof;
DwScreenSpaceGeometryBuffer geombuffer;
DwMagnifier magnifier;
void settings() {
if (FULLSCREEN) fullScreen(P3D);
else size(displayWidth*9/10, displayHeight*9/10, P3D);
noSmooth();
}
void setup() {
frameRate(FPS);
cursor(CROSS);
if (RESIZABLE) getSurface().setResizable(true);
getSurface().setLocation(displayWidth - width >> 1, 8);
peasy = new PeasyCam(this, -4.083, -6.096, 7, 2000);
peasy.setRotations(1.085, -.477, 2.91);
dw_filter = DwFilter.get(context = new DwPixelFlow(this));
context.print();
context.printGL();
dof = new DepthOfField(context);
dof.param.mult_blur = MULT_BLUR;
final DwSceneDisplay scene_display = new DwSceneDisplay() {
@ Override final public void display(final PGraphics3D canvas) {
displayScene(canvas);
}
};
geombuffer = new DwScreenSpaceGeometryBuffer(context, scene_display);
final int mag_h = height/3;
magnifier = new DwMagnifier(this, 4, 0, height - mag_h, mag_h, mag_h);
}
void draw() {
final PGraphics canv = getGraphics();
final DepthOfField.Param param = dof.param;
setTitle();
resizeScreen();
displaySceneWrap(pg_render, canv);
dw_filter.gamma.apply(pg_render, pg_render);
if (apply_dof) applyDoF(param);
renderScene(param, canv);
}
void keyPressed() {
final int k = keyCode;
if (k == ENTER | k == RETURN) shp_scene = null;
else if (k == 'C' | k == CONTROL) printCam();
else if (k == 'P' | k == BACKSPACE) looping ^= true;
else if (k == ' ') apply_dof ^= true;
else if (k == SHIFT) alt_render ^= true;
}
void applyDoF(final DepthOfField.Param param) {
final PGraphicsOpenGL geom = geombuffer.pg_geom;
dw_filter.gaussblur.apply(geom, geom, pg_tmp, BLUR_POW);
param.focus_pos[0] = map(mouseX + .5, 0, width, 00, 1);
param.focus_pos[1] = map(mouseY + .5, 0, height, 1, 0);
dof.apply(pg_render, pg_dof, geombuffer);
dw_filter.copy.apply(pg_dof, pg_render);
}
void renderScene(final DepthOfField.Param param, final PGraphics canv) {
final PGraphics pg = alt_render? geombuffer.pg_geom : pg_render;
magnifier.apply(pg, mouseX, mouseY);
magnifier.displayTool();
DwUtils.beginScreen2D(canv);
//peasy.beginHUD();
blendMode(REPLACE);
image(pg, 0, 0);
magnifier.display(pg, 0, height - magnifier.h);
final float fpx = param.focus_pos[0] * width;
final float fpy = (1 - param.focus_pos[1]) * height;
blendMode(EXCLUSION);
strokeCap(PROJECT);
stroke(CROSS_COL);
line(fpx - CROSS_S, fpy, fpx + CROSS_S, fpy);
line(fpx, fpy - CROSS_S, fpx, fpy + CROSS_S);
blendMode(BLEND);
//peasy.endHUD();
DwUtils.endScreen2D(canv);
}
boolean resizeScreen() { // dynamically resize render-targets
final int w = width, h = height;
perspective(RAD60, (float) w/h, 2, ZFAR);
peasy.feed();
boolean happened = resized[0] = false;
pg_render = DwUtils.changeTextureSize(this, pg_render, w, h, 8, resized);
happened |= resized[0];
resized[0] = false;
pg_dof = DwUtils.changeTextureSize(this, pg_dof, w, h, 0, resized);
happened |= resized[0];
resized[0] = false;
pg_tmp = DwUtils.changeTextureSize(this, pg_tmp, w, h, 0, resized,
GL2.GL_RGBA16F, GL2.GL_RGBA, GL2.GL_FLOAT);
geombuffer.update(pg_render);
return happened | resized[0];
}
void displaySceneWrap(final PGraphics3D canvas, final PGraphics canv) {
DwUtils.copyMatrices((PGraphicsOpenGL) canv, canvas);
canvas.beginDraw();
canvas.background(2);
displayScene(canvas);
canvas.endDraw();
}
void displayScene(final PGraphics3D canvas) {
canvas.directionalLight(255, 255, 255, 200, 600, 400);
canvas.directionalLight(255, 255, 255, -200, -600, -400);
canvas.ambientLight(64, 64, 64);
if (canvas == geombuffer.pg_geom) {
canvas.background(-1);
canvas.pgl.clearColor(1, 1, 1, ZFAR);
canvas.pgl.clear(PGL.COLOR_BUFFER_BIT);
}
if (shp_scene == null) shp_scene = makeShape();
canvas.shape(shp_scene);
}
PShape makeShape() {
final PShape scene = createShape(GROUP);
pushStyle();
colorMode(HSB, 360, 1, 1);
noStroke();
if (FIXED_SEED) randomSeed(SEED);
for (int i = 0; i < BOXES; ++i) {
final float px = random(XMIN, XMAX), py = random(YMIN, YMAX);
final float sx = random(BOX_DIAM, BOX_DIAM), sy = random(BOX_DIAM, BOX_DIAM);
final float sz = random(ZMIN, ZMAX);
fill(random(-45, 45), 1, random(.1, 1));
final PShape shp_box = createShape(BOX, sx, sy, sz);
shp_box.translate(px, py, sz*.5);
scene.addChild(shp_box);
}
for (int i = 0; i < SPHERES; ++i) {
final float px = random(XMIN, XMAX), py = random(YMIN, YMAX);
final float pz = random(ZMIN, ZMAX), rr = random(SPH_MIN_D, SPH_MAX_D);
fill(random(205, 245), 1, random(.1, 1));
final PShape shp_sphere = createShape(PShape.GEOMETRY);
shp_sphere.scale(rr);
shp_sphere.translate(px, py, pz);
scene.addChild(shp_sphere);
if ((i&1) == 0)
DwMeshUtils.createPolyhedronShape(shp_sphere, cube_facets, 1, 4, false);
else
DwMeshUtils.createPolyhedronShape(shp_sphere, cube_smooth, 1, 4, true);
}
fill(BASE_COL);
scene.addChild(createShape(RECT, BB_COORD, BB_COORD, BB_DIAM, BB_DIAM));
popStyle();
return scene;
}
static final void clearFormatter(final Formatter f) {
((StringBuilder) f.out()).setLength(0);
}
void setTitle() {
clearFormatter(formatter);
getSurface().setTitle(formatter.format(TITLE, frameRate).toString());
}
void printCam() {
final float[] pos = peasy.getPosition();
final float[] rot = peasy.getRotations();
final float[] lat = peasy.getLookAt();
final double dis = peasy.getDistance();
clearFormatter(formatter);
println(formatter.
format(POSITION, pos[0], pos[1], pos[2]).
format(ROTATION, rot[0], rot[1], rot[2]).
format(LOOK__AT, lat[0], lat[1], lat[2]).
format(DISTANCE, dis));
}
I really would like some help with that Python script... it's been weeks i'm working on that Depth of Field effect without finding a proper solution. Could you give me a hand finding what's wrong with the .pyde script ?
In other words, and to make it easier to understand...
In the working Java sketch I have something like this:
public void setup() {
...
public boolean resizeScreen(){
boolean[] RESIZED = {false};
pg_render = DwUtils.changeTextureSize(this, pg_render, width, height, 8, RESIZED);
pg_dof = DwUtils.changeTextureSize(this, pg_dof , width, height, 0, RESIZED);
pg_tmp = DwUtils.changeTextureSize(this, pg_tmp , width, height, 0, RESIZED, GL2.GL_RGBA16F, GL2.GL_RGBA, GL2.GL_FLOAT);
peasycam.feed();
perspective(60 * DEG_TO_RAD, width/(float)height, 2, 6000);
return RESIZED[0];
}
public void draw() {
resizeScreen();
displaySceneWrap(pg_render);
DwFilter.get(context).gamma.apply(pg_render, pg_render);
...
Python version
def setup():
...
def resizeScreen():
RESIZED = [False]
pg_render = DwUtils.changeTextureSize(this, None, width, height, 8, RESIZED)
pg_dof = DwUtils.changeTextureSize(this, None, width, height, 0, RESIZED)
pg_tmp = DwUtils.changeTextureSize(this, None, width, height, 0, RESIZED, GL2.GL_RGBA16F, GL2.GL_RGBA, GL2.GL_FLOAT)
cam.feed()
perspective(60 * DEG_TO_RAD, width/float(height), 2, 6000)
return RESIZED[0]
def draw():
resizeScreen()
displaySceneWrap(pg_render)
DwFilter.get(context).gamma.apply(pg_render, pg_render)
...
However, although the Python version looks similar to the Java script, it doesn't work (Processing suddenly quits).
When I add: global pg_render, pg_dof, pg_tmp
just below def resizeScreen()
the script runs but then I get the errors I mentionned before:
GammaCorrection.apply shader | GL_ERROR: invalid operation
GammaCorrection.apply | GL_ERROR: invalid operation
GammaCorrection.apply | GL_ERROR: invalid framebuffer operation
Would love your insight @GoToLoop
I'm back with another question, sorry. I still have a persistent issue with the resizeScreen()
function and more particularly with thepg_render
and pg_tmp
grahics buffers variables.
When running the .pyde script I get the following error messages:
GammaCorrection.apply shader | GL_ERROR: invalid operation
GammaCorrection.apply | GL_ERROR: invalid operation
GammaCorrection.apply | GL_ERROR: invalid framebuffer operation
This occurs at line 110 (Java script) or 58 (Python version):
DwFilter.get(context).gamma.apply(pg_render, pg_render)
Do you know what could be the problem here ?
Here below, for comparison purposes:
Java
import java.util.Locale;
import com.jogamp.opengl.GL2;
import com.thomasdiewald.pixelflow.java.DwPixelFlow;
import com.thomasdiewald.pixelflow.java.geometry.DwCube;
import com.thomasdiewald.pixelflow.java.geometry.DwMeshUtils;
import com.thomasdiewald.pixelflow.java.imageprocessing.filter.DepthOfField;
import com.thomasdiewald.pixelflow.java.imageprocessing.filter.DwFilter;
import com.thomasdiewald.pixelflow.java.render.skylight.DwSceneDisplay;
import com.thomasdiewald.pixelflow.java.render.skylight.DwScreenSpaceGeometryBuffer;
import com.thomasdiewald.pixelflow.java.utils.DwMagnifier;
import com.thomasdiewald.pixelflow.java.utils.DwUtils;
import peasy.*;
import processing.core.PApplet;
import processing.core.PConstants;
import processing.core.PShape;
import processing.opengl.PGL;
import processing.opengl.PGraphics3D;
boolean START_FULLSCREEN = !true;
int viewport_w = 1280;
int viewport_h = 720;
int viewport_x = 230;
int viewport_y = 0;
// camera control
PeasyCam peasycam;
// library context
DwPixelFlow context;
PGraphics3D pg_render;
PGraphics3D pg_dof;
PGraphics3D pg_tmp;
DepthOfField dof;
DwScreenSpaceGeometryBuffer geombuffer;
boolean APPLY_DOF = true;
public void settings() {
if(START_FULLSCREEN){
viewport_w = displayWidth;
viewport_h = displayHeight;
viewport_x = 0;
viewport_y = 0;
fullScreen(P3D);
} else {
size(viewport_w, viewport_h, P3D);
}
smooth(0);
}
public void setup() {
// camera
peasycam = new PeasyCam(this, -4.083, -6.096, 7.000, 1300);
peasycam.setRotations( 1.085, -0.477, 2.910);
// main library context
context = new DwPixelFlow(this);
context.print();
context.printGL();
// callback for scene display (used in GBAA)
DwSceneDisplay scene_display = new DwSceneDisplay() {
@Override
public void display(PGraphics3D canvas) {
displayScene(canvas);
}
};
geombuffer = new DwScreenSpaceGeometryBuffer(context, scene_display);
dof = new DepthOfField(context);
frameRate(1000);
}
// dynamically resize render-targets
public boolean resizeScreen(){
boolean[] RESIZED = {false};
pg_render = DwUtils.changeTextureSize(this, pg_render, width, height, 8, RESIZED);
pg_dof = DwUtils.changeTextureSize(this, pg_dof , width, height, 0, RESIZED);
pg_tmp = DwUtils.changeTextureSize(this, pg_tmp , width, height, 0, RESIZED, GL2.GL_RGBA16F, GL2.GL_RGBA, GL2.GL_FLOAT);
peasycam.feed();
perspective(60 * DEG_TO_RAD, width/(float)height, 2, 6000);
return RESIZED[0];
}
public void draw() {
resizeScreen();
displaySceneWrap(pg_render);
DwFilter.get(context).gamma.apply(pg_render, pg_render);
int mult_blur = 30;
geombuffer.update(pg_render);
DwFilter.get(context).gaussblur.apply(geombuffer.pg_geom, geombuffer.pg_geom, pg_tmp, (int) Math.pow(mult_blur, 0.33f));
//// dof.param.focus = map(mouseX, 0, width, 0, 1);
dof.param.focus_pos = new float[]{0.5f, 0.5f};
dof.param.focus_pos[0] = map(mouseX+0.5f, 0, width , 0, 1);
dof.param.focus_pos[1] = map(mouseY+0.5f, 0, height, 1, 0);
dof.param.mult_blur = mult_blur;
dof.apply(pg_render, pg_dof, geombuffer);
DwFilter.get(context).copy.apply(pg_dof, pg_render);
DwUtils.beginScreen2D(g);
{
blendMode(REPLACE);
clear();
image(pg_render, 0, 0);
}
DwUtils.endScreen2D(g);
}
public void displaySceneWrap(PGraphics3D canvas){
canvas.beginDraw();
DwUtils.copyMatrices((PGraphics3D) this.g, canvas);
// background
canvas.blendMode(PConstants.BLEND);
canvas.background(2);
displayScene(canvas);
canvas.endDraw();
}
// render something
public void displayScene(PGraphics3D canvas){
// lights
canvas.directionalLight(255, 255, 255, 200,600,400);
canvas.directionalLight(255, 255, 255, -200,-600,-400);
canvas.ambientLight(64, 64, 64);
if(canvas == geombuffer.pg_geom){
canvas.background(255, 255);
canvas.pgl.clearColor(1, 1, 1, 6000);
canvas.pgl.clear(PGL.COLOR_BUFFER_BIT);
}
sceneShape(canvas);
}
PShape shp_scene;
public void sceneShape(PGraphics3D canvas){
if(shp_scene != null){
canvas.shape(shp_scene);
return;
}
shp_scene = createShape(GROUP);
int num_spheres = 50;
float bb_size = 800;
float xmin = -bb_size;
float xmax = +bb_size;
float ymin = -bb_size;
float ymax = +bb_size;
float zmin = 0;
float zmax = +bb_size;
colorMode(HSB, 360, 1, 1);
DwCube cube_smooth = new DwCube(4);
DwCube cube_facets = new DwCube(2);
for(int i = 0; i < num_spheres; i++){
float px = random(xmin, xmax);
float py = random(ymin, ymax);
float pz = random(zmin, zmax);
float rr = random(50) + 50;
boolean facets = true;//(i%2 == 0);
float off = 20;
float base = 225;
float hsb_h = base + random(-off,off);
float hsb_s = 1;
float hsb_b = random(0.1f,1.0f);
int shading = color(hsb_h, hsb_s, hsb_b);
PShape shp_sphere = createShape(PShape.GEOMETRY);
if(facets){
DwMeshUtils.createPolyhedronShape(shp_sphere, cube_facets, 1, 4, false);
} else {
DwMeshUtils.createPolyhedronShape(shp_sphere, cube_smooth, 1, 4, true);
}
shp_sphere.setStroke(!true);
shp_sphere.setStroke(color(0));
shp_sphere.setStrokeWeight(0.01f / rr);
shp_sphere.setFill(true);
shp_sphere.setFill(shading);
shp_sphere.resetMatrix();
shp_sphere.scale(rr);
shp_sphere.translate(px, py, pz);
shp_scene.addChild(shp_sphere);
}
}
Python
add_library('PixelFlow')
add_library('peasycam')
from com.jogamp.opengl import GL2
import java.util.Locale
liste = []
viewport_w = 1280
viewport_h = 720
viewport_x = 0
viewport_y = 0
FS = False
def settings():
global viewport_w, viewport_h
if FS:
viewport_w = displayWidth
viewport_h = displayHeight
viewport_x = 0
viewport_y = 0
fullScreen(P3D)
else:
size(viewport_w, viewport_h, P3D)
smooth(0)
def setup():
global context, scene_display, geombuffer, dof, cam
cam = PeasyCam(this, -4.083, -6.096, 7.000, 1300)
context = DwPixelFlow(this)
context.print()
context.printGL()
scene_display = MySceneDisplay()
geombuffer = DwScreenSpaceGeometryBuffer(context, scene_display)
dof = DepthOfField(context)
def resizeScreen():
global pg_render, pg_dof, pg_tmp
RESIZED = [False]
pg_render = DwUtils.changeTextureSize(this, None, width, height, 8, RESIZED)
pg_dof = DwUtils.changeTextureSize(this, None, width, height, 0, RESIZED)
pg_tmp = DwUtils.changeTextureSize(this, None, width, height, 0, RESIZED, GL2.GL_RGBA16F, GL2.GL_RGBA, GL2.GL_FLOAT)
cam.feed()
perspective(60 * DEG_TO_RAD, width/float(height), 2, 6000)
return RESIZED[0]
def draw():
resizeScreen()
displaySceneWrap(pg_render)
DwFilter.get(context).gamma.apply(pg_render, pg_render)
mult_blur = 30
geombuffer.update(pg_render)
DwFilter.get(context).gaussblur.apply(geombuffer.pg_geom, geombuffer.pg_geom, pg_tmp, int(Math.pow(mult_blur, 0.33)))
dof.param.focus_pos = float(0.5, 0.5)
dof.param.focus_pos[0] = map(mouseX+0.5, 0, width, 0, 1)
dof.param.focus_pos[1] = map(mouseY+0.5, 0, height, 1, 0)
dof.param.mult_blur = mult_blur
dof.apply(pg_render, pg_dof, geombuffer)
DwFilter.get(context).copy.apply(pg_dof, pg_render)
DwUtils.beginScreen2D(g)
blendMode(REPLACE)
clear()
image(pg.render,0,0)
DwUtils.endScreen2D(g)
def displaySceneWrap(canvas):
canvas.beginDraw()
DwUtils.copyMatrices(this.g, canvas)
canvas.blendMode(PConstants.BLEND)
canvas.background(2)
displayScene(canvas)
canvas.endDraw()
def displayScene(canvas):
canvas.directionalLight(255, 255, 255, 200,600,400)
canvas.directionalLight(255, 255, 255, -200,-600,-400)
canvas.ambientLight(64, 64, 64)
if canvas == geombuffer.pg_geom:
canvas.background(255, 255)
canvas.pgl.clearColor(1, 1, 1, 6000)
canvas.pgl.clear(PGL.COLOR_BUFFER_BIT)
sceneShape(canvas)
def sceneShape(canvas):
shp_scene = createShape(GROUP)
if shp_scene != None:
canvas.shape(shp_scene)
return
num_spheres = 50
bb_size = 800
xmin = -bb_size
xmax = +bb_size
ymin = -bb_size
ymax = +bb_size
zmin = 0
zmax = +bb_size
colorMode(HSB, 360, 1, 1)
cube_smooth = DwCube(4)
cube_facets = DwCube(2)
for i in range(num_spheres):
px = random(xmin, xmax)
py = random(ymin, ymax)
pz = random(zmin, zmax)
facets = True
off = 20
base =225
hsb_h = base + random(-off, off)
hsb_s = 1
hsb_b = random(0.1, 1.0)
shading = color(hsb_h, hsb_s, hsb_b)
shp_sphere = createShape(PShape.GEOMETRY)
if facets:
DwMeshUtils.createPolyhedronShape(shp_sphere, cube_facets, 1, 4, False)
else:
DwMeshUtils.createPolyhedronShape(shp_sphere, cube_smooth, 1, 4, True)
shp_sphere.setStroke(False);
shp_sphere.setStroke(color(0));
shp_sphere.setStrokeWeight(0.01 / rr);
shp_sphere.setFill(True);
shp_sphere.setFill(shading);
shp_sphere.resetMatrix();
shp_sphere.scale(rr);
shp_sphere.translate(px, py, pz);
shp_scene.addChild(shp_sphere);
class MySceneDisplay(DwSceneDisplay):
def display(_, canvas): displayScene(canvas)
Processing as a "programming language", rather than an actual library, caters more for the artistic folks. :D
And Processing's already got the 3 most important languages for them covered, and even beyond: $-)
Of course there are also R as R Mode, Clojure as Quill and Ruby as Ruby-Processing. Maybe more. <:-P
And similar to Processing we've even got C/C++ as Arduino & openFrameworks. \m/
Not sure it will help but here is my two cents.
If I'm not mistaken the best you can do to achieve this (connecting points from a WB_Point[] array) with the Hemesh library is using the alphaTriangulate3D()
method.
Here's a quick example, it's in Python but really easy to understand:
add_library('hemesh')
phi = (sqrt(5) + 1) / 2 - 1
angle = phi * 2 * PI
n_points, radius = 300, 200
liste = []
def setup():
global triangles, render
size(600, 600, P3D)
smooth(8)
render = WB_Render(this)
for p in range(n_points):
lon = angle * p
lon /= 2 * PI; lon -= floor(lon); lon *= 2 * PI
if lon > PI: lon -= 2 * PI
lat = asin(-1 + 2 * p / float(n_points))
new_points = WB_Point(radius * cos(lat) * cos(lon), radius * cos(lat) * sin(lon), radius * sin(lat))
liste.append(new_points)
triangulation = WB_Triangulate.alphaTriangulate3D(liste)
triangles = triangulation.getAlphaTriangles(radius+1)
noFill()
beginShape(TRIANGLES)
def draw():
background(255)
translate(width/2, height/2)
for i in range(0, len(triangles), 3):
point(liste[triangles[i]].xd(), liste[triangles[i]].yd(), liste[triangles[i]].zd())
render.drawTriangle(liste[triangles[i]], liste[triangles[i+1]], liste[triangles[i+2]])
liste
is the WB_Point[] array list alphaTriangulate3D(liste)
method. triangulation.getAlphaTriangles(radius+1)
Now, if you want to create a mesh from an array of points distributed on a 3D plane rather than around a sphere, I'd suggest to use the Triangulate library instead. You can find a 2D example here and a 3D example here.
Hi @gersart,
I realise you posted this question more than a year ago and that you've probably moved on but I feel like it'd be better to provide an answer anyway, hoping it will be useful for future forum users.
I had the same problem you're describing (trying to compute 3D triangulation with Hemesh) and with the precious help of this this forum I could come up with a rather simple solution: using the Triangulate library by Nicolas Clavaud instead.
The library is available here
You can find an example sketch here
For a 3D example sketch you can have a look at the script I posted on this thread (post from may the 3rd, it's in Python but really easy to understand).
Hope that helps.
... GL2.GL_RGBA16F, GL2.GL_RGBA, GL2.GL_FLOAT don't seem to work.
Have you imported the interface GL2 from package com.jogamp.opengl before using its constants? :-\"
http://JogAmp.org/deployment/jogamp-next/javadoc/jogl/javadoc/com/jogamp/opengl/GL2.html
import com.jogamp.opengl.GL2;
--> from com.jogamp.opengl import GL2
(because there's no such thing as
PGraphics3D pg_render;
in Python)
PGraphics3D is the declared datatype which variable pg_render accepts to be assigned w/ under Java.
Under Python however, variables hold any datatype reference. No restriction at all! 8->
Under Java, all reference datatype fields are initialized w/ null
by default. ~O)
Under Python, simply assign them w/ None
in order to have the same default behavior. :\">
PGraphics3D pg_render;
--> pg_render = None
Take a look at the link below in order to learn the default initial value for each Java datatype: ~O)
https://Docs.Oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html