Implement polygon scanline renderer

main
sigonasr2 3 years ago
parent b135fb5408
commit 4b14f30509
  1. BIN
      bin/sig/Edge.class
  2. BIN
      bin/sig/Panel.class
  3. BIN
      bin/sig/Point.class
  4. 33
      src/sig/Edge.java
  5. 100
      src/sig/Panel.java
  6. 32
      src/sig/Point.java

Binary file not shown.

Binary file not shown.

Binary file not shown.

@ -0,0 +1,33 @@
package sig;
public class Edge {
Point a,b;
int min_y;
int max_y;
int min_x;
int max_x;
double x_of_min_y;
double inverse_slope;
public Edge(Point a, Point b) {
super();
this.a = a;
this.b = b;
min_y=Math.min(a.y, b.y);
max_y=Math.max(a.y, b.y);
min_x=Math.min(a.x, b.x);
max_x=Math.max(a.x, b.x);
if (a.y==min_y) {
x_of_min_y=a.x;
} else {
x_of_min_y=b.x;
}
inverse_slope=(double)(a.x-b.x)/(a.y-b.y);
}
@Override
public String toString() {
return "Edge [a=" + a + ", b=" + b + ", min_y=" + min_y + ", max_y=" + max_y + ", min_x=" + min_x + ", max_x="
+ max_x + ", x_of_min_y=" + x_of_min_y + ", inverse_slope=" + inverse_slope + "]";
}
}

@ -6,6 +6,8 @@ import java.awt.Image;
import java.awt.Toolkit;
import java.awt.image.ColorModel;
import java.awt.image.MemoryImageSource;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JPanel;
@ -17,6 +19,8 @@ public class Panel extends JPanel implements Runnable {
private Image imageBuffer;
private MemoryImageSource mImageProducer;
private ColorModel cm;
int scanLine=0;
int nextScanLine=0;
public Panel() {
super(true);
@ -85,9 +89,103 @@ public class Panel extends JPanel implements Runnable {
}
}
FillPolygon(new Point[] {
new Point(135,2),
new Point(166,96),
new Point(265,97),
new Point(185,156),
new Point(215,251),
new Point(134,192),
new Point(54,251),
new Point(84,156),
new Point(4,97),
new Point(103,96),
});
}
public void FillPolygon(Point...points) {
Edge[] edges = new Edge[points.length];
List<Edge> edges_sorted = new ArrayList<Edge>();
for (int i=0;i<points.length;i++) {
edges[i] = new Edge(points[i],points[(i+1)%points.length]);
if (edges_sorted.size()==0) {
edges_sorted.add(edges[i]);
} else {
boolean inserted=false;
for (int j=0;j<edges_sorted.size();j++) {
Edge e2 = edges_sorted.get(j);
if (e2.min_y>edges[i].min_y) {
edges_sorted.add(j,edges[i]);
inserted=true;
break;
} else
if (e2.min_y==edges[i].min_y){
if (e2.min_x>edges[i].min_x) {
edges_sorted.add(j,edges[i]);
inserted=true;
break;
}
}
}
if (!inserted) {
edges_sorted.add(edges[i]);
}
}
}
List<Edge> active_edges = new ArrayList<Edge>();
scanLine = edges_sorted.get(0).min_y-1;
nextScanLine = scanLine+1;
do {
if (active_edges.size()%2==0) {
for (int i=0;i<active_edges.size();i+=2) {
Edge e1 = active_edges.get(i);
Edge e2 = active_edges.get(i+1);
for (int x=(int)Math.round(e1.x_of_min_y);x<=e2.x_of_min_y;x++) {
pixel[scanLine*width+x]=(255<<16)+(0<<8)+0;
}
}
for (int i=0;i<active_edges.size();i++) {
Edge e = active_edges.get(i);
if (e.max_y==scanLine+1) {
active_edges.remove(i--);
} else {
e.x_of_min_y+=e.inverse_slope;
}
}
scanLine++;
GetNextScanLineEdges(edges_sorted, active_edges);
}
}
while (active_edges.size()>0);
}
private void GetNextScanLineEdges(List<Edge> edges_sorted, List<Edge> active_edges) {
if (scanLine==nextScanLine) {
for (int i=0;i<edges_sorted.size();i++) {
Edge e = edges_sorted.get(i);
if (e.min_y==scanLine) {
e = edges_sorted.remove(i--);
boolean inserted=false;
for (int j=0;j<active_edges.size();j++) {
if (e.x_of_min_y<active_edges.get(j).x_of_min_y) {
active_edges.add(j,e);
inserted=true;
break;
}
}
if (!inserted) {
active_edges.add(e);
}
} else
if (e.min_y>scanLine) {
nextScanLine=e.min_y;
break;
}
}
}
}
@Override
public void run() {
while (true) {

@ -0,0 +1,32 @@
package sig;
public class Point {
int x,y;
public Point(int x, int y) {
super();
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
@Override
public String toString() {
return "Point(" + x + "," + y + ")";
}
}
Loading…
Cancel
Save