Search in sources :

Example 1 with Vector3

use of org.sunflow.math.Vector3 in project joons-renderer by joonhyublee.

the class TriangleMesh method prepareShadingState.

@Override
public void prepareShadingState(ShadingState state) {
    state.init();
    Instance parent = state.getInstance();
    int primID = state.getPrimitiveID();
    float u = state.getU();
    float v = state.getV();
    float w = 1 - u - v;
    state.getRay().getPoint(state.getPoint());
    int tri = 3 * primID;
    int index0 = triangles[tri + 0];
    int index1 = triangles[tri + 1];
    int index2 = triangles[tri + 2];
    Point3 v0p = getPoint(index0);
    Point3 v1p = getPoint(index1);
    Point3 v2p = getPoint(index2);
    Vector3 ng = Point3.normal(v0p, v1p, v2p);
    ng = state.transformNormalObjectToWorld(ng);
    ng.normalize();
    state.getGeoNormal().set(ng);
    switch(normals.interp) {
        case NONE:
        case FACE:
            {
                state.getNormal().set(ng);
                break;
            }
        case VERTEX:
            {
                int i30 = 3 * index0;
                int i31 = 3 * index1;
                int i32 = 3 * index2;
                float[] normalsu = this.normals.data;
                state.getNormal().x = w * normalsu[i30 + 0] + u * normalsu[i31 + 0] + v * normalsu[i32 + 0];
                state.getNormal().y = w * normalsu[i30 + 1] + u * normalsu[i31 + 1] + v * normalsu[i32 + 1];
                state.getNormal().z = w * normalsu[i30 + 2] + u * normalsu[i31 + 2] + v * normalsu[i32 + 2];
                state.getNormal().set(state.transformNormalObjectToWorld(state.getNormal()));
                state.getNormal().normalize();
                break;
            }
        case FACEVARYING:
            {
                int idx = 3 * tri;
                float[] normalsu = this.normals.data;
                state.getNormal().x = w * normalsu[idx + 0] + u * normalsu[idx + 3] + v * normalsu[idx + 6];
                state.getNormal().y = w * normalsu[idx + 1] + u * normalsu[idx + 4] + v * normalsu[idx + 7];
                state.getNormal().z = w * normalsu[idx + 2] + u * normalsu[idx + 5] + v * normalsu[idx + 8];
                state.getNormal().set(state.transformNormalObjectToWorld(state.getNormal()));
                state.getNormal().normalize();
                break;
            }
    }
    float uv00 = 0, uv01 = 0, uv10 = 0, uv11 = 0, uv20 = 0, uv21 = 0;
    switch(uvs.interp) {
        case NONE:
        case FACE:
            {
                state.getUV().x = 0;
                state.getUV().y = 0;
                break;
            }
        case VERTEX:
            {
                int i20 = 2 * index0;
                int i21 = 2 * index1;
                int i22 = 2 * index2;
                float[] uvsu = this.uvs.data;
                uv00 = uvsu[i20 + 0];
                uv01 = uvsu[i20 + 1];
                uv10 = uvsu[i21 + 0];
                uv11 = uvsu[i21 + 1];
                uv20 = uvsu[i22 + 0];
                uv21 = uvsu[i22 + 1];
                break;
            }
        case FACEVARYING:
            {
                int idx = tri << 1;
                float[] uvsu = this.uvs.data;
                uv00 = uvsu[idx + 0];
                uv01 = uvsu[idx + 1];
                uv10 = uvsu[idx + 2];
                uv11 = uvsu[idx + 3];
                uv20 = uvsu[idx + 4];
                uv21 = uvsu[idx + 5];
                break;
            }
    }
    if (uvs.interp != InterpolationType.NONE) {
        // get exact uv coords and compute tangent vectors
        state.getUV().x = w * uv00 + u * uv10 + v * uv20;
        state.getUV().y = w * uv01 + u * uv11 + v * uv21;
        float du1 = uv00 - uv20;
        float du2 = uv10 - uv20;
        float dv1 = uv01 - uv21;
        float dv2 = uv11 - uv21;
        Vector3 dp1 = Point3.sub(v0p, v2p, new Vector3()), dp2 = Point3.sub(v1p, v2p, new Vector3());
        float determinant = du1 * dv2 - dv1 * du2;
        if (determinant == 0.0f) {
            // create basis in world space
            state.setBasis(OrthoNormalBasis.makeFromW(state.getNormal()));
        } else {
            float invdet = 1.f / determinant;
            // Vector3 dpdu = new Vector3();
            // dpdu.x = (dv2 * dp1.x - dv1 * dp2.x) * invdet;
            // dpdu.y = (dv2 * dp1.y - dv1 * dp2.y) * invdet;
            // dpdu.z = (dv2 * dp1.z - dv1 * dp2.z) * invdet;
            Vector3 dpdv = new Vector3();
            dpdv.x = (-du2 * dp1.x + du1 * dp2.x) * invdet;
            dpdv.y = (-du2 * dp1.y + du1 * dp2.y) * invdet;
            dpdv.z = (-du2 * dp1.z + du1 * dp2.z) * invdet;
            dpdv = state.transformVectorObjectToWorld(dpdv);
            // create basis in world space
            state.setBasis(OrthoNormalBasis.makeFromWV(state.getNormal(), dpdv));
        }
    } else {
        state.setBasis(OrthoNormalBasis.makeFromW(state.getNormal()));
    }
    int shaderIndex = faceShaders == null ? 0 : (faceShaders[primID] & 0xFF);
    state.setShader(parent.getShader(shaderIndex));
    state.setModifier(parent.getModifier(shaderIndex));
}
Also used : Point3(org.sunflow.math.Point3) Instance(org.sunflow.core.Instance) Vector3(org.sunflow.math.Vector3)

Example 2 with Vector3

use of org.sunflow.math.Vector3 in project joons-renderer by joonhyublee.

the class CausticPhotonMap method balanceSegment.

private void balanceSegment(Photon[] temp, int index, int start, int end) {
    int median = 1;
    while ((4 * median) <= (end - start + 1)) {
        median += median;
    }
    if ((3 * median) <= (end - start + 1)) {
        median += median;
        median += (start - 1);
    } else {
        median = end - median + 1;
    }
    int axis = Photon.SPLIT_Z;
    Vector3 extents = bounds.getExtents();
    if ((extents.x > extents.y) && (extents.x > extents.z)) {
        axis = Photon.SPLIT_X;
    } else if (extents.y > extents.z) {
        axis = Photon.SPLIT_Y;
    }
    int left = start;
    int right = end;
    while (right > left) {
        double v = photons[right].getCoord(axis);
        int i = left - 1;
        int j = right;
        while (true) {
            while (photons[++i].getCoord(axis) < v) {
            }
            while ((photons[--j].getCoord(axis) > v) && (j > left)) {
            }
            if (i >= j) {
                break;
            }
            swap(i, j);
        }
        swap(i, right);
        if (i >= median) {
            right = i - 1;
        }
        if (i <= median) {
            left = i + 1;
        }
    }
    temp[index] = photons[median];
    temp[index].setSplitAxis(axis);
    if (median > start) {
        if (start < (median - 1)) {
            float tmp;
            switch(axis) {
                case Photon.SPLIT_X:
                    tmp = bounds.getMaximum().x;
                    bounds.getMaximum().x = temp[index].x;
                    balanceSegment(temp, 2 * index, start, median - 1);
                    bounds.getMaximum().x = tmp;
                    break;
                case Photon.SPLIT_Y:
                    tmp = bounds.getMaximum().y;
                    bounds.getMaximum().y = temp[index].y;
                    balanceSegment(temp, 2 * index, start, median - 1);
                    bounds.getMaximum().y = tmp;
                    break;
                default:
                    tmp = bounds.getMaximum().z;
                    bounds.getMaximum().z = temp[index].z;
                    balanceSegment(temp, 2 * index, start, median - 1);
                    bounds.getMaximum().z = tmp;
            }
        } else {
            temp[2 * index] = photons[start];
        }
    }
    if (median < end) {
        if ((median + 1) < end) {
            float tmp;
            switch(axis) {
                case Photon.SPLIT_X:
                    tmp = bounds.getMinimum().x;
                    bounds.getMinimum().x = temp[index].x;
                    balanceSegment(temp, (2 * index) + 1, median + 1, end);
                    bounds.getMinimum().x = tmp;
                    break;
                case Photon.SPLIT_Y:
                    tmp = bounds.getMinimum().y;
                    bounds.getMinimum().y = temp[index].y;
                    balanceSegment(temp, (2 * index) + 1, median + 1, end);
                    bounds.getMinimum().y = tmp;
                    break;
                default:
                    tmp = bounds.getMinimum().z;
                    bounds.getMinimum().z = temp[index].z;
                    balanceSegment(temp, (2 * index) + 1, median + 1, end);
                    bounds.getMinimum().z = tmp;
            }
        } else {
            temp[(2 * index) + 1] = photons[end];
        }
    }
}
Also used : Vector3(org.sunflow.math.Vector3)

Example 3 with Vector3

use of org.sunflow.math.Vector3 in project joons-renderer by joonhyublee.

the class GridPhotonMap method getRadiance.

@Override
public synchronized Color getRadiance(Point3 p, Vector3 n) {
    if (!bounds.contains(p)) {
        return Color.BLACK;
    }
    Vector3 ext = bounds.getExtents();
    int ix = (int) (((p.x - bounds.getMinimum().x) * nx) / ext.x);
    int iy = (int) (((p.y - bounds.getMinimum().y) * ny) / ext.y);
    int iz = (int) (((p.z - bounds.getMinimum().z) * nz) / ext.z);
    ix = MathUtils.clamp(ix, 0, nx - 1);
    iy = MathUtils.clamp(iy, 0, ny - 1);
    iz = MathUtils.clamp(iz, 0, nz - 1);
    int id = ix + iy * nx + iz * nx * ny;
    rwl.readLock().lock();
    PhotonGroup center = null;
    for (PhotonGroup g = get(ix, iy, iz); g != null; g = g.next) {
        if (g.id == id && Vector3.dot(n, g.normal) > NORMAL_THRESHOLD) {
            if (g.radiance == null) {
                center = g;
                break;
            }
            Color r = g.radiance.copy();
            rwl.readLock().unlock();
            return r;
        }
    }
    int vol = 1;
    while (true) {
        int numPhotons = 0;
        int ndiff = 0;
        Color irr = Color.black();
        Color diff = (center == null) ? Color.black() : null;
        for (int z = iz - (vol - 1); z <= iz + (vol - 1); z++) {
            for (int y = iy - (vol - 1); y <= iy + (vol - 1); y++) {
                for (int x = ix - (vol - 1); x <= ix + (vol - 1); x++) {
                    int vid = x + y * nx + z * nx * ny;
                    for (PhotonGroup g = get(x, y, z); g != null; g = g.next) {
                        if (g.id == vid && Vector3.dot(n, g.normal) > NORMAL_THRESHOLD) {
                            numPhotons += g.count;
                            irr.add(g.flux);
                            if (diff != null) {
                                diff.add(g.diffuse);
                                ndiff++;
                            }
                            // only one valid group can be found,
                            break;
                        // skip the others
                        }
                    }
                }
            }
        }
        if (numPhotons >= numGather || vol >= 3) {
            // we have found enough photons
            // cache irradiance and return
            float area = (2 * vol - 1) / 3.0f * ((ext.x / nx) + (ext.y / ny) + (ext.z / nz));
            area *= area;
            area *= Math.PI;
            irr.mul(1.0f / area);
            // upgrade lock manually
            rwl.readLock().unlock();
            rwl.writeLock().lock();
            try {
                if (center == null) {
                    if (ndiff > 0) {
                        diff.mul(1.0f / ndiff);
                    }
                    center = new PhotonGroup(id, n);
                    center.diffuse.set(diff);
                    center.next = cellHash[id % cellHash.length];
                    cellHash[id % cellHash.length] = center;
                }
                irr.mul(center.diffuse);
                center.radiance = irr.copy();
            } finally {
                rwl.writeLock().unlock();
            }
            return irr;
        }
        vol++;
    }
}
Also used : Color(org.sunflow.image.Color) Vector3(org.sunflow.math.Vector3)

Example 4 with Vector3

use of org.sunflow.math.Vector3 in project joons-renderer by joonhyublee.

the class SCParser method parseCameraMatrix.

private void parseCameraMatrix(int index, SunflowAPIInterface api) throws IOException, ParserException {
    String offset = index < 0 ? "" : String.format("[%d]", index);
    if (p.peekNextToken(TRANSFORM)) {
        // advanced camera
        api.parameter(String.format("transform%s", offset), parseMatrix());
    } else {
        if (index >= 0) {
            p.checkNextToken("{");
        }
        // regular camera specification
        p.checkNextToken("eye");
        Point3 eye = parsePoint();
        p.checkNextToken("target");
        Point3 target = parsePoint();
        p.checkNextToken("up");
        Vector3 up = parseVector();
        api.parameter(String.format("transform%s", offset), Matrix4.lookAt(eye, target, up));
        if (index >= 0) {
            p.checkNextToken("}");
        }
    }
}
Also used : Point3(org.sunflow.math.Point3) Vector3(org.sunflow.math.Vector3)

