Move 3D raytracing engine to new project.

origin
sigonasr2, Sig, Sigo 3 years ago
commit b7e570dd5f
  1. 2
      .gitignore
  2. 9
      .gitpod.yml
  3. 3
      .vscode/settings.json
  4. 41
      coauthors.sh
  5. 96
      pom.xml
  6. 2
      run
  7. 126
      src/sig/Panel.java
  8. 13
      src/sig/Pixel.java
  9. 142
      src/sig/SigRenderer.java
  10. 70
      src/sig/Triangle.java

2
.gitignore vendored

@ -0,0 +1,2 @@
/bin/
/target/

@ -0,0 +1,9 @@
---
# List the start up tasks. Learn more https://www.gitpod.io/docs/config-start-tasks/
tasks:
- init: sh coauthors.sh
vscode:
extensions:
- redhat.java
- mhutchie.git-graph
- vscjava.vscode-maven

@ -0,0 +1,3 @@
{
"java.configuration.updateBuildConfiguration": "automatic"
}

@ -0,0 +1,41 @@
npm i -g git-mob
cat <<-EOF > ~/.git-coauthors
{
"coauthors": {
"sig": {
"name": "sigonasr2",
"email": "sigonasr2@gmail.com"
}
}
}
EOF
git mob sig
cat <<-EOF > .git/hooks/prepare-commit-msg
#!/usr/bin/env node
let exec = require('child_process').exec,
fs = require('fs');
const commitMessage = process.argv[2];
// expect .git/COMMIT_EDITMSG
if(/COMMIT_EDITMSG/g.test(commitMessage)){
let contents = "";
exec("git mob-print",
function (err, stdout) {
if(err) {
process.exit(0);
}
// opens .git/COMMIT_EDITMSG
contents = fs.readFileSync(commitMessage);
if(contents.indexOf(stdout.trim()) !== -1) {
process.exit(0);
}
const commentPos = contents.indexOf('# ');
const gitMessage = contents.slice(0, commentPos);
const gitComments = contents.slice(commentPos)
fs.writeFileSync(commitMessage, gitMessage + stdout + gitComments);
process.exit(0);
});
}
EOF
chmod +x .git/hooks/prepare-commit-msg
cd /workspace/SigRenderer
echo "Environment is setup!"

@ -0,0 +1,96 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>SigRenderer</groupId>
<artifactId>SigRenderer</artifactId>
<version>0</version>
<name>SigRenderer</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/javax.vecmath/vecmath -->
<dependency>
<groupId>javax.vecmath</groupId>
<artifactId>vecmath</artifactId>
<version>1.5.2</version>
</dependency>
</dependencies>
<build>
<sourceDirectory>src</sourceDirectory>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
<plugin>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.0.0</version>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>sig.SigRenderer</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- bind to the packaging phase -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>

2
run

@ -0,0 +1,2 @@
mvn compile assembly:single
java -jar target/SigRenderer-0-jar-with-dependencies.jar

