Search in sources :

Example 6 with IndexCache

use of processing.opengl.PGraphicsOpenGL.IndexCache in project processing by processing.

the class PShapeOpenGL method updatePolyIndexCache.

// Updates the index cache for the range that corresponds to this shape.
protected void updatePolyIndexCache() {
    IndexCache cache = tessGeo.polyIndexCache;
    if (family == GROUP) {
        // Updates the index cache to include the elements corresponding to
        // a group shape, using the cache entries of the child shapes. The
        // index cache has a pyramidal structure where the base is formed
        // by the entries corresponding to the leaf (geometry) shapes, and
        // each subsequent level is determined by the higher-level group shapes
        // The index pyramid is flattened into arrays in order to use simple
        // data structures, so each shape needs to store the positions in the
        // cache that corresponds to itself.
        // The index ranges of the child shapes that share the vertex offset
        // are unified into a single range in the parent level.
        firstPolyIndexCache = lastPolyIndexCache = -1;
        int gindex = -1;
        for (int i = 0; i < childCount; i++) {
            PShapeOpenGL child = (PShapeOpenGL) children[i];
            int first = child.firstPolyIndexCache;
            int count = -1 < first ? child.lastPolyIndexCache - first + 1 : -1;
            for (int n = first; n < first + count; n++) {
                if (gindex == -1) {
                    gindex = cache.addNew(n);
                    firstPolyIndexCache = gindex;
                } else {
                    if (cache.vertexOffset[gindex] == cache.vertexOffset[n]) {
                        // When the vertex offsets are the same, this means that the
                        // current index range in the group shape can be extended to
                        // include the index range in the current child shape.
                        // This is a result of how the indices are updated for the
                        // leaf shapes.
                        cache.incCounts(gindex, cache.indexCount[n], cache.vertexCount[n]);
                    } else {
                        gindex = cache.addNew(n);
                    }
                }
            }
            // Updating the first and last poly vertices for this group shape.
            if (-1 < child.firstPolyVertex) {
                if (firstPolyVertex == -1) {
                    firstPolyVertex = Integer.MAX_VALUE;
                }
                firstPolyVertex = PApplet.min(firstPolyVertex, child.firstPolyVertex);
            }
            if (-1 < child.lastPolyVertex) {
                lastPolyVertex = PApplet.max(lastPolyVertex, child.lastPolyVertex);
            }
        }
        lastPolyIndexCache = gindex;
    } else {
        // The index cache is updated in order to reflect the fact that all
        // the vertices will be stored in a single VBO in the root shape.
        // This update works as follows (the methodology is the same for
        // poly, line and point): the VertexAbs variable in the root shape
        // stores the index of the last vertex up to this shape (plus one)
        // without taking into consideration the MAX_VERTEX_INDEX limit, so
        // it effectively runs over the entire range.
        // VertexRel, on the other hand, is reset every time the limit is
        // exceeded, therefore creating the start of a new index group in the
        // root shape. When this happens, the indices in the child shape need
        // to be restarted as well to reflect the new index offset.
        firstPolyVertex = lastPolyVertex = cache.vertexOffset[firstPolyIndexCache];
        for (int n = firstPolyIndexCache; n <= lastPolyIndexCache; n++) {
            int ioffset = cache.indexOffset[n];
            int icount = cache.indexCount[n];
            int vcount = cache.vertexCount[n];
            if (// Too many vertices already signal the start of a new cache...
            PGL.MAX_VERTEX_INDEX1 <= root.polyVertexRel + vcount || (is2D() && startStrokedTex(n))) {
                // ... or, in 2D, the beginning of line or points.
                root.polyVertexRel = 0;
                root.polyVertexOffset = root.polyVertexAbs;
                cache.indexOffset[n] = root.polyIndexOffset;
            } else {
                tessGeo.incPolyIndices(ioffset, ioffset + icount - 1, root.polyVertexRel);
            }
            cache.vertexOffset[n] = root.polyVertexOffset;
            if (is2D()) {
                setFirstStrokeVertex(n, lastPolyVertex);
            }
            root.polyIndexOffset += icount;
            root.polyVertexAbs += vcount;
            root.polyVertexRel += vcount;
            lastPolyVertex += vcount;
        }
        lastPolyVertex--;
        if (is2D()) {
            setLastStrokeVertex(lastPolyVertex);
        }
    }
}
Also used : IndexCache(processing.opengl.PGraphicsOpenGL.IndexCache)

Example 7 with IndexCache

