This site requires JavaScript, please enable it in your browser!
Greenfoot back
CE3A
CE3A wrote ...

2016/7/5

orthographic 3d

CE3A CE3A

2016/7/5

#
in case anyone wants to render triangles in 3d, heres 2 ways you can: wireframe:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
import java.util.ArrayList;
import java.awt.Color;

public class Render3d extends Actor
{
    public int cycles;
    java.util.List<Triangle> tris = new ArrayList<>();
    public void act() 
    {
        if(cycles == 0) {//only runs once
            
            tris.add(new Triangle(new Vertex(100, 100, 100), new Vertex(-100, -100, 100), new Vertex(-100, 100, -100), new Color(0xFF, 0x33, 0))); // add triangles to list tris
            tris.add(new Triangle(new Vertex(100, 100, 100), new Vertex(-100, -100, 100), new Vertex(100, -100, -100), new Color(0x66, 0xFF, 0x66)));
            tris.add(new Triangle(new Vertex(-100, 100, -100), new Vertex(100, -100, -100), new Vertex(100, 100, 100), new Color(0xFF, 0, 0xFF)));
            tris.add(new Triangle(new Vertex(-100, 100, -100), new Vertex(100, -100, -100), new Vertex(-100, -100, 100), new Color(0x33, 0xCC, 0xFF)));
        }
        
        renderTris();
        
        cycles++;
    }
    
