28. November 2012
Wir hatten wiederum die Aufgabe, ein Programm zu erweitern, welches ein "Force Field" mit beeinflussbaren Punkten in einem Raster bereitstellt. Man kann die Punkte mit einem Linksklick anziehen und neu auch mit Rechtsklick abstossen. Ich habe mich entschieden, mich nicht nur mit dem Spielen mit Parametern zu beschäftigen, sondern aus dem Prinzip etwas anderes zu bauen. Ich hatte die Idee, eine dreidimensionale Oberfläche anheben und absenken zu lassen. Dies würde auf dem gleichen Prinzip basieren, nur dass nicht einzelne Punkte abgestossen werden, sondern die Punkte als Gitter verbunden sind. Arbeit mit Meshes Schnell erkannte ich die Schwierigkeit, die einzelnen Punkte zu verbinden und ein funktionierendes Netz (Mesh) herzustellen. Ich begann daher, nach Libraries zu suchen und wurde fündig bei der Library "He_Mesh", welche Funktionen zur Erstellung und Arbeit mit 3D-Meshes bereitstellt. Ergebnis Mit der Libary schaffte ich es nach viel viel Ausprobieren endlich ein flaches Netz hinzubekommen, welches aus einzelnen Vertexes besteht. Die Funktionalität des "Force Fieldes" habe ich übernommen, es ist möglich mit der Maus auf dem Netz einen Bereich anzuheben und mit einem Rechtsklick abzusenken. Danach senken sich die Erhebungen langsam wieder zurück (Damping). Mit Parametern kann ich Aussehen, Smoothing, Die Mesh-Linien, Flächen etc. beeinflussen.import wblut.hemesh.modifiers.*; import wblut.core.processing.*; import wblut.hemesh.creators.*; import wblut.hemesh.core.*; HE_Mesh mesh; HEC_Grid grid; WB_Render render; int radius = 100; HashMap<HE_Vertex,PVector> vertexOffsets; float damper = 0.994; boolean dampSurface = true; boolean drawFaces = true; boolean drawEdges = false; boolean smooth = true; float rotationValue = 0.0; void setup() { size(800, 800, P3D); camera(width/2.0, height/1.5, (height/1.5) / tan(PI*30.0 / 180.0), width/2.0, height/2.0, 0, 0, 1, 0); grid = new HEC_Grid(80,80,width * 1.5,height * 1.5); mesh=new HE_Mesh(grid); vertexOffsets = new HashMap<HE_Vertex,PVector>(); Iterator<HE_Vertex> vItr=mesh.vItr(); HE_Vertex v; while (vItr.hasNext ()) { v=vItr.next(); vertexOffsets.put(v,new PVector(0,0,0)); } render=new WB_Render(this); } void draw() { rotateX(radians(45)); translate(width/2,height/2,0); rotateZ(radians(rotationValue)); translate(-width/2,-height/2,0); updateSurface(); background(#939393); directionalLight(255, 255, 255, 1, 1, -1); directionalLight(127, 127, 127, -1, -1, 1); translate(width/2, height/2, 0); fill(255); noStroke(); if(drawFaces) { if(smooth) { render.drawFacesSmooth(mesh); } else { render.drawFaces(mesh); } } stroke(0); if(drawEdges) { render.drawEdges(mesh); } } void pressSurface(HE_Vertex v, int direction) { PVector vertexOffset = vertexOffsets.get(v); PVector mouseDist = new PVector(mouseX - width/2 - (int)v.x,mouseY - height/2 - (int)v.y); if(mouseDist.mag() < radius) { float offsetLevel = map(mouseDist.mag(),0,radius,8,0); PVector offsetVector = PVector.mult(new PVector(0,0,offsetLevel),direction); vertexOffset.add(offsetVector); } } void updateSurface() { Iterator<HE_Vertex> vItr=mesh.vItr(); HE_Vertex v; while (vItr.hasNext()) { v=vItr.next(); PVector vertexOffset = vertexOffsets.get(v); if(mousePressed && mouseButton == LEFT) { pressSurface(v, 1); } else if(mousePressed && mouseButton == RIGHT) { pressSurface(v, -1); } v.z = vertexOffset.z; if(dampSurface) { vertexOffset.mult(damper); } } } void keyPressed() { switch(key) { case 'q': dampSurface = ! dampSurface; break; case 'w': drawFaces = ! drawFaces; break; case 'e': drawEdges = ! drawEdges; break; case 'r': smooth = ! smooth; break; case 'a': rotationValue+=10; break; case 's': rotationValue-=10; break; default: break; } }