Created
January 10, 2021 15:48
-
-
Save elbosso/5cea6a07d0c238b315acfc2643b5826a to your computer and use it in GitHub Desktop.
Source to generate somewhat pretty graphics (abstract, generative art) - see also https://mastodon.social/@elbosso/105526549344085753 Creates "/tmp/render.png" upon execution in three different modes: 0,1,2. Tons of other parameters adjustable by altering the source code. Inspired by https://pixelfed.social/p/y6nH/38965 and https://www.scratchap…
This file contains hidden or 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
/* | |
* Copyright (c) 2021. | |
* | |
* Juergen Key. Alle Rechte vorbehalten. | |
* | |
* Weiterverbreitung und Verwendung in nichtkompilierter oder kompilierter Form, | |
* mit oder ohne Veraenderung, sind unter den folgenden Bedingungen zulaessig: | |
* | |
* 1. Weiterverbreitete nichtkompilierte Exemplare muessen das obige Copyright, | |
* die Liste der Bedingungen und den folgenden Haftungsausschluss im Quelltext | |
* enthalten. | |
* 2. Weiterverbreitete kompilierte Exemplare muessen das obige Copyright, | |
* die Liste der Bedingungen und den folgenden Haftungsausschluss in der | |
* Dokumentation und/oder anderen Materialien, die mit dem Exemplar verbreitet | |
* werden, enthalten. | |
* 3. Weder der Name des Autors noch die Namen der Beitragsleistenden | |
* duerfen zum Kennzeichnen oder Bewerben von Produkten, die von dieser Software | |
* abgeleitet wurden, ohne spezielle vorherige schriftliche Genehmigung verwendet | |
* werden. | |
* | |
* DIESE SOFTWARE WIRD VOM AUTOR UND DEN BEITRAGSLEISTENDEN OHNE | |
* JEGLICHE SPEZIELLE ODER IMPLIZIERTE GARANTIEN ZUR VERFUEGUNG GESTELLT, DIE | |
* UNTER ANDEREM EINSCHLIESSEN: DIE IMPLIZIERTE GARANTIE DER VERWENDBARKEIT DER | |
* SOFTWARE FUER EINEN BESTIMMTEN ZWECK. AUF KEINEN FALL IST DER AUTOR | |
* ODER DIE BEITRAGSLEISTENDEN FUER IRGENDWELCHE DIREKTEN, INDIREKTEN, | |
* ZUFAELLIGEN, SPEZIELLEN, BEISPIELHAFTEN ODER FOLGENDEN SCHAEDEN (UNTER ANDEREM | |
* VERSCHAFFEN VON ERSATZGUETERN ODER -DIENSTLEISTUNGEN; EINSCHRAENKUNG DER | |
* NUTZUNGSFAEHIGKEIT; VERLUST VON NUTZUNGSFAEHIGKEIT; DATEN; PROFIT ODER | |
* GESCHAEFTSUNTERBRECHUNG), WIE AUCH IMMER VERURSACHT UND UNTER WELCHER | |
* VERPFLICHTUNG AUCH IMMER, OB IN VERTRAG, STRIKTER VERPFLICHTUNG ODER | |
* UNERLAUBTE HANDLUNG (INKLUSIVE FAHRLAESSIGKEIT) VERANTWORTLICH, AUF WELCHEM | |
* WEG SIE AUCH IMMER DURCH DIE BENUTZUNG DIESER SOFTWARE ENTSTANDEN SIND, SOGAR, | |
* WENN SIE AUF DIE MOEGLICHKEIT EINES SOLCHEN SCHADENS HINGEWIESEN WORDEN SIND. | |
* | |
*/ | |
//https://pixelfed.social/p/y6nH/38965 | |
//https://www.scratchapixel.com/lessons/3d-basic-rendering/perspective-and-orthographic-projection-matrix/building-basic-perspective-projection-matrix | |
import java.awt.*; | |
import java.awt.geom.Path2D; | |
import java.awt.image.BufferedImage; | |
import java.io.IOException; | |
import java.util.Arrays; | |
import java.awt.geom.Point2D; | |
class RandomColor | |
{ | |
private static final float golden_ratio_conjugate = 0.618033988749895f; | |
float h; | |
float s; | |
float b; | |
float alpha; | |
private final java.util.Random random; | |
public RandomColor() | |
{ | |
this(System.currentTimeMillis(),1,1,1); | |
} | |
public RandomColor(long seed,float s,float b,float alpha) | |
{ | |
super(); | |
random=new java.util.Random(seed); | |
init(s,b,alpha); | |
} | |
private final void init(float s,float b,float alpha) | |
{ | |
h=random.nextFloat(); | |
this.s=s; | |
this.b=b; | |
this.alpha=alpha; | |
} | |
public Color next() | |
{ | |
java.awt.Color rv=java.awt.Color.getHSBColor(h, s, b); | |
float []rgb=rv.getRGBComponents(null); | |
rv=new java.awt.Color(rgb[0], rgb[1], rgb[2], alpha); | |
h += golden_ratio_conjugate; | |
h %= 1; | |
return rv; | |
} | |
} | |
interface Constants | |
{ | |
final static int X=0; | |
final static int Y=1; | |
final static int Z=2; | |
final static int W=3; | |
} | |
class Vec3 implements Constants | |
{ | |
final double[] elements=new double[3]; | |
public Vec3() | |
{ | |
super(); | |
for(int i=0;i< elements.length;++i) | |
elements[i]=0.0; | |
} | |
public Vec3(double... src) | |
{ | |
this(); | |
for(int i=0;i<src.length;++i) | |
elements[i]=src[i]; | |
} | |
public double getX() | |
{ | |
return elements[X]; | |
} | |
public double getY() | |
{ | |
return elements[Y]; | |
} | |
public double getZ() | |
{ | |
return elements[Z]; | |
} | |
public Vec3 addAndNew(double... coords) | |
{ | |
double[] el=Arrays.copyOf(elements,elements.length); | |
for(int i=0;i<coords.length;++i) | |
el[i]+=coords[i]; | |
return new Vec3(el); | |
} | |
public java.awt.geom.Point2D toPoint2D() | |
{ | |
return new Point2D.Double(elements[X],elements[Y]); | |
} | |
@Override | |
public String toString() | |
{ | |
return "Vec3{" + | |
"elements=" + Arrays.toString(elements) + | |
'}'; | |
} | |
} | |
public class Matrix44 implements Constants | |
{ | |
final double[][] elements=new double[4][4]; | |
static Matrix44 buildPerspectiveMatrix(double angleOfViewInDeg, double near, double far) | |
{ | |
Matrix44 rv=new Matrix44(); | |
// set the basic projection matrix | |
double scale = 1.0 / java.lang.Math.tan(angleOfViewInDeg * 0.5 * Math.PI / 180.0); | |
//double scale = 1.0 / java.lang.Math.tan(java.lang.Math.toRadians(angleOfViewInDeg)); | |
rv.elements[0][0] = scale; // scale the x coordinates of the projected point | |
rv.elements[1][1] = scale; // scale the y coordinates of the projected point | |
rv.elements[2][2] = -far / (far - near); // used to remap z to [0,1] | |
rv.elements[3][2] = -far * near / (far - near); // used to remap z [0,1] | |
rv.elements[2][3] = -1; // set w = -z | |
rv.elements[3][3] = 0; | |
return rv; | |
} | |
static Matrix44 buildAffineTranslateMatrix(double tx, double ty, double tz) | |
{ | |
Matrix44 rv=new Matrix44(); | |
rv.elements[0][0]=1; | |
rv.elements[1][1]=1; | |
rv.elements[2][2]=1; | |
rv.elements[3][0]=tx; | |
rv.elements[3][1]=ty; | |
rv.elements[3][2]=tz; | |
rv.elements[3][3]=1; | |
return rv; | |
} | |
static Matrix44 buildAffineScaleMatrix(double sx, double sy, double sz) | |
{ | |
Matrix44 rv=new Matrix44(); | |
rv.elements[0][0]=sx; | |
rv.elements[1][1]=sy; | |
rv.elements[2][2]=sz; | |
rv.elements[3][3]=1; | |
return rv; | |
} | |
static Matrix44 buildAffineRotateAroundZMatrix(double thetaInDeg) | |
{ | |
Matrix44 rv=new Matrix44(); | |
double thetaRan=java.lang.Math.toRadians(thetaInDeg); | |
rv.elements[0][0]=java.lang.Math.cos(thetaRan); | |
rv.elements[0][1]=-java.lang.Math.sin(thetaRan); | |
rv.elements[1][0]=java.lang.Math.sin(thetaRan); | |
rv.elements[1][1]=java.lang.Math.cos(thetaRan); | |
rv.elements[2][2]=1; | |
rv.elements[3][3]=1; | |
return rv; | |
} | |
static Matrix44 buildIdentity(double thetaInDeg) | |
{ | |
Matrix44 rv=new Matrix44(); | |
double thetaRan=java.lang.Math.toRadians(thetaInDeg); | |
rv.elements[0][0]=1; | |
rv.elements[1][1]=1; | |
rv.elements[2][2]=1; | |
rv.elements[3][3]=1; | |
return rv; | |
} | |
public Matrix44() | |
{ | |
super(); | |
for(int row=0;row<4;++row) | |
{ | |
for(int col=0;col<4;++col) | |
{ | |
elements[row][col]=0.0; | |
} | |
} | |
} | |
public void multPointMatrix(Vec3 in, Vec3 out) | |
{ | |
//in is a row-vector in this!! | |
//out = in * this; | |
out.elements[X] = in.elements[X] * elements[0][0] + in.elements[Y] * elements[1][0] + in.elements[Z] * elements[2][0] + /* in.w = 1 */ elements[3][0]; | |
out.elements[Y] = in.elements[X] * elements[0][1] + in.elements[Y] * elements[1][1] + in.elements[Z] * elements[2][1] + /* in.w = 1 */ elements[3][1]; | |
out.elements[Z] = in.elements[X] * elements[0][2] + in.elements[Y] * elements[1][2] + in.elements[Z] * elements[2][2] + /* in.w = 1 */ elements[3][2]; | |
double w = in.elements[X] * elements[0][3] + in.elements[Y] * elements[1][3] + in.elements[Z] * elements[2][3] + /* in.w = 1 */ elements[3][3]; | |
// normalize if w is different than 1 (convert from homogeneous to Cartesian coordinates) | |
if (w != 1) { | |
out.elements[X] /= w; | |
out.elements[Y] /= w; | |
out.elements[Z] /= w; | |
} | |
} | |
public void multMatrixMatrix(Matrix44 in, Matrix44 out) | |
{ | |
for(int rvrow=0;rvrow<4;++rvrow) | |
{ | |
for (int rvcol = 0; rvcol < 4; ++rvcol) | |
{ | |
out.elements[rvrow][rvcol]=0; | |
for(int i=0;i<4;++i) | |
{ | |
out.elements[rvrow][rvcol]+=elements[rvrow][i]*in.elements[i][rvcol]; | |
} | |
} | |
} | |
} | |
@Override | |
public String toString() | |
{ | |
return "Matrix44{" + | |
"elements=" + Arrays.toString(elements) + | |
'}'; | |
} | |
public static void main(java.lang.String[] args) throws IOException | |
{ | |
java.util.List<java.util.List<Vec3>> ll=new java.util.LinkedList(); | |
java.util.List<Vec3> l=new java.util.LinkedList(); | |
l.add(new Vec3(15,3,2)); | |
l.add(new Vec3(15,3,8)); | |
l.add(new Vec3(15,-3,8)); | |
l.add(new Vec3(15,-3,2)); | |
ll.add(l); | |
java.util.Random rand=new java.util.Random(); | |
double maxx=80.0; | |
double maxy=80.0; | |
double maxz=40.0; | |
double maxwidth=18.0; | |
double maxheight=18.0; | |
int mode=0; | |
if(mode==0) | |
{ | |
for (int i = 0; i < 80; ++i) | |
{ | |
double x = rand.nextDouble() * (maxx - maxx * 0.5); | |
double y = rand.nextDouble() * (maxy - maxy * 0.5 - maxwidth / 2); | |
double z = rand.nextDouble() * maxz - (maxz - 10); | |
double width = rand.nextDouble() * (maxwidth - 2) + 2; | |
double height = rand.nextDouble() * (maxheight - 2) + 2; | |
l = new java.util.LinkedList(); | |
l.add(new Vec3(x, y, z)); | |
l.add(l.get(l.size() - 1).addAndNew(0, width, 0)); | |
l.add(l.get(l.size() - 1).addAndNew(0, 0, height)); | |
l.add(l.get(l.size() - 1).addAndNew(0, -width, 0)); | |
ll.add(l); | |
} | |
} | |
else if (mode==1) | |
{ | |
for (int i = 0; i < 80; ++i) | |
{ | |
double x = rand.nextDouble() * maxx - maxx * 0.5; | |
double y = rand.nextDouble() * maxy - maxy * 0.5 - maxwidth / 2; | |
double z = rand.nextDouble() * maxz - (maxz - 10); | |
double width = rand.nextDouble() * (maxwidth - 2) + 2; | |
double height = rand.nextDouble() * (maxheight - 2) + 2; | |
l = new java.util.LinkedList(); | |
l.add(new Vec3(x, y, z)); | |
l.add(l.get(l.size() - 1).addAndNew(0, width, 0)); | |
l.add(l.get(l.size() - 1).addAndNew(0, 0, height)); | |
l.add(l.get(l.size() - 1).addAndNew(0, -width, 0)); | |
ll.add(l); | |
} | |
} | |
else if (mode==2) | |
{ | |
for (int i = 0; i < 40; ++i) | |
{ | |
double x = rand.nextDouble() * maxx - maxx * 0.5; | |
double y = rand.nextDouble() * maxy - maxy * 0.5 - maxwidth / 2; | |
double z = rand.nextDouble() * maxz - (maxz - 10); | |
double width = rand.nextDouble() * (maxwidth - 2) + 2; | |
double height = rand.nextDouble() * (maxheight - 2) + 2; | |
l = new java.util.LinkedList(); | |
l.add(new Vec3(x, y, z)); | |
l.add(l.get(l.size() - 1).addAndNew(0, width, 0)); | |
l.add(l.get(l.size() - 1).addAndNew(0, 0, height)); | |
l.add(l.get(l.size() - 1).addAndNew(0, -width, 0)); | |
ll.add(l); | |
} | |
for (int i = 0; i < 40; ++i) | |
{ | |
double x = rand.nextDouble() * maxx - maxx * 0.5; | |
double y = rand.nextDouble() * maxy - maxy * 0.5 - maxwidth / 2; | |
double z = rand.nextDouble() * maxz - (maxz - 10); | |
double width = rand.nextDouble() * (maxwidth - 2) + 2; | |
double height = rand.nextDouble() * (maxheight - 2) + 2; | |
l = new java.util.LinkedList(); | |
l.add(new Vec3(x, y, z)); | |
l.add(l.get(l.size() - 1).addAndNew(width, 0, 0)); | |
l.add(l.get(l.size() - 1).addAndNew(0, 0, height)); | |
l.add(l.get(l.size() - 1).addAndNew(-width, 0, 0)); | |
ll.add(l); | |
} | |
} | |
java.awt.image.BufferedImage bimg=new java.awt.image.BufferedImage(512,512, BufferedImage.TYPE_INT_ARGB); | |
Matrix44 proj=Matrix44.buildPerspectiveMatrix(120,0.1,100); | |
Matrix44 worldToCamera=Matrix44.buildAffineTranslateMatrix(0,0,-30); | |
Matrix44 scale=Matrix44.buildAffineScaleMatrix(bimg.getWidth()/2,bimg.getHeight()/2,0); | |
Matrix44 trans=Matrix44.buildAffineTranslateMatrix(bimg.getWidth()/2,bimg.getHeight()/2,0); | |
Matrix44 m1=new Matrix44(); | |
Matrix44 m2=new Matrix44(); | |
worldToCamera.multMatrixMatrix(proj,m1); | |
m1.multMatrixMatrix(scale,m2); | |
m2.multMatrixMatrix(trans,m1); | |
Vec3 vertCamera=new Vec3(); | |
Vec3 projectedVert=new Vec3(); | |
Vec3 scaled=new Vec3(); | |
Vec3 translated=new Vec3(); | |
Vec3 v1=new Vec3(); | |
Vec3 v2=new Vec3(); | |
java.awt.Color background= Color.DARK_GRAY; | |
java.awt.Graphics2D g2=bimg.createGraphics(); | |
g2.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING,RenderingHints.VALUE_COLOR_RENDER_QUALITY); | |
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON); | |
g2.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION,RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY); | |
g2.setPaint(background); | |
g2.fillRect(0,0,bimg.getWidth(),bimg.getHeight()); | |
int loop=0; | |
RandomColor randomColor=new RandomColor(); | |
for(java.util.List<Vec3> lt:ll) | |
{ | |
java.awt.Polygon polygon=new Polygon(); | |
Vec3 origin=lt.get(0); | |
Matrix44 hin=Matrix44.buildAffineTranslateMatrix(-origin.elements[X],-origin.elements[Y],0); | |
Matrix44 rot=Matrix44.buildAffineRotateAroundZMatrix(rand.nextDouble()*360.0); | |
Matrix44 rueck=Matrix44.buildAffineTranslateMatrix(origin.elements[X],origin.elements[Y],0); | |
for(Vec3 vv:lt) | |
{ | |
if(mode==0) | |
{ | |
rot.multPointMatrix(vv, v1); | |
m1.multPointMatrix(v1, translated); | |
} | |
else | |
m1.multPointMatrix(vv, translated); | |
g2.setPaint(Color.BLUE); | |
polygon.addPoint((int)translated.toPoint2D().getX(),(int)translated.toPoint2D().getY()); | |
++loop; | |
} | |
polygon.addPoint(polygon.xpoints[0],polygon.ypoints[0]); | |
java.awt.Color c=randomColor.next(); | |
c=new Color(c.getRed(),c.getGreen(),c.getBlue(),180-rand.nextInt(100)); | |
RadialGradientPaint p = | |
new RadialGradientPaint(new java.awt.geom.Point2D.Double(bimg.getWidth()/2,bimg.getHeight()/2), bimg.getWidth()/2, new float[]{0,1f}, new java.awt.Color[]{background,c}); | |
g2.setPaint(p); | |
g2.fillPolygon(polygon); | |
} | |
g2.dispose(); | |
javax.imageio.ImageIO.write(bimg,"png",new java.io.File("/tmp/render.png")); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment