package com.exh.bevel.algo; import java.util.List; import android.graphics.RectF; import com.exh.bevel.BevelView; import com.exh.bevel.ProgressReport; import com.exh.bevel.render.Spotlight; import com.exh.math.primitive.Plane; import com.exh.math.primitive.Point3; import com.exh.math.primitive.Polygon; import com.exh.math.primitive.Segment; import com.exh.math.primitive.Tri; import com.exh.math.tests.LinePlane; import com.exh.math.tests.SegPlane; /* CLIP * The clipping algorith. Given a list of extruded tris, * find where they overlap in 3D space and cut at the * intersections. */ public final class Clip { public Spotlight mSpotlight; // Clients need to set this vec to something that will generate // the proper mesh object based on the cmp tris. That is, turn // a flat tri into a 3d volume that can be clipped against. private final Point3 mExt = new Point3(0, 0, 0); private final Plane mSrcP = new Plane(); // Intersection tests private final LinePlane mLP = new LinePlane(); private final SegPlane mSP = new SegPlane(); private final Mask mMask = new Mask(); private final Point3.Order mOrder = new Point3.Order(); // Tmp storage private final Point3 mPtA = new Point3(); private final Segment mSegA = new Segment(); private final Polygon mPolyB = new Polygon(), mPolyPrj = new Polygon(); // The destination poly projected // onto the source plane private final RectF mSrcF = new RectF(), mCmpF = new RectF(); private int[] mI = new int[8]; // Should cover any input private final boolean acceptDst(final int idx) { if (BevelView.EDIT_MODE) return idx == 0; // return ((idx == 37)); return true; } // The extensionVec is a vector describing how to extend the // target triangle into a 3d volume. For my purposes, it will // always just be a point of x=0,y=0,z=something large enough // to cover the bevel depth. public void on( final Point3 extensionVec, final List input, final List output, final ProgressReport progress) { mExt.set(extensionVec); if (mSpotlight != null) mSpotlight.clear(); mMask.mSpotlight = mSpotlight; final boolean TESTING = false; final boolean CLIP = (BevelView.EDIT_MODE ? true : true); final boolean CLIP_RANGE = (BevelView.EDIT_MODE ? false : false); final float size = (float)input.size(); // Clip each tri in input against all others in input, placing the results // into output. System.out.println("ON size=" + input.size()); int idx = -1; for (Polygon src : input) { idx++; if (progress != null) progress.setProgressReport(((float)idx) / size); if (acceptDst(idx)) { mSrcP.from(src); src.getFrame(mSrcF); System.out.println("DST " + idx + "=" + src); //src.print(); //if (TESTING) System.out.println("DST=" + src); mMask.start(); int cnt = -1; for (Polygon cmp : input) { cnt++; if (!CLIP) continue; if (CLIP_RANGE) { if (!(cnt == 1)) continue; // if (!(cnt >= 4 & cnt <= 4)) continue; // if (!(cnt >= 3 & cnt <= 3)) continue; } if (src == cmp) continue; // mSpotlight.pushPoly(cmp); // Rely on the fact that we have a fixed overhead viewing // angle, so if frames don't overlap in XY space, they // won't intersect at all. cmp.getFrame(mCmpF); if (!RectF.intersects(mSrcF, mCmpF)) continue; //System.out.println("CLIP AGAINST=" + cnt + " " + cmp); //if (src != cmp) continue; //if (cmp != ct) continue; if (TESTING) System.out.println("src " + cnt + " = " + cmp); // Get a poly describing the intersection of the source // plane and the cmp tri. Add the poly to the clip. // Note that it's possible for the dst poly to be collapsed // down to as small as a single point based on how things // intersect. Which, obviously, is not right. mPolyB.clear(); if (getDstPoly(mSrcP, cmp, mPolyB) && mPolyB.mSize > 2) { // for (int k=0; k 2) { //System.out.println("clip against " + cnt); //mPolyB.print(); mOrder.makeCcw(mPolyB.mPt, mPolyB.mSize); //for (int k=0; k= org.mSize) { for (int k=0; k= org.mSize) { return false; } //System.out.println("case3"); // Any pts below are added straight in, any above are found // where the intersection is with the one below. Point3 oprv = org.mPt[org.mSize-1]; int iprv = mI[org.mSize-1]; for (int k=0; k 0) { mSegA.set(oprv, onxt); if (mSP.on(mSegA, srcP, mPtA) >= SegPlane.INTERSECT) { dst.add(mPtA); } } // Now add in this point if (!dst.sameAsLast(snxt, 0.1)) dst.add(snxt); // This point is above. If the previous is below or equal, // find the segment intersection with the src plane. } else if (iprv <= 0) { mSegA.set(oprv, onxt); if (mSP.on(mSegA, srcP, mPtA) >= SegPlane.INTERSECT) { if (!dst.sameAsLast(mPtA, 0.1)) { dst.add(mPtA); } } } oprv = onxt; iprv = inxt; } return true; } private boolean validateI(final int size) { if (mI != null && size <= mI.length) return true; try { mI = new int[size+4]; return true; } catch (Exception ex) { } return false; } }