use of processing.opengl.PGraphicsOpenGL.IndexCache in project processing by processing.

the class PShapeOpenGL method renderPolys.

protected void renderPolys(PGraphicsOpenGL g, PImage textureImage) {
    boolean customShader = g.polyShader != null;
    boolean needNormals = customShader ? g.polyShader.accessNormals() : false;
    boolean needTexCoords = customShader ? g.polyShader.accessTexCoords() : false;
    Texture tex = textureImage != null ? g.getTexture(textureImage) : null;
    boolean renderingFill = false, renderingStroke = false;
    PShader shader = null;
    IndexCache cache = tessGeo.polyIndexCache;
    for (int n = firstPolyIndexCache; n <= lastPolyIndexCache; n++) {
        if (is3D() || (tex != null && (firstLineIndexCache == -1 || n < firstLineIndexCache) && (firstPointIndexCache == -1 || n < firstPointIndexCache))) {
            // Rendering fill triangles, which can be lit and textured.
            if (!renderingFill) {
                shader = g.getPolyShader(g.lights, tex != null);
                shader.bind();
                renderingFill = true;
            }
        } else {
            // Rendering line or point triangles, which are never lit nor textured.
            if (!renderingStroke) {
                if (tex != null) {
                    tex.unbind();
                    tex = null;
                }
                if (shader != null && shader.bound()) {
                    shader.unbind();
                }
                // If the renderer is 2D, then g.lights should always be false,
                // so no need to worry about that.
                shader = g.getPolyShader(g.lights, false);
                shader.bind();
                renderingFill = false;
                renderingStroke = true;
            }
        }
        int ioffset = cache.indexOffset[n];
        int icount = cache.indexCount[n];
        int voffset = cache.vertexOffset[n];
        shader.setVertexAttribute(root.bufPolyVertex.glId, 4, PGL.FLOAT, 0, 4 * voffset * PGL.SIZEOF_FLOAT);
        shader.setColorAttribute(root.bufPolyColor.glId, 4, PGL.UNSIGNED_BYTE, 0, 4 * voffset * PGL.SIZEOF_BYTE);
        if (g.lights) {
            shader.setNormalAttribute(root.bufPolyNormal.glId, 3, PGL.FLOAT, 0, 3 * voffset * PGL.SIZEOF_FLOAT);
            shader.setAmbientAttribute(root.bufPolyAmbient.glId, 4, PGL.UNSIGNED_BYTE, 0, 4 * voffset * PGL.SIZEOF_BYTE);
            shader.setSpecularAttribute(root.bufPolySpecular.glId, 4, PGL.UNSIGNED_BYTE, 0, 4 * voffset * PGL.SIZEOF_BYTE);
            shader.setEmissiveAttribute(root.bufPolyEmissive.glId, 4, PGL.UNSIGNED_BYTE, 0, 4 * voffset * PGL.SIZEOF_BYTE);
            shader.setShininessAttribute(root.bufPolyShininess.glId, 1, PGL.FLOAT, 0, voffset * PGL.SIZEOF_FLOAT);
        }
        if (g.lights || needNormals) {
            shader.setNormalAttribute(root.bufPolyNormal.glId, 3, PGL.FLOAT, 0, 3 * voffset * PGL.SIZEOF_FLOAT);
        }
        if (tex != null || needTexCoords) {
            shader.setTexcoordAttribute(root.bufPolyTexcoord.glId, 2, PGL.FLOAT, 0, 2 * voffset * PGL.SIZEOF_FLOAT);
            shader.setTexture(tex);
        }
        for (VertexAttribute attrib : polyAttribs.values()) {
            if (!attrib.active(shader))
                continue;
            attrib.bind(pgl);
            shader.setAttributeVBO(attrib.glLoc, attrib.buf.glId, attrib.tessSize, attrib.type, attrib.isColor(), 0, attrib.sizeInBytes(voffset));
        }
        shader.draw(root.bufPolyIndex.glId, icount, ioffset);
    }
    for (VertexAttribute attrib : polyAttribs.values()) {
        if (attrib.active(shader))
            attrib.unbind(pgl);
    }
    if (shader != null && shader.bound()) {
        shader.unbind();
    }
}
Also used : IndexCache(processing.opengl.PGraphicsOpenGL.IndexCache) VertexAttribute(processing.opengl.PGraphicsOpenGL.VertexAttribute)

Example 8 with IndexCache

use of processing.opengl.PGraphicsOpenGL.IndexCache in project processing by processing.