@ -0,0 +1,126 @@
package sig;
import javax.swing.JPanel;
import javax.vecmath.Vector3f;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Image;
import java.awt.image.MemoryImageSource;
import java.awt.image.ColorModel;
import java.awt.GraphicsEnvironment;
import java.awt.GraphicsConfiguration;
import java.awt.Toolkit;
public class Panel extends JPanel implements Runnable {
long startTime = System.nanoTime();
long endTime = System.nanoTime();
public int pixel[];
public int width=SigRenderer.SCREEN_WIDTH;
public int height=SigRenderer.SCREEN_HEIGHT;
private Image imageBuffer;
private MemoryImageSource mImageProducer;
private ColorModel cm;
private Thread thread;
public Panel() {
super(true);
thread = new Thread(this, "MyPanel Thread");
}
/**
* Get Best Color model available for current screen.
* @return color model
*/
protected static ColorModel getCompatibleColorModel(){
GraphicsConfiguration gfx_config = GraphicsEnvironment.
getLocalGraphicsEnvironment().getDefaultScreenDevice().
getDefaultConfiguration();
return gfx_config.getColorModel();
}
/**
* Call it after been visible and after resizes.
*/
public void init(){
cm = getCompatibleColorModel();
width = getWidth();
height = getHeight();
int screenSize = width * height;
if(pixel == null || pixel.length < screenSize){
pixel = new int[screenSize];
}
mImageProducer = new MemoryImageSource(width, height, cm, pixel,0, width);
mImageProducer.setAnimated(true);
mImageProducer.setFullBufferUpdates(true);
imageBuffer = Toolkit.getDefaultToolkit().createImage(mImageProducer);
if(thread.isInterrupted() || !thread.isAlive()){
thread.start();
}
}
/**
* Do your draws in here !!
* pixel is your canvas!
*/
public /* abstract */ void render(){
int[] p = pixel; // this avoid crash when resizing
final int h=SigRenderer.SCREEN_HEIGHT;
if(p.length != width * height) return;
for (int x=0;x<SigRenderer.SCREEN_WIDTH/SigRenderer.RESOLUTION;x++) {
for (int y=0;y<SigRenderer.SCREEN_HEIGHT/SigRenderer.RESOLUTION;y++) {
Vector3f dir = new Vector3f((-SigRenderer.SCREEN_WIDTH/2f+x*SigRenderer.RESOLUTION),(-SigRenderer.SCREEN_HEIGHT/2f+y*SigRenderer.RESOLUTION),SigRenderer.SCREEN_WIDTH);
if (SigRenderer.tri.rayTriangleIntersect(SigRenderer.origin, dir)) {
p[ (int)(SigRenderer.SCREEN_WIDTH-x*SigRenderer.RESOLUTION) + (int)(SigRenderer.SCREEN_HEIGHT-y*SigRenderer.RESOLUTION) * width] = Color.WHITE.getRGB();
}
if (SigRenderer.tri2.rayTriangleIntersect(SigRenderer.origin, dir)) {
p[ (int)(SigRenderer.SCREEN_WIDTH-x*SigRenderer.RESOLUTION) + (int)(SigRenderer.SCREEN_HEIGHT-y*SigRenderer.RESOLUTION) * width] = Color.BLUE.getRGB();
}
if (SigRenderer.tri3.rayTriangleIntersect(SigRenderer.origin, dir)) {
p[ (int)(SigRenderer.SCREEN_WIDTH-x*SigRenderer.RESOLUTION) + (int)(SigRenderer.SCREEN_HEIGHT-y*SigRenderer.RESOLUTION) * width] = Color.RED.getRGB();
}
if (SigRenderer.tri4.rayTriangleIntersect(SigRenderer.origin, dir)) {
p[ (int)(SigRenderer.SCREEN_WIDTH-x*SigRenderer.RESOLUTION) + (int)(SigRenderer.SCREEN_HEIGHT-y*SigRenderer.RESOLUTION) * width] = Color.GREEN.getRGB();
}
}
}
i += 1;
j += 1;
endTime=System.nanoTime();
SigRenderer.DRAWLOOPTIME=(endTime-startTime)/1000000f;
}
private int i=1,j=256;
public void repaint() {
super.repaint();
startTime = System.nanoTime();
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
// perform draws on pixels
render();
// ask ImageProducer to update image
mImageProducer.newPixels();
// draw it on panel
g.drawImage(this.imageBuffer, 0, 0, this);
}
/**
* Overrides ImageObserver.imageUpdate.
* Always return true, assuming that imageBuffer is ready to go when called
*/
@Override
public boolean imageUpdate(Image image, int a, int b, int c, int d, int e) {
return true;
}
@Override
public void run() {
while (true) {
// request a JPanel re-drawing
repaint();
try {Thread.sleep(5);} catch (InterruptedException e) {}
}
}
}

@ -0,0 +1,13 @@
package sig;
import java.awt.Color;
public class Pixel {
int x,y;
Color col;
Pixel(int x,int y,Color col) {
this.x=x;
this.y=y;
this.col=col;
}
}