Example 5 with Vector3

use of org.sunflow.math.Vector3 in project joons-renderer by joonhyublee.

the class GlobalPhotonMap method balanceSegment.

private void balanceSegment(Photon[] temp, int index, int start, int end) {
    int median = 1;
    while ((4 * median) <= (end - start + 1)) {
        median += median;
    }
    if ((3 * median) <= (end - start + 1)) {
        median += median;
        median += (start - 1);
    } else {
        median = end - median + 1;
    }
    int axis = Photon.SPLIT_Z;
    Vector3 extents = bounds.getExtents();
    if ((extents.x > extents.y) && (extents.x > extents.z)) {
        axis = Photon.SPLIT_X;
    } else if (extents.y > extents.z) {
        axis = Photon.SPLIT_Y;
    }
    int left = start;
    int right = end;
    while (right > left) {
        double v = photons[right].getCoord(axis);
        int i = left - 1;
        int j = right;
        while (true) {
            while (photons[++i].getCoord(axis) < v) {
            }
            while ((photons[--j].getCoord(axis) > v) && (j > left)) {
            }
            if (i >= j) {
                break;
            }
            swap(i, j);
        }
        swap(i, right);
        if (i >= median) {
            right = i - 1;
        }
        if (i <= median) {
            left = i + 1;
        }
    }
    temp[index] = photons[median];
    temp[index].setSplitAxis(axis);
    if (median > start) {
        if (start < (median - 1)) {
            float tmp;
            switch(axis) {
                case Photon.SPLIT_X:
                    tmp = bounds.getMaximum().x;
                    bounds.getMaximum().x = temp[index].x;
                    balanceSegment(temp, 2 * index, start, median - 1);
                    bounds.getMaximum().x = tmp;
                    break;
                case Photon.SPLIT_Y:
                    tmp = bounds.getMaximum().y;
                    bounds.getMaximum().y = temp[index].y;
                    balanceSegment(temp, 2 * index, start, median - 1);
                    bounds.getMaximum().y = tmp;
                    break;
                default:
                    tmp = bounds.getMaximum().z;
                    bounds.getMaximum().z = temp[index].z;
                    balanceSegment(temp, 2 * index, start, median - 1);
                    bounds.getMaximum().z = tmp;
            }
        } else {
            temp[2 * index] = photons[start];
        }
    }
    if (median < end) {
        if ((median + 1) < end) {
            float tmp;
            switch(axis) {
                case Photon.SPLIT_X:
                    tmp = bounds.getMinimum().x;
                    bounds.getMinimum().x = temp[index].x;
                    balanceSegment(temp, (2 * index) + 1, median + 1, end);
                    bounds.getMinimum().x = tmp;
                    break;
                case Photon.SPLIT_Y:
                    tmp = bounds.getMinimum().y;
                    bounds.getMinimum().y = temp[index].y;
                    balanceSegment(temp, (2 * index) + 1, median + 1, end);
                    bounds.getMinimum().y = tmp;
                    break;
                default:
                    tmp = bounds.getMinimum().z;
                    bounds.getMinimum().z = temp[index].z;
                    balanceSegment(temp, (2 * index) + 1, median + 1, end);
                    bounds.getMinimum().z = tmp;
            }
        } else {
            temp[(2 * index) + 1] = photons[end];
        }
    }
}
Also used : Vector3(org.sunflow.math.Vector3)

Aggregations

Vector3 (org.sunflow.math.Vector3)75 Color (org.sunflow.image.Color)34 Point3 (org.sunflow.math.Point3)27 Ray (org.sunflow.core.Ray)25 OrthoNormalBasis (org.sunflow.math.OrthoNormalBasis)17 Instance (org.sunflow.core.Instance)11 LightSample (org.sunflow.core.LightSample)8 ShadingState (org.sunflow.core.ShadingState)3 ParameterList (org.sunflow.core.ParameterList)2 TriangleMesh (org.sunflow.core.primitive.TriangleMesh)2 XYZColor (org.sunflow.image.XYZColor)2 Timer (org.sunflow.system.Timer)2 File (java.io.File)1 FileInputStream (java.io.FileInputStream)1 FileNotFoundException (java.io.FileNotFoundException)1 IOException (java.io.IOException)1 FloatBuffer (java.nio.FloatBuffer)1 MappedByteBuffer (java.nio.MappedByteBuffer)1 ReentrantReadWriteLock (java.util.concurrent.locks.ReentrantReadWriteLock)1 PrimitiveList (org.sunflow.core.PrimitiveList)1