the class PShapeOpenGL method updateLineIndexCache.

protected void updateLineIndexCache() {
    IndexCache cache = tessGeo.lineIndexCache;
    if (family == GROUP) {
        firstLineIndexCache = lastLineIndexCache = -1;
        int gindex = -1;
        for (int i = 0; i < childCount; i++) {
            PShapeOpenGL child = (PShapeOpenGL) children[i];
            int first = child.firstLineIndexCache;
            int count = -1 < first ? child.lastLineIndexCache - first + 1 : -1;
            for (int n = first; n < first + count; n++) {
                if (gindex == -1) {
                    gindex = cache.addNew(n);
                    firstLineIndexCache = gindex;
                } else {
                    if (cache.vertexOffset[gindex] == cache.vertexOffset[n]) {
                        cache.incCounts(gindex, cache.indexCount[n], cache.vertexCount[n]);
                    } else {
                        gindex = cache.addNew(n);
                    }
                }
            }
            // Updating the first and last line vertices for this group shape.
            if (-1 < child.firstLineVertex) {
                if (firstLineVertex == -1)
                    firstLineVertex = Integer.MAX_VALUE;
                firstLineVertex = PApplet.min(firstLineVertex, child.firstLineVertex);
            }
            if (-1 < child.lastLineVertex) {
                lastLineVertex = PApplet.max(lastLineVertex, child.lastLineVertex);
            }
        }
        lastLineIndexCache = gindex;
    } else {
        firstLineVertex = lastLineVertex = cache.vertexOffset[firstLineIndexCache];
        for (int n = firstLineIndexCache; n <= lastLineIndexCache; n++) {
            int ioffset = cache.indexOffset[n];
            int icount = cache.indexCount[n];
            int vcount = cache.vertexCount[n];
            if (PGL.MAX_VERTEX_INDEX1 <= root.lineVertexRel + vcount) {
                root.lineVertexRel = 0;
                root.lineVertexOffset = root.lineVertexAbs;
                cache.indexOffset[n] = root.lineIndexOffset;
            } else {
                tessGeo.incLineIndices(ioffset, ioffset + icount - 1, root.lineVertexRel);
            }
            cache.vertexOffset[n] = root.lineVertexOffset;
            root.lineIndexOffset += icount;
            root.lineVertexAbs += vcount;
            root.lineVertexRel += vcount;
            lastLineVertex += vcount;
        }
        lastLineVertex--;
    }
}
Also used : IndexCache(processing.opengl.PGraphicsOpenGL.IndexCache)

Example 9 with IndexCache

use of processing.opengl.PGraphicsOpenGL.IndexCache in project processing by processing.

the class PShapeOpenGL method getTessellation.