    public void renderTris() {
        getWorld().getBackground().setColor(Color.BLACK);//fill background black
        getWorld().getBackground().fill();
        int mouseX = 0;
        int mouseY = 0;
        
        MouseInfo mouse = Greenfoot.getMouseInfo();
        
        if(mouse != null) {
            mouseX = mouse.getX();
            mouseY = mouse.getY();//set variables to mouse location(if the mouse is on the screen)
        }
        
        double heading = Math.toRadians(mouseX);//calculate heading
        Matrix3 headingTransform = new Matrix3(new double[] {//creating transform matricies for rotation
            Math.cos(heading), 0, Math.sin(heading),
                0, 1, 0,
                -Math.sin(heading), 0, Math.cos(heading)
            });
        double pitch = Math.toRadians(mouseY);//calculate pitch
        Matrix3 pitchTransform = new Matrix3(new double[] {
            1, 0, 0,
            0, Math.cos(pitch), Math.sin(pitch),
            0, -Math.sin(pitch), Math.cos(pitch)
        });
        Matrix3 transform = headingTransform.multiply(pitchTransform);//making one matrix that does both heading and pitch rotation
        
        
        for (Triangle t : tris) { // wireframe render(only works with tetrahedron)
            Vertex v1 = transform.transform(t.v1);
            Vertex v2 = transform.transform(t.v2);
            Vertex v3 = transform.transform(t.v3);
            
            getWorld().getBackground().setColor(Color.WHITE);
            getWorld().getBackground().drawLine(centerX + (int)v1.x, centerY + (int) v1.y, centerX + (int) v2.x, centerY + (int) v2.y);
            getWorld().getBackground().drawLine(centerX + (int)v1.x, centerY + (int) v1.y, centerX + (int) v3.x, centerY + (int) v3.y);
            getWorld().getBackground().drawLine(centerX + (int)v2.x, centerY + (int) v2.y, centerX + (int) v3.x, centerY + (int) v3.y);
        }
        
    }
shaded:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
import java.util.ArrayList;
import java.awt.Color;
/**
 * Write a description of class Render3d here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class Render3d extends Actor
{
    public int cycles;
    java.util.List<Triangle> tris = new ArrayList<>();
    public void act() 
    {
        if(cycles == 0) {//only runs once
            
            tris.add(new Triangle(new Vertex(100, 100, 100), new Vertex(-100, -100, 100), new Vertex(-100, 100, -100), new Color(0xFF, 0x33, 0))); // add triangles to list tris
            tris.add(new Triangle(new Vertex(100, 100, 100), new Vertex(-100, -100, 100), new Vertex(100, -100, -100), new Color(0x66, 0xFF, 0x66)));
            tris.add(new Triangle(new Vertex(-100, 100, -100), new Vertex(100, -100, -100), new Vertex(100, 100, 100), new Color(0xFF, 0, 0xFF)));
            tris.add(new Triangle(new Vertex(-100, 100, -100), new Vertex(100, -100, -100), new Vertex(-100, -100, 100), new Color(0x33, 0xCC, 0xFF)));
        }
        
        renderTris();
        
        cycles++;
    }
    
    public void renderTris() {
        getWorld().getBackground().setColor(Color.BLACK);//fill background black
        getWorld().getBackground().fill();
        int mouseX = 0;
        int mouseY = 0;
        
        MouseInfo mouse = Greenfoot.getMouseInfo();
        
        if(mouse != null) {
            mouseX = mouse.getX();
            mouseY = mouse.getY();//set variables to mouse location(if the mouse is on the screen)
        }
        
        double heading = Math.toRadians(mouseX);//calculate heading
        Matrix3 headingTransform = new Matrix3(new double[] {//creating transform matricies for rotation
            Math.cos(heading), 0, Math.sin(heading),
                0, 1, 0,
                -Math.sin(heading), 0, Math.cos(heading)
            });
        double pitch = Math.toRadians(mouseY);//calculate pitch
        Matrix3 pitchTransform = new Matrix3(new double[] {
            1, 0, 0,
            0, Math.cos(pitch), Math.sin(pitch),
            0, -Math.sin(pitch), Math.cos(pitch)
        });
        Matrix3 transform = headingTransform.multiply(pitchTransform);//making one matrix that does both heading and pitch rotation
                
        GreenfootImage img = getWorld().getBackground();//

        double[] zBuffer = new double[img.getWidth() * img.getHeight()];
        // initialize array with negative infinite depths
        for (int q = 0; q < zBuffer.length; q++) {
            zBuffer[q] = Double.NEGATIVE_INFINITY;
        }

        for (Triangle t : tris) {
            Vertex v1 = transform.transform(t.v1);
            Vertex v2 = transform.transform(t.v2);
            Vertex v3 = transform.transform(t.v3);

            v1.x += 400;//center object
            v1.y += 300;
            v2.x += 400;
            v2.y += 300;
            v3.x += 400;
            v3.y += 300;

            // compute rectangular bounds for triangle
            int minX = (int) Math.max(0, Math.ceil(Math.min(v1.x, Math.min(v2.x, v3.x))));
            int maxX = (int) Math.min(img.getWidth() - 1,
                    Math.floor(Math.max(v1.x, Math.max(v2.x, v3.x))));
            int minY = (int) Math.max(0, Math.ceil(Math.min(v1.y, Math.min(v2.y, v3.y))));
            int maxY = (int) Math.min(img.getHeight() - 1,
                    Math.floor(Math.max(v1.y, Math.max(v2.y, v3.y))));

            double triangleArea =
                    (v1.y - v3.y) * (v2.x - v3.x) + (v2.y - v3.y) * (v3.x - v1.x);

            // transform vertices before calculating normal...

            Vertex ab = new Vertex(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);

            Vertex ac = new Vertex(v1.x - v3.x, v1.y - v3.y, v1.z - v3.z);

            Vertex norm = new Vertex(//calculate normal vector for shading
                    ab.y * ac.z - ab.z * ac.y,
                    ab.z * ac.x - ab.x * ac.z,
                    ab.x * ac.y - ab.y * ac.x
            );
            double normalLength =
                    Math.sqrt(norm.x * norm.x + norm.y * norm.y + norm.z * norm.z);
            norm.x /= normalLength;
            norm.y /= normalLength;
            norm.z /= normalLength;

            double angleCos = Math.abs(norm.z);

            for (int x = minX; x <= maxX; x++) {
                for (int y = minY; y <= maxY; y++) {//iterate over every pixel(inneficient)
                    double b1 =
                            ((y - v3.y) * (v2.x - v3.x) + (v2.y - v3.y) * (v3.x - x)) / triangleArea;
                    double b2 =
                            ((y - v1.y) * (v3.x - v1.x) + (v3.y - v1.y) * (v1.x - x)) / triangleArea;
                    double b3 =
                            ((y - v2.y) * (v1.x - v2.x) + (v1.y - v2.y) * (v2.x - x)) / triangleArea;


                    // handle rasterization...
                    // for each rasterized pixel:
                    if (b1 >= 0 && b1 <= 1 && b2 >= 0 && b2 <= 1 && b3 >= 0 && b3 <= 1) {//check if pixel is inside the triangle
                        double depth = b1 * v1.z + b2 * v2.z + b3 * v3.z; //calculate depth
                        int zIndex = y * img.getWidth() + x;
                        if (zBuffer[zIndex] < depth) {
                            img.setColor(getShade(t.color, angleCos));//calculate shade
                            img.drawRect(x, y, 1, 1);//draw pixel
                            zBuffer[zIndex] = depth;
                        }
                    }



                }
            }
        }
    }
    
    public static Color getShade(Color color, double shade) {
        double redLinear = Math.pow(color.getRed(), 2.4) * shade;
        double greenLinear = Math.pow(color.getGreen(), 2.4) * shade;
        double blueLinear = Math.pow(color.getBlue(), 2.4) * shade;

        int red = (int) Math.pow(redLinear, 1/2.4);
        int green = (int) Math.pow(greenLinear, 1/2.4);
        int blue = (int) Math.pow(blueLinear, 1/2.4);

        return new Color(red, green, blue);
    }
}
both of these methods were originally made in this blog post, and adapted to greenfoot by me. a full project using this can be foundhere. i am planning to also make a rendering engine for greenfoot that uses openGL, because this is using the CPU for rendering when it would be way faster to use the GPU, which openGL lets you do.
danpost danpost

2016/7/6

#
There are a couple of classes used in the code given that are not readily available to users of this site unless they go to the openGL site and get them (I presume they are available there) -- specifically: Matrix3 and Vector (which I would also presume to be a 3d vector class). Maybe you should make the source code available in your linked uploaded scenario (re-upload with the 'Publish source code' checkbox checked) so others can download the scenario and acquire those classes.
CE3A CE3A

2016/7/6

#
sorry if i was unclear, but this is not using openGL or any classes from openGL. the Matrix3, Vertex, and Triangle classes were from the blog post i linked. also, this isn't using a Vector class, instead it is using a Vertex. i will also re upload with the source code available.
danpost danpost

2016/7/6

#
CE3A wrote...
sorry if i was unclear, but this is not using openGL or any classes from openGL. the Matrix3, Vertex, and Triangle classes were from the blog post i linked. also, this isn't using a Vector class, instead it is using a Vertex. i will also re upload with the source code available.
My apologies -- I did overlook the link to the blog post and mistook the name of the ungiven class beginning with a 'V'. What I said pretty much still stands as far as having to go elsewhere for the codes. Thank you for understanding and uploading the source.
You need to login to post a reply.