@ -0,0 +1,142 @@
package sig;
import javax.swing.JFrame;
import javax.vecmath.Point2d;
import javax.vecmath.Tuple3d;
import javax.vecmath.Vector3f;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.List;
import java.awt.Toolkit;
import java.awt.Color;
public class SigRenderer implements KeyListener,MouseListener,MouseMotionListener{
public static Triangle tri,tri2,tri3,tri4,tri5,tri6;
public final static int SCREEN_WIDTH=1280;
public final static int SCREEN_HEIGHT=720;
public final static long TIMEPERTICK = 16666667l;
public static float DRAWTIME=0;
public static float DRAWLOOPTIME=0;
public static final float RESOLUTION=1;
public static Vector3f origin = new Vector3f(0,0,10);
public static float rot = (float)Math.PI/4; //In radians.
public static List<Pixel> pixels;
public void runGameLoop() {
rot+=Math.PI/480d;
}
SigRenderer(JFrame f) {
tri = new Triangle(new Vector3f(-1,-1,0),new Vector3f(0,-1,0),new Vector3f(-1,0,0));
tri2 = new Triangle(new Vector3f(-1,0,0),new Vector3f(0,-1,0),new Vector3f(0,0,0));
tri3 = new Triangle(new Vector3f(0,0,0),new Vector3f(0,-1,0),new Vector3f(0,-1,-1));
tri4 = new Triangle(new Vector3f(0,-1,-1),new Vector3f(0,0,-1),new Vector3f(0,-1,0));
/*tri5 = new Triangle(new Vector3f(0,-1,0),new Vector3f(0,-1,-1),new Vector3f(0,0,0));
tri6 = new Triangle(new Vector3f(0,0,0),new Vector3f(0,-1,-1),new Vector3f(0,0,-1));*/
Panel p = new Panel();
new Thread() {
public void run(){
while (true) {
long startTime = System.nanoTime();
runGameLoop();
p.repaint();
Toolkit.getDefaultToolkit().sync();
long endTime = System.nanoTime();
long diff = endTime-startTime;
try {
long sleepTime = TIMEPERTICK - diff;
long millis = (sleepTime)/1000000;
int nanos = (int)(sleepTime-(((sleepTime)/1000000)*1000000));
//System.out.println("FRAME DRAWING: Sleeping for ("+millis+"ms,"+nanos+"ns) - "+(diff)+"ns");
DRAWTIME = (float)diff/1000000;
f.setTitle("Game Loop: "+DRAWTIME+"ms, Draw Loop: "+DRAWLOOPTIME+"ms");
if (sleepTime>0) {
Thread.sleep(millis,nanos);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
f.getContentPane().addMouseListener(this);
f.getContentPane().addMouseMotionListener(this);
f.addKeyListener(this);
f.add(p);
f.setSize(SCREEN_WIDTH,SCREEN_HEIGHT);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
p.init();
}
public static void main(String[] args) {
JFrame f = new JFrame("SigRenderer");
new SigRenderer(f);
}
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void mouseDragged(MouseEvent e) {
}
@Override
public void mouseMoved(MouseEvent e) {
}
@Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
@Override
public void keyPressed(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_UP:{
origin.add(new Vector3f(0,0,-1));
}break;
case KeyEvent.VK_RIGHT:{
origin.add(new Vector3f(1,0,0));
}break;
case KeyEvent.VK_LEFT:{
origin.add(new Vector3f(-1,0,0));
}break;
case KeyEvent.VK_DOWN:{
origin.add(new Vector3f(0,0,1));
}break;
}
}
@Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
}

@ -0,0 +1,70 @@
package sig;
import javax.vecmath.Vector3f;
public class Triangle {
Vector3f A,B,C;
Triangle(Vector3f A,Vector3f B,Vector3f C) {
this.A=A;
this.B=B;
this.C=C;
}
@Override
public String toString() {
return "Triangle [A=" + A + ", B=" + B + ", C=" + C + "]";
}
public Vector3f getNormal() {
Vector3f AB = (Vector3f)A.clone();
AB.sub(B);
Vector3f BC = (Vector3f)B.clone();
BC.sub(C);
Vector3f crossP = new Vector3f();
crossP.cross(AB,BC);
//crossP.normalize();
return crossP;
}
public float distanceFromOrigin() {
return getNormal().dot(A);
}
public boolean rayTriangleIntersect(Vector3f origin,Vector3f dir) {
Vector3f N = getNormal();
float NrayDir = N.dot(dir);
if (NrayDir<=0.001) { //Very small, so it's parallel.
return false;
}
float d = distanceFromOrigin();
float T=(getNormal().dot(origin)+d)/(NrayDir);
if (T<0) {return false;} //Triangle is behind the ray.
//System.out.println("Not behind.");
Vector3f scaleMult = (Vector3f)dir.clone();
scaleMult.scale(T);
Vector3f P = (Vector3f)origin.clone();
P.add(scaleMult);
Vector3f C;
Vector3f edge0 = (Vector3f)B.clone(); edge0.sub(A);
Vector3f vp0 = (Vector3f)P.clone(); vp0.sub(A);
C = new Vector3f(); C.cross(edge0,vp0);
if (N.dot(C)<0) {return false;}
Vector3f edge1 = (Vector3f)this.C.clone(); edge1.sub(B);
Vector3f vp1 = (Vector3f)P.clone(); vp1.sub(B);
C = new Vector3f(); C.cross(edge1,vp1);
if (N.dot(C)<0) {return false;}
Vector3f edge2 = (Vector3f)A.clone(); edge2.sub(this.C);
Vector3f vp2 = (Vector3f)P.clone(); vp2.sub(this.C);
C = new Vector3f(); C.cross(edge2,vp2);
if (N.dot(C)<0) {return false;}
return true;
}
}
Loading…
Cancel
Save