///////////////////////////////////////////////////////////
//
// Tessellated geometry getter.
@Override
public PShape getTessellation() {
    updateTessellation();
    float[] vertices = tessGeo.polyVertices;
    float[] normals = tessGeo.polyNormals;
    int[] color = tessGeo.polyColors;
    float[] uv = tessGeo.polyTexCoords;
    short[] indices = tessGeo.polyIndices;
    PShape tess;
    //    if (is3D()) {
    //      //tess = PGraphics3D.createShapeImpl(pg, PShape.GEOMETRY);
    //      tess = pg.createShapeFamily(PShape.GEOMETRY);
    //    } else if (is2D()) {
    //      //tess = PGraphics2D.createShapeImpl(pg, PShape.GEOMETRY);
    //      tess = pg.createShapeFamily(PShape.GEOMETRY);
    //    } else {
    //      PGraphics.showWarning("This shape is not either 2D or 3D!");
    //      return null;
    //    }
    tess = pg.createShapeFamily(PShape.GEOMETRY);
    // if this is a 3D shape, make the new shape 3D as well
    tess.set3D(is3D);
    tess.beginShape(TRIANGLES);
    tess.noStroke();
    IndexCache cache = tessGeo.polyIndexCache;
    for (int n = firstPolyIndexCache; n <= lastPolyIndexCache; n++) {
        int ioffset = cache.indexOffset[n];
        int icount = cache.indexCount[n];
        int voffset = cache.vertexOffset[n];
        for (int tr = ioffset / 3; tr < (ioffset + icount) / 3; tr++) {
            int i0 = voffset + indices[3 * tr + 0];
            int i1 = voffset + indices[3 * tr + 1];
            int i2 = voffset + indices[3 * tr + 2];
            if (is3D()) {
                float x0 = vertices[4 * i0 + 0];
                float y0 = vertices[4 * i0 + 1];
                float z0 = vertices[4 * i0 + 2];
                float x1 = vertices[4 * i1 + 0];
                float y1 = vertices[4 * i1 + 1];
                float z1 = vertices[4 * i1 + 2];
                float x2 = vertices[4 * i2 + 0];
                float y2 = vertices[4 * i2 + 1];
                float z2 = vertices[4 * i2 + 2];
                float nx0 = normals[3 * i0 + 0];
                float ny0 = normals[3 * i0 + 1];
                float nz0 = normals[3 * i0 + 2];
                float nx1 = normals[3 * i1 + 0];
                float ny1 = normals[3 * i1 + 1];
                float nz1 = normals[3 * i1 + 2];
                float nx2 = normals[3 * i2 + 0];
                float ny2 = normals[3 * i2 + 1];
                float nz2 = normals[3 * i2 + 2];
                int argb0 = PGL.nativeToJavaARGB(color[i0]);
                int argb1 = PGL.nativeToJavaARGB(color[i1]);
                int argb2 = PGL.nativeToJavaARGB(color[i2]);
                tess.fill(argb0);
                tess.normal(nx0, ny0, nz0);
                tess.vertex(x0, y0, z0, uv[2 * i0 + 0], uv[2 * i0 + 1]);
                tess.fill(argb1);
                tess.normal(nx1, ny1, nz1);
                tess.vertex(x1, y1, z1, uv[2 * i1 + 0], uv[2 * i1 + 1]);
                tess.fill(argb2);
                tess.normal(nx2, ny2, nz2);
                tess.vertex(x2, y2, z2, uv[2 * i2 + 0], uv[2 * i2 + 1]);
            } else if (is2D()) {
                float x0 = vertices[4 * i0 + 0], y0 = vertices[4 * i0 + 1];
                float x1 = vertices[4 * i1 + 0], y1 = vertices[4 * i1 + 1];
                float x2 = vertices[4 * i2 + 0], y2 = vertices[4 * i2 + 1];
                int argb0 = PGL.nativeToJavaARGB(color[i0]);
                int argb1 = PGL.nativeToJavaARGB(color[i1]);
                int argb2 = PGL.nativeToJavaARGB(color[i2]);
                tess.fill(argb0);
                tess.vertex(x0, y0, uv[2 * i0 + 0], uv[2 * i0 + 1]);
                tess.fill(argb1);
                tess.vertex(x1, y1, uv[2 * i1 + 0], uv[2 * i1 + 1]);
                tess.fill(argb2);
                tess.vertex(x2, y2, uv[2 * i2 + 0], uv[2 * i2 + 1]);
            }
        }
    }
    tess.endShape();
    return tess;
}
Also used : PShape(processing.core.PShape) IndexCache(processing.opengl.PGraphicsOpenGL.IndexCache)

Example 10 with IndexCache

use of processing.opengl.PGraphicsOpenGL.IndexCache in project processing by processing.

the class PShapeOpenGL method renderLines.

protected void renderLines(PGraphicsOpenGL g) {
    PShader shader = g.getLineShader();
    shader.bind();
    IndexCache cache = tessGeo.lineIndexCache;
    for (int n = firstLineIndexCache; n <= lastLineIndexCache; n++) {
        int ioffset = cache.indexOffset[n];
        int icount = cache.indexCount[n];
        int voffset = cache.vertexOffset[n];
        shader.setVertexAttribute(root.bufLineVertex.glId, 4, PGL.FLOAT, 0, 4 * voffset * PGL.SIZEOF_FLOAT);
        shader.setColorAttribute(root.bufLineColor.glId, 4, PGL.UNSIGNED_BYTE, 0, 4 * voffset * PGL.SIZEOF_BYTE);
        shader.setLineAttribute(root.bufLineAttrib.glId, 4, PGL.FLOAT, 0, 4 * voffset * PGL.SIZEOF_FLOAT);
        shader.draw(root.bufLineIndex.glId, icount, ioffset);
    }
    shader.unbind();
}
Also used : IndexCache(processing.opengl.PGraphicsOpenGL.IndexCache)

Aggregations

IndexCache (processing.opengl.PGraphicsOpenGL.IndexCache)10 PGraphics (processing.core.PGraphics)3 PShape (processing.core.PShape)1 VertexAttribute (processing.opengl.PGraphicsOpenGL.VertexAttribute)1