diff options
Diffstat (limited to 'src')
70 files changed, 13347 insertions, 0 deletions
diff --git a/src/classes/com/sun/opengl/impl/awt/packrect/BackingStoreManager.java b/src/classes/com/sun/opengl/impl/awt/packrect/BackingStoreManager.java new file mode 100755 index 000000000..acff0aa79 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/awt/packrect/BackingStoreManager.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.sun.opengl.impl.awt.packrect; + +/** This interface must be implemented by the end user and is called + in response to events like addition of rectangles into the + RectanglePacker. It is used both when a full re-layout must be + done as well as when the data in the backing store must be copied + to a new one. */ + +public interface BackingStoreManager { + public Object allocateBackingStore(int w, int h); + public void deleteBackingStore(Object backingStore); + + /** Notification that expansion of the backing store is about to be + done due to addition of the given rectangle. Gives the manager a + chance to do some compaction and potentially remove old entries + from the backing store, if it acts like a least-recently-used + cache. This method receives as argument the number of attempts + so far to add the given rectangle. Manager should return true if + the RectanglePacker should retry the addition (which may result + in this method being called again, with an increased attempt + number) or false if the RectanglePacker should just expand the + backing store. The caller should not call RectanglePacker.add() + in its preExpand() method. */ + public boolean preExpand(Rect cause, int attemptNumber); + + /** Notification that addition of the given Rect failed because a + maximum size was set in the RectanglePacker and the backing + store could not be expanded. */ + public void additionFailed(Rect cause, int attemptNumber); + + /** Notification that movement is starting. */ + public void beginMovement(Object oldBackingStore, Object newBackingStore); + + /** Tells the manager to move the contents of the given rect from + the old location on the old backing store to the new location on + the new backing store. The backing stores can be identical in + the case of compacting the existing backing store instead of + reallocating it. */ + public void move(Object oldBackingStore, + Rect oldLocation, + Object newBackingStore, + Rect newLocation); + + /** Notification that movement is ending. */ + public void endMovement(Object oldBackingStore, Object newBackingStore); +} diff --git a/src/classes/com/sun/opengl/impl/awt/packrect/Level.java b/src/classes/com/sun/opengl/impl/awt/packrect/Level.java new file mode 100755 index 000000000..2ef6cb989 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/awt/packrect/Level.java @@ -0,0 +1,275 @@ +/* + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.sun.opengl.impl.awt.packrect; + +import java.util.*; + +public class Level { + private int width; + private int height; + private int yPos; + private LevelSet holder; + + private List/*<Rect>*/ rects = new ArrayList/*<Rect>*/(); + private List/*<Rect>*/ freeList; + private int nextAddX; + + static class RectXComparator implements Comparator { + public int compare(Object o1, Object o2) { + Rect r1 = (Rect) o1; + Rect r2 = (Rect) o2; + return r1.x() - r2.x(); + } + + public boolean equals(Object obj) { + return this == obj; + } + } + private static final Comparator rectXComparator = new RectXComparator(); + + public Level(int width, int height, int yPos, LevelSet holder) { + this.width = width; + this.height = height; + this.yPos = yPos; + this.holder = holder; + } + + public int w() { return width; } + public int h() { return height; } + public int yPos() { return yPos; } + + /** Tries to add the given rectangle to this level only allowing + non-disruptive changes like trivial expansion of the last level + in the RectanglePacker and allocation from the free list. More + disruptive changes like compaction of the level must be + requested explicitly. */ + public boolean add(Rect rect) { + if (rect.h() > height) { + // See whether it's worth trying to expand vertically + if (nextAddX + rect.w() > width) { + return false; + } + + // See whether we're the last level and can expand + if (!holder.canExpand(this, rect.h())) { + return false; + } + + // Trivially expand and try the allocation + holder.expand(this, height, rect.h()); + height = rect.h(); + } + + // See whether we can add at the end + if (nextAddX + rect.w() <= width) { + rect.setPosition(nextAddX, yPos); + rects.add(rect); + nextAddX += rect.w(); + return true; + } + + // See whether we can add from the free list + if (freeList != null) { + Rect candidate = null; + for (Iterator iter = freeList.iterator(); iter.hasNext(); ) { + Rect cur = (Rect) iter.next(); + if (cur.canContain(rect)) { + candidate = cur; + break; + } + } + + if (candidate != null) { + // Remove the candidate from the free list + freeList.remove(candidate); + // Set up and add the real rect + rect.setPosition(candidate.x(), candidate.y()); + rects.add(rect); + // Re-add any remaining free space + if (candidate.w() > rect.w()) { + candidate.setPosition(candidate.x() + rect.w(), candidate.y()); + candidate.setSize(candidate.w() - rect.w(), height); + freeList.add(candidate); + } + + coalesceFreeList(); + + return true; + } + } + + return false; + } + + /** Removes the given Rect from this Level. */ + public boolean remove(Rect rect) { + if (!rects.remove(rect)) + return false; + + // If this is the rightmost rectangle, instead of adding its space + // to the free list, we can just decrease the nextAddX + if (rect.maxX() + 1 == nextAddX) { + nextAddX -= rect.w(); + } else { + if (freeList == null) { + freeList = new ArrayList/*<Rect>*/(); + } + freeList.add(new Rect(rect.x(), rect.y(), rect.w(), height, null)); + coalesceFreeList(); + } + + return true; + } + + /** Indicates whether this Level contains no rectangles. */ + public boolean isEmpty() { + return rects.isEmpty(); + } + + /** Indicates whether this Level could satisfy an allocation request + if it were compacted. */ + public boolean couldAllocateIfCompacted(Rect rect) { + if (rect.h() > height) + return false; + if (freeList == null) + return false; + int freeListWidth = 0; + for (Iterator iter = freeList.iterator(); iter.hasNext(); ) { + Rect cur = (Rect) iter.next(); + freeListWidth += cur.w(); + } + // Add on the remaining space at the end + freeListWidth += (width - nextAddX); + return (freeListWidth >= rect.w()); + } + + public void compact(Object backingStore, BackingStoreManager manager) { + Collections.sort(rects, rectXComparator); + int nextCompactionDest = 0; + manager.beginMovement(backingStore, backingStore); + for (Iterator iter = rects.iterator(); iter.hasNext(); ) { + Rect cur = (Rect) iter.next(); + if (cur.x() != nextCompactionDest) { + manager.move(backingStore, cur, + backingStore, new Rect(nextCompactionDest, cur.y(), cur.w(), cur.h(), null)); + cur.setPosition(nextCompactionDest, cur.y()); + } + nextCompactionDest += cur.w(); + } + nextAddX = nextCompactionDest; + freeList.clear(); + manager.endMovement(backingStore, backingStore); + } + + public Iterator iterator() { + return rects.iterator(); + } + + /** Visits all Rects contained in this Level. */ + public void visit(RectVisitor visitor) { + for (Iterator iter = rects.iterator(); iter.hasNext(); ) { + Rect rect = (Rect) iter.next(); + visitor.visit(rect); + } + } + + /** Updates the references to the Rect objects in this Level with + the "next locations" of those Rects. This is actually used to + update the new Rects in a newly laid-out LevelSet with the + original Rects. */ + public void updateRectangleReferences() { + for (int i = 0; i < rects.size(); i++) { + Rect cur = (Rect) rects.get(i); + Rect next = cur.getNextLocation(); + next.setPosition(cur.x(), cur.y()); + if (cur.w() != next.w() || cur.h() != next.h()) + throw new RuntimeException("Unexpected disparity in rectangle sizes during updateRectangleReferences"); + rects.set(i, next); + } + } + + private void coalesceFreeList() { + if (freeList == null) + return; + if (freeList.isEmpty()) + return; + + // Try to coalesce adjacent free blocks in the free list + Collections.sort(freeList, rectXComparator); + int i = 0; + while (i < freeList.size() - 1) { + Rect r1 = (Rect) freeList.get(i); + Rect r2 = (Rect) freeList.get(i+1); + if (r1.maxX() + 1 == r2.x()) { + // Coalesce r1 and r2 into one block + freeList.remove(i+1); + r1.setSize(r1.w() + r2.w(), r1.h()); + } else { + ++i; + } + } + // See whether the last block bumps up against the addition point + Rect last = (Rect) freeList.get(freeList.size() - 1); + if (last.maxX() + 1 == nextAddX) { + nextAddX -= last.w(); + freeList.remove(freeList.size() - 1); + } + if (freeList.isEmpty()) { + freeList = null; + } + } + + //---------------------------------------------------------------------- + // Debugging functionality + // + + public void dumpFreeSpace() { + int freeListWidth = 0; + for (Iterator iter = freeList.iterator(); iter.hasNext(); ) { + Rect cur = (Rect) iter.next(); + System.err.println(" Free rectangle at " + cur); + freeListWidth += cur.w(); + } + // Add on the remaining space at the end + System.err.println(" Remaining free space " + (width - nextAddX)); + freeListWidth += (width - nextAddX); + System.err.println(" Total free space " + freeListWidth); + } +} diff --git a/src/classes/com/sun/opengl/impl/awt/packrect/LevelSet.java b/src/classes/com/sun/opengl/impl/awt/packrect/LevelSet.java new file mode 100755 index 000000000..724af27e0 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/awt/packrect/LevelSet.java @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.sun.opengl.impl.awt.packrect; + +import java.util.*; + +/** Manages a list of Levels; this is the core data structure + contained within the RectanglePacker and encompasses the storage + algorithm for the contained Rects. */ + +public class LevelSet { + // Maintained in sorted order by increasing Y coordinate + private List/*<Level>*/ levels = new ArrayList/*<Level>*/(); + private int nextAddY; + private int w; + private int h; + + /** A LevelSet manages all of the backing store for a region of a + specified width and height. */ + public LevelSet(int w, int h) { + this.w = w; + this.h = h; + } + + public int w() { return w; } + public int h() { return h; } + + /** Returns true if the given rectangle was successfully added to + the LevelSet given its current dimensions, false if not. Caller + is responsible for performing compaction, expansion, etc. as a + consequence. */ + public boolean add(Rect rect) { + if (rect.w() > w) + return false; + + // Go in reverse order through the levels seeing whether we can + // trivially satisfy the allocation request + for (int i = levels.size() - 1; i >= 0; --i) { + Level level = (Level) levels.get(i); + if (level.add(rect)) + return true; + } + + // See whether compaction could satisfy this allocation. This + // increases the computational complexity of the addition process, + // but prevents us from expanding unnecessarily. + for (int i = levels.size() - 1; i >= 0; --i) { + Level level = (Level) levels.get(i); + if (level.couldAllocateIfCompacted(rect)) + return false; + } + + // OK, we need to either add a new Level or expand the backing + // store. Try to add a new Level. + if (nextAddY + rect.h() > h) + return false; + + Level newLevel = new Level(w, rect.h(), nextAddY, this); + levels.add(newLevel); + nextAddY += rect.h(); + boolean res = newLevel.add(rect); + if (!res) + throw new RuntimeException("Unexpected failure in addition to new Level"); + return true; + } + + /** Removes the given Rect from this LevelSet. */ + public boolean remove(Rect rect) { + for (int i = levels.size() - 1; i >= 0; --i) { + Level level = (Level) levels.get(i); + if (level.remove(rect)) + return true; + } + + return false; + } + + /** Allocates the given Rectangle, performing compaction of a Level + if necessary. This is the correct fallback path to {@link + #add(Rect)} above. Returns true if allocated successfully, false + otherwise (indicating the need to expand the backing store). */ + public boolean compactAndAdd(Rect rect, + Object backingStore, + BackingStoreManager manager) { + for (int i = levels.size() - 1; i >= 0; --i) { + Level level = (Level) levels.get(i); + if (level.couldAllocateIfCompacted(rect)) { + level.compact(backingStore, manager); + boolean res = level.add(rect); + if (!res) + throw new RuntimeException("Unexpected failure to add after compaction"); + return true; + } + } + + return false; + } + + /** Indicates whether it's legal to trivially increase the height of + the given Level. This is only possible if it's the last Level + added and there's enough room in the backing store. */ + public boolean canExpand(Level level, int height) { + if (levels.isEmpty()) + return false; // Should not happen + if (levels.get(levels.size() - 1) == level && + (h - nextAddY >= height - level.h())) + return true; + return false; + } + + public void expand(Level level, int oldHeight, int newHeight) { + nextAddY += (newHeight - oldHeight); + } + + /** Gets the used height of the levels in this LevelSet. */ + public int getUsedHeight() { + return nextAddY; + } + + /** Sets the height of this LevelSet. It is only legal to reduce the + height to greater than or equal to the currently used height. */ + public void setHeight(int height) throws IllegalArgumentException { + if (height < getUsedHeight()) { + throw new IllegalArgumentException("May not reduce height below currently used height"); + } + h = height; + } + + /** Returns the vertical fragmentation ratio of this LevelSet. This + is defined as the ratio of the sum of the heights of all + completely empty Levels divided by the overall used height of + the LevelSet. A high vertical fragmentation ratio indicates that + it may be profitable to perform a compaction. */ + public float verticalFragmentationRatio() { + int freeHeight = 0; + int usedHeight = getUsedHeight(); + if (usedHeight == 0) + return 0.0f; + for (Iterator iter = iterator(); iter.hasNext(); ) { + Level level = (Level) iter.next(); + if (level.isEmpty()) { + freeHeight += level.h(); + } + } + return (float) freeHeight / (float) usedHeight; + } + + public Iterator iterator() { + return levels.iterator(); + } + + /** Visits all Rects contained in this LevelSet. */ + public void visit(RectVisitor visitor) { + for (Iterator iter = levels.iterator(); iter.hasNext(); ) { + Level level = (Level) iter.next(); + level.visit(visitor); + } + } + + /** Updates the references to the Rect objects in this LevelSet with + the "next locations" of those Rects. This is actually used to + update the new Rects in a newly laid-out LevelSet with the + original Rects. */ + public void updateRectangleReferences() { + for (Iterator iter = levels.iterator(); iter.hasNext(); ) { + Level level = (Level) iter.next(); + level.updateRectangleReferences(); + } + } + + /** Clears out all Levels stored in this LevelSet. */ + public void clear() { + levels.clear(); + nextAddY = 0; + } +} diff --git a/src/classes/com/sun/opengl/impl/awt/packrect/Rect.java b/src/classes/com/sun/opengl/impl/awt/packrect/Rect.java new file mode 100755 index 000000000..c3b6be6da --- /dev/null +++ b/src/classes/com/sun/opengl/impl/awt/packrect/Rect.java @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.sun.opengl.impl.awt.packrect; + +/** Represents a rectangular region on the backing store. The edges of + the rectangle are the infinitely thin region between adjacent + pixels on the screen. The origin of the rectangle is its + upper-left corner. It is inclusive of the pixels on the top and + left edges and exclusive of the pixels on the bottom and right + edges. For example, a rect at position (0, 0) and of size (1, 1) + would include only the pixel at (0, 0). <P> + + Negative coordinates and sizes are not supported, since they make + no sense in the context of the packer, which deals only with + positively sized regions. <P> + + This class contains a user data field for efficient hookup to + external data structures as well as enough other hooks to + efficiently plug into the rectangle packer. */ + +public class Rect { + private int x; + private int y; + private int w; + private int h; + + // The level we're currently installed in in the parent + // RectanglePacker, or null if not hooked in to the table yet + private Level level; + + // The user's object this rectangle represents. + private Object userData; + + // Used transiently during re-layout of the backing store (when + // there is no room left due either to fragmentation or just being + // out of space) + private Rect nextLocation; + + public Rect() { + this(null); + } + + public Rect(Object userData) { + this(0, 0, 0, 0, userData); + } + + public Rect(int x, int y, int w, int h, Object userData) { + setPosition(x, y); + setSize(w, h); + setUserData(userData); + } + + public int x() { return x; } + public int y() { return y; } + public int w() { return w; } + public int h() { return h; } + public Object getUserData() { return userData; } + public Rect getNextLocation() { return nextLocation; } + + public void setPosition(int x, int y) { + if (x < 0) + throw new IllegalArgumentException("Negative x"); + if (y < 0) + throw new IllegalArgumentException("Negative y"); + this.x = x; + this.y = y; + } + + public void setSize(int w, int h) throws IllegalArgumentException { + if (w < 0) + throw new IllegalArgumentException("Negative width"); + if (h < 0) + throw new IllegalArgumentException("Negative height"); + this.w = w; + this.h = h; + } + + public void setUserData(Object obj) { userData = obj; } + public void setNextLocation(Rect nextLocation) { this.nextLocation = nextLocation; } + + // Helpers for computations. + + /** Returns the maximum x-coordinate contained within this + rectangle. Note that this returns a different result than Java + 2D's rectangles; for a rectangle of position (0, 0) and size (1, + 1) this will return 0, not 1. Returns -1 if the width of this + rectangle is 0. */ + public int maxX() { + if (w() < 1) + return -1; + return x() + w() - 1; + } + + /** Returns the maximum y-coordinate contained within this + rectangle. Note that this returns a different result than Java + 2D's rectangles; for a rectangle of position (0, 0) and size (1, + 1) this will return 0, not 1. Returns -1 if the height of this + rectangle is 0. */ + public int maxY() { + if (h() < 1) + return -1; + return y() + h() - 1; + } + + public boolean canContain(Rect other) { + return (w() >= other.w() && + h() >= other.h()); + } + + public String toString() { + return "[Rect x: " + x() + " y: " + y() + " w: " + w() + " h: " + h() + "]"; + } + + // Unclear whether it's a good idea to override hashCode and equals + // for these objects + /* + public boolean equals(Object other) { + if (other == null || (!(other instanceof Rect))) { + return false; + } + + Rect r = (Rect) other; + return (this.x() == r.x() && + this.y() == r.y() && + this.w() == r.w() && + this.h() == r.h()); + } + + public int hashCode() { + return (x + y * 13 + w * 17 + h * 23); + } + */ +} diff --git a/src/classes/com/sun/opengl/impl/awt/packrect/RectVisitor.java b/src/classes/com/sun/opengl/impl/awt/packrect/RectVisitor.java new file mode 100755 index 000000000..9fd253d43 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/awt/packrect/RectVisitor.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.sun.opengl.impl.awt.packrect; + +/** Iteration construct without exposing the internals of the + RectanglePacker and without implementing a complex Iterator. */ + +public interface RectVisitor { + public void visit(Rect rect); +} diff --git a/src/classes/com/sun/opengl/impl/awt/packrect/RectanglePacker.java b/src/classes/com/sun/opengl/impl/awt/packrect/RectanglePacker.java new file mode 100755 index 000000000..f795fe00a --- /dev/null +++ b/src/classes/com/sun/opengl/impl/awt/packrect/RectanglePacker.java @@ -0,0 +1,295 @@ +/* + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.sun.opengl.impl.awt.packrect; + +import java.util.*; + +/** Packs rectangles supplied by the user (typically representing + image regions) into a larger backing store rectangle (typically + representing a large texture). Supports automatic compaction of + the space on the backing store, and automatic expansion of the + backing store, when necessary. */ + +public class RectanglePacker { + private BackingStoreManager manager; + private Object backingStore; + private LevelSet levels; + private float EXPANSION_FACTOR = 0.5f; + private float SHRINK_FACTOR = 0.3f; + + private int initialWidth; + private int initialHeight; + + private int maxWidth = -1; + private int maxHeight = -1; + + static class RectHComparator implements Comparator { + public int compare(Object o1, Object o2) { + Rect r1 = (Rect) o1; + Rect r2 = (Rect) o2; + return r2.h() - r1.h(); + } + + public boolean equals(Object obj) { + return this == obj; + } + } + private static final Comparator rectHComparator = new RectHComparator(); + + public RectanglePacker(BackingStoreManager manager, + int initialWidth, + int initialHeight) { + this.manager = manager; + levels = new LevelSet(initialWidth, initialHeight); + this.initialWidth = initialWidth; + this.initialHeight = initialHeight; + } + + public Object getBackingStore() { + if (backingStore == null) { + backingStore = manager.allocateBackingStore(levels.w(), levels.h()); + } + + return backingStore; + } + + /** Sets up a maximum width and height for the backing store. These + are optional and if not specified the backing store will grow as + necessary. Setting up a maximum width and height introduces the + possibility that additions will fail; these are handled with the + BackingStoreManager's allocationFailed notification. */ + public void setMaxSize(int maxWidth, int maxHeight) { + this.maxWidth = maxWidth; + this.maxHeight = maxHeight; + } + + /** Decides upon an (x, y) position for the given rectangle (leaving + its width and height unchanged) and places it on the backing + store. May provoke re-layout of other Rects already added. */ + public void add(Rect rect) { + // Allocate backing store if we don't have any yet + if (backingStore == null) + backingStore = manager.allocateBackingStore(levels.w(), levels.h()); + + int attemptNumber = 0; + boolean tryAgain = false; + + do { + // Try to allocate + if (levels.add(rect)) + return; + + // Try to allocate with horizontal compaction + if (levels.compactAndAdd(rect, backingStore, manager)) + return; + + // Let the manager have a chance at potentially evicting some entries + tryAgain = manager.preExpand(rect, attemptNumber++); + } while (tryAgain); + + compactImpl(rect); + + // Retry the addition of the incoming rectangle + add(rect); + // Done + } + + /** Removes the given rectangle from this RectanglePacker. */ + public void remove(Rect rect) { + levels.remove(rect); + } + + /** Visits all Rects contained in this RectanglePacker. */ + public void visit(RectVisitor visitor) { + levels.visit(visitor); + } + + /** Returns the vertical fragmentation ratio of this + RectanglePacker. This is defined as the ratio of the sum of the + heights of all completely empty Levels divided by the overall + used height of the LevelSet. A high vertical fragmentation ratio + indicates that it may be profitable to perform a compaction. */ + public float verticalFragmentationRatio() { + return levels.verticalFragmentationRatio(); + } + + /** Forces a compaction cycle, which typically results in allocating + a new backing store and copying all entries to it. */ + public void compact() { + compactImpl(null); + } + + // The "cause" rect may be null + private void compactImpl(Rect cause) { + // Have to either expand, compact or both. Need to figure out what + // direction to go. Prefer to expand vertically. Expand + // horizontally only if rectangle being added is too wide. FIXME: + // may want to consider rebalancing the width and height to be + // more equal if it turns out we keep expanding in the vertical + // direction. + boolean done = false; + int newWidth = levels.w(); + int newHeight = levels.h(); + LevelSet nextLevelSet = null; + int attemptNumber = 0; + boolean needAdditionFailureNotification = false; + + while (!done) { + if (cause != null) { + if (cause.w() > newWidth) { + newWidth = cause.w(); + } else { + newHeight = (int) (newHeight * (1.0f + EXPANSION_FACTOR)); + } + } + + // Clamp to maximum values + needAdditionFailureNotification = false; + if (maxWidth > 0 && newWidth > maxWidth) { + newWidth = maxWidth; + needAdditionFailureNotification = true; + } + if (maxHeight > 0 && newHeight > maxHeight) { + newHeight = maxHeight; + needAdditionFailureNotification = true; + } + + nextLevelSet = new LevelSet(newWidth, newHeight); + + // Make copies of all existing rectangles + List/*<Rect>*/ newRects = new ArrayList/*<Rect>*/(); + for (Iterator i1 = levels.iterator(); i1.hasNext(); ) { + Level level = (Level) i1.next(); + for (Iterator i2 = level.iterator(); i2.hasNext(); ) { + Rect cur = (Rect) i2.next(); + Rect newRect = new Rect(0, 0, cur.w(), cur.h(), null); + cur.setNextLocation(newRect); + // Hook up the reverse mapping too for easier replacement + newRect.setNextLocation(cur); + newRects.add(newRect); + } + } + // Sort them by decreasing height (note: this isn't really + // guaranteed to improve the chances of a successful layout) + Collections.sort(newRects, rectHComparator); + // Try putting all of these rectangles into the new level set + done = true; + for (Iterator iter = newRects.iterator(); iter.hasNext(); ) { + if (!nextLevelSet.add((Rect) iter.next())) { + done = false; + break; + } + } + + if (done && cause != null) { + // Try to add the new rectangle as well + if (nextLevelSet.add(cause)) { + // We're OK + } else { + done = false; + } + } + + // Don't send addition failure notifications if we're only doing + // a compaction + if (!done && needAdditionFailureNotification && cause != null) { + manager.additionFailed(cause, attemptNumber); + } + ++attemptNumber; + } + + // See whether the implicit compaction that just occurred has + // yielded excess empty space. + if (nextLevelSet.getUsedHeight() > 0 && + nextLevelSet.getUsedHeight() < nextLevelSet.h() * SHRINK_FACTOR) { + int shrunkHeight = Math.max(initialHeight, + (int) (nextLevelSet.getUsedHeight() * (1.0f + EXPANSION_FACTOR))); + if (maxHeight > 0 && shrunkHeight > maxHeight) { + shrunkHeight = maxHeight; + } + nextLevelSet.setHeight(shrunkHeight); + } + + // If we temporarily added the new rectangle to the new LevelSet, + // take it out since we don't "really" add it here but in add(), above + if (cause != null) { + nextLevelSet.remove(cause); + } + + // OK, now we have a new layout and a mapping from the old to the + // new locations of rectangles on the backing store. Allocate a + // new backing store, move the contents over and deallocate the + // old one. + Object newBackingStore = manager.allocateBackingStore(nextLevelSet.w(), + nextLevelSet.h()); + manager.beginMovement(backingStore, newBackingStore); + for (Iterator i1 = levels.iterator(); i1.hasNext(); ) { + Level level = (Level) i1.next(); + for (Iterator i2 = level.iterator(); i2.hasNext(); ) { + Rect cur = (Rect) i2.next(); + manager.move(backingStore, cur, + newBackingStore, cur.getNextLocation()); + } + } + // Replace references to temporary rectangles with original ones + nextLevelSet.updateRectangleReferences(); + manager.endMovement(backingStore, newBackingStore); + // Now delete the old backing store + manager.deleteBackingStore(backingStore); + // Update to new versions of backing store and LevelSet + backingStore = newBackingStore; + levels = nextLevelSet; + } + + /** Clears all Rects contained in this RectanglePacker. */ + public void clear() { + levels.clear(); + } + + /** Disposes the backing store allocated by the + BackingStoreManager. This RectanglePacker may no longer be used + after calling this method. */ + public void dispose() { + if (backingStore != null) + manager.deleteBackingStore(backingStore); + backingStore = null; + levels = null; + } +} diff --git a/src/classes/com/sun/opengl/impl/awt/packrect/package.html b/src/classes/com/sun/opengl/impl/awt/packrect/package.html new file mode 100755 index 000000000..7f2522244 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/awt/packrect/package.html @@ -0,0 +1,7 @@ +This package implements a rectangle packing algorithm suitable for +tracking the placement of multiple rectangles inside a larger one. It +is useful for cases such as placing the contents of multiple windows +on a larger backing store texture for a compositing window manager; +placing multiple rasterized strings in a texture map for quick +rendering to the screen; and many other situations where it is useful +to carve up a larger texture into smaller pieces dynamically. <P> diff --git a/src/classes/com/sun/opengl/impl/glu/error/Error.java b/src/classes/com/sun/opengl/impl/glu/error/Error.java new file mode 100644 index 000000000..fd6a4e50e --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/error/Error.java @@ -0,0 +1,99 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 1.1 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.sun.opengl.impl.glu.error; + +import javax.media.opengl.GL; +import javax.media.opengl.glu.GLU; + +/** + * + * @author Administrator + */ +public class Error { + + private static String[] glErrorStrings = { + "invalid enumerant", + "invalid value", + "invalid operation", + "stack overflow", + "stack underflow", + "out of memory", + "invalid framebuffer operation" + }; + + private static String[] gluErrorStrings = { + "invalid enumerant", + "invalid value", + "out of memory", + "", + "invalid operation" + }; + + /** Creates a new instance of Error */ + public Error() { + } + + public static String gluErrorString( int errorCode ) { + if( errorCode == 0 ) { + return( "no error" ); + } + if( (errorCode >= GL.GL_INVALID_ENUM) && (errorCode <= GL.GL_INVALID_FRAMEBUFFER_OPERATION) ) { + return( glErrorStrings[ errorCode - GL.GL_INVALID_ENUM ] ); + } + if( errorCode == 0x8031 /* GL.GL_TABLE_TOO_LARGE */ ) { + return( "table too large" ); + } + if( (errorCode >= GLU.GLU_INVALID_ENUM) && (errorCode <= GLU.GLU_INVALID_OPERATION) ) { + return( gluErrorStrings[ errorCode - GLU.GLU_INVALID_ENUM ] ); + } +// if( (errorCode >= GLU.GLU_NURBS_ERROR1) && (errorCode <= GLU.GLU_NURBS_ERROR37) ) { +// return( gluErrorStrings[ errorCode - (GLU.GLU_NURBS_ERROR1 - 1) ] ); +// } + if( (errorCode >= GLU.GLU_TESS_ERROR1) && (errorCode <= GLU.GLU_TESS_ERROR8) ) { + return( gluErrorStrings[ errorCode - (GLU.GLU_TESS_ERROR1 - 1) ] ); + } + return( "error ("+errorCode+")" ); + } +} diff --git a/src/classes/com/sun/opengl/impl/glu/gl2/glue/Glue.java b/src/classes/com/sun/opengl/impl/glu/gl2/glue/Glue.java new file mode 100644 index 000000000..0037fd2f3 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/gl2/glue/Glue.java @@ -0,0 +1,114 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 1.1 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.sun.opengl.impl.glu.gl2.glue; + +/** + * + * @author Administrator + */ +public class Glue { + private static String[] __gluNurbsErrors = { + " ", + "spline order un-supported", + "too few knots", + "valid knot range is empty", + "decreasing knot sequence knot", + "knot multiplicity greater than order of spline", + "gluEndCurve() must follow gluBeginCurve()", + "gluBeginCurve() must precede gluEndCurve()", + "missing or extra geometric data", + "can't draw piecewise linear trimming curves", + "missing or extra domain data", + "missing or extra domain data", + "gluEndTrim() must precede gluEndSurface()", + "gluBeginSurface() must precede gluEndSurface()", + "curve of improper type passed as trim curve", + "gluBeginSurface() must precede gluBeginTrim()", + "gluEndTrim() must follow gluBeginTrim()", + "gluBeginTrim() must follow gluEndTrim()", + "invalid or missing trim curve", + "gluBeginTrim() must precede gluPwlCurve()", + "piecewise linear trimming curve referenced twice", + "piecewise linear trimming curve and nurbs curve mixed", + "improper usage of trim data type", + "nurbs curve referenced twice", + "nurbs curve and piecewise linear trimming curve mixed", + "nurbs surface referenced twice", + "invalid property", + "gluEndSurface() must follow gluBeginSurface()", + "intersecting or misoriented trim curve", + "intersecting trim curves", + "UNUSED", + "inconnected trim curves", + "unknown knot error", + "negative vertex count encountered", + "negative byte-stride encountered", + "unknown type descriptor", + "null control point reference", + "duplicate point on piecewise linear trimming curve" + } ; + + /** Creates a new instance of Glue */ + public Glue() { + } + + public static String __gluNURBSErrorString( int errno ) { + return( __gluNurbsErrors[ errno ] ); + } + + private static String[] __gluTessErrors = { + " ", + "gluTessBeginPolygon() must precede a gluTessEndPolygon", + "gluTessBeginContour() must precede a gluTessEndContour()", + "gluTessEndPolygon() must follow a gluTessBeginPolygon()", + "gluTessEndContour() must follow a gluTessBeginContour()", + "a coordinate is too large", + "need combine callback" + }; + + public static String __gluTessErrorString( int errno ) { + return( __gluTessErrors[ errno ] ); + } +} diff --git a/src/classes/com/sun/opengl/impl/glu/nurbs/Arc.java b/src/classes/com/sun/opengl/impl/glu/nurbs/Arc.java new file mode 100755 index 000000000..e96aa83f8 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/nurbs/Arc.java @@ -0,0 +1,258 @@ +package com.sun.opengl.impl.glu.nurbs; + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 1.1 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +*/ + +/** + * Trimming arc + * @author Tomas Hrasky + * + */ +public class Arc { + /** + * Corresponding picewise-linear arc + */ + public PwlArc pwlArc; + + /** + * Arc type + */ + private long type; + + /** + * Arc link in linked list + */ + public Arc link; + + /** + * Previous arc + */ + Arc prev; + + /** + * Next arc + */ + Arc next; + + /** + * Corresponding berizer type arc + */ + private BezierArc bezierArc; + + /** + * Makes new arc at specified side + * + * @param side + * which side doeas this arc form + */ + public Arc(int side) { + bezierArc = null; + pwlArc = null; + type = 0; + setside(side); + // nuid=_nuid + } + + /** + * Sets side the arc is at + * + * @param side + * arc side + */ + private void setside(int side) { + // DONE + clearside(); + type |= side << 8; + } + + /** + * Unsets side + */ + private void clearside() { + // DONE + type &= ~(0x7 << 8); + } + + // this one replaces enum arc_side + /** + * Side not specified + */ + public static final int ARC_NONE = 0; + + /** + * Arc on right + */ + public static final int ARC_RIGHT = 1; + + /** + * Arc on top + */ + public static final int ARC_TOP = 2; + + /** + * Arc on left + */ + public static final int ARC_LEFT = 3; + + /** + * Arc on bottom + */ + public static final int ARC_BOTTOM = 4; + + /** + * Bezier type flag + */ + private static final long BEZIER_TAG = 1 << 13; + + /** + * Arc type flag + */ + private static final long ARC_TAG = 1 << 3; + + /** + * Tail type tag + */ + private static final long TAIL_TAG = 1 << 6; + + /** + * Appends arc to the list + * + * @param jarc + * arc to be append + * @return this + */ + public Arc append(Arc jarc) { + // DONE + if (jarc != null) { + next = jarc.next; + prev = jarc; + next.prev = this; + prev.next = this; + } else { + next = this; + prev = this; + } + + return this; + } + + /** + * Unused + * + * @return true + */ + public boolean check() { + return true; + } + + /** + * Sets bezier type flag + */ + public void setbezier() { + // DONE + type |= BEZIER_TAG; + + } + + /** + * Returns tail of linked list coords + * + * @return tail coords + */ + public float[] tail() { + // DONE + return pwlArc.pts[0].param; + } + + /** + * Returns head of linked list coords + * + * @return head coords + */ + public float[] head() { + // DONE + return next.pwlArc.pts[0].param; + } + + /** + * Returns whether arc is marked with arc_tag + * + * @return is arc marked with arc_tag + */ + public boolean ismarked() { + // DONE + return ((type & ARC_TAG) > 0) ? true : false; + } + + /** + * Cleans arc_tag flag + */ + public void clearmark() { + // DONE + type &= (~ARC_TAG); + } + + /** + * Sets arc_tag flag + */ + public void setmark() { + // DONE + type |= ARC_TAG; + } + + /** + * sets tail tag + */ + public void setitail() { + // DONE + type |= TAIL_TAG; + } + + /** + * Returns whether arc is marked tail + * + * @return is tail + */ + public boolean getitail() { + return false; + } + + /** + * Unsets tail tag + */ + public void clearitail() { + // DONE + type &= (~TAIL_TAG); + } +} diff --git a/src/classes/com/sun/opengl/impl/glu/nurbs/ArcSdirSorter.java b/src/classes/com/sun/opengl/impl/glu/nurbs/ArcSdirSorter.java new file mode 100755 index 000000000..f8fbe2930 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/nurbs/ArcSdirSorter.java @@ -0,0 +1,63 @@ +package com.sun.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 1.1 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class for sorting list of Arcs + * @author Tomas Hrasky + * + */ +public class ArcSdirSorter { + + /** + * Makes new ArcSdirSorter with Subdivider + * @param subdivider subdivider + */ + public ArcSdirSorter(Subdivider subdivider) { + //TODO + // System.out.println("TODO arcsdirsorter.constructor"); + } + + /** + * Sorts list of arcs + * @param list arc list to be sorted + * @param count size of list + */ + public void qsort(CArrayOfArcs list, int count) { + // TODO + // System.out.println("TODO arcsdirsorter.qsort"); + } + +} diff --git a/src/classes/com/sun/opengl/impl/glu/nurbs/ArcTdirSorter.java b/src/classes/com/sun/opengl/impl/glu/nurbs/ArcTdirSorter.java new file mode 100755 index 000000000..9e9a10b42 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/nurbs/ArcTdirSorter.java @@ -0,0 +1,60 @@ +package com.sun.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 1.1 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class for sorting list of Arcs + * @author Tomas Hrasky + * + */ +public class ArcTdirSorter { + /** + * Makes new ArcSdirSorter with Subdivider + * @param subdivider subdivider + */ + public ArcTdirSorter(Subdivider subdivider) { + // TODO Auto-generated constructor stub + // System.out.println("TODO arcTsorter.konstruktor"); + } + /** + * Sorts list of arcs + * @param list arc list to be sorted + * @param count size of list + */ + public void qsort(CArrayOfArcs list, int count) { + // TODO Auto-generated method stub + // System.out.println("TODO arcTsorter.qsort"); + } +} diff --git a/src/classes/com/sun/opengl/impl/glu/nurbs/ArcTesselator.java b/src/classes/com/sun/opengl/impl/glu/nurbs/ArcTesselator.java new file mode 100755 index 000000000..496e8b7d6 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/nurbs/ArcTesselator.java @@ -0,0 +1,90 @@ +package com.sun.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 1.1 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class for arc tesselation + * @author Tomas Hrasky + * + */ +public class ArcTesselator { + + /** + * Makes given arc an bezier arc + * @param arc arc to work with + * @param s1 minimum s param + * @param s2 maximum s param + * @param t1 minimum t param + * @param t2 maximum s param + */ + public void bezier(Arc arc, float s1, float s2, float t1, float t2) { + // DONE + TrimVertex[] p = new TrimVertex[2]; + p[0] = new TrimVertex(); + p[1] = new TrimVertex(); + arc.pwlArc = new PwlArc(2, p); + p[0].param[0] = s1; + p[0].param[1] = s2; + p[1].param[0] = t1; + p[1].param[1] = t2; + arc.setbezier(); + } + + /** + * Empty method + * @param newright arc to work with + * @param s first tail + * @param t2 second tail + * @param t1 third tail + * @param f stepsize + */ + public void pwl_right(Arc newright, float s, float t1, float t2, float f) { + // TODO Auto-generated method stub + // System.out.println("TODO arctesselator.pwl_right"); + } + + /** + * Empty method + * @param newright arc to work with + * @param s first tail + * @param t2 second tail + * @param t1 third tail + * @param f stepsize + */ + public void pwl_left(Arc newright, float s, float t2, float t1, float f) { + // TODO Auto-generated method stub + // System.out.println("TODO arctesselator.pwl_left"); + } +} diff --git a/src/classes/com/sun/opengl/impl/glu/nurbs/Backend.java b/src/classes/com/sun/opengl/impl/glu/nurbs/Backend.java new file mode 100755 index 000000000..9467104f5 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/nurbs/Backend.java @@ -0,0 +1,217 @@ +package com.sun.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 1.1 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class responsible for rendering + * @author Tomas Hrasky + * + */ +public abstract class Backend { + + /** + * Fill surface + */ + public static final int N_MESHFILL = 0; + + /** + * Draw surface as wire model + */ + public static final int N_MESHLINE = 1; + + /** + * Draw surface with points + */ + public static final int N_MESHPOINT = 2; + + /** + * Object rendering curves + */ + protected CurveEvaluator curveEvaluator; + + /** + * Object rendering surfaces + */ + protected SurfaceEvaluator surfaceEvaluator; + + /** + * Makes new backend + */ + public Backend() { + // curveEvaluator = new OpenGLCurveEvaluator(); + // surfaceEvaluator = new OpenGLSurfaceEvaluator(); + } + + /** + * Begin a curve + */ + public void bgncurv() { + // DONE + curveEvaluator.bgnmap1f(); + + } + + /** + * End a curve + */ + public void endcurv() { + // DONE + curveEvaluator.endmap1f(); + + } + + /** + * Make cuve with given parameters + * @param type curve type + * @param ps control points + * @param stride control points coordinates number + * @param order order of curve + * @param ulo smallest u + * @param uhi highest u + */ + public void curvpts(int type, CArrayOfFloats ps, int stride, int order, + float ulo, float uhi) { + // DONE + curveEvaluator.map1f(type, ulo, uhi, stride, order, ps); + curveEvaluator.enable(type); + } + + /** + * Draw curve + * @param u1 smallest u + * @param u2 highest u + * @param nu number of pieces + */ + public void curvgrid(float u1, float u2, int nu) { + // DONE + curveEvaluator.mapgrid1f(nu, u1, u2); + + } + + /** + * Evaluates curve mesh + * @param from low param + * @param n step + */ + public void curvmesh(int from, int n) { + // DONE + curveEvaluator.mapmesh1f(N_MESHFILL, from, from + n); + } + + /** + * Begin surface + * @param wiretris use triangles + * @param wirequads use quads + */ + public void bgnsurf(int wiretris, int wirequads) { + // DONE + surfaceEvaluator.bgnmap2f(); + + if (wiretris > 0) + surfaceEvaluator.polymode(NurbsConsts.N_MESHLINE); + else + surfaceEvaluator.polymode(NurbsConsts.N_MESHFILL); + } + + /** + * End surface + */ + public void endsurf() { + // DONE + surfaceEvaluator.endmap2f(); + } + + /** + * Empty method + * @param ulo low u param + * @param uhi hig u param + * @param vlo low v param + * @param vhi high v param + */ + public void patch(float ulo, float uhi, float vlo, float vhi) { + // DONE + surfaceEvaluator.domain2f(ulo, uhi, vlo, vhi); + } + + /** + * Draw surface + * @param u0 lowest u + * @param u1 highest u + * @param nu number of pieces in u direction + * @param v0 lowest v + * @param v1 highest v + * @param nv number of pieces in v direction + */ + public void surfgrid(float u0, float u1, int nu, float v0, float v1, int nv) { + // DONE + surfaceEvaluator.mapgrid2f(nu, u0, u1, nv, v0, v1); + + } + + /** + * Evaluates surface mesh + * @param u u param + * @param v v param + * @param n step in u direction + * @param m step in v direction + */ + public void surfmesh(int u, int v, int n, int m) { + // System.out.println("TODO backend.surfmesh wireframequads"); + // TODO wireframequads + surfaceEvaluator.mapmesh2f(NurbsConsts.N_MESHFILL, u, u + n, v, v + m); + } + + /** + * Make surface + * @param type surface type + * @param pts control points + * @param ustride control points coordinates in u direction + * @param vstride control points coordinates in v direction + * @param uorder surface order in u direction + * @param vorder surface order in v direction + * @param ulo lowest u + * @param uhi hightest u + * @param vlo lowest v + * @param vhi hightest v + */ + public void surfpts(int type, CArrayOfFloats pts, int ustride, int vstride, + int uorder, int vorder, float ulo, float uhi, float vlo, float vhi) { + // DONE + surfaceEvaluator.map2f(type, ulo, uhi, ustride, uorder, vlo, vhi, + vstride, vorder, pts); + surfaceEvaluator.enable(type); + + } +} diff --git a/src/classes/com/sun/opengl/impl/glu/nurbs/BezierArc.java b/src/classes/com/sun/opengl/impl/glu/nurbs/BezierArc.java new file mode 100755 index 000000000..ef4cf0684 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/nurbs/BezierArc.java @@ -0,0 +1,44 @@ +package com.sun.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 1.1 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Empty class + * @author Tomas Hrasky + * + */ +public class BezierArc { + +} diff --git a/src/classes/com/sun/opengl/impl/glu/nurbs/Bin.java b/src/classes/com/sun/opengl/impl/glu/nurbs/Bin.java new file mode 100755 index 000000000..0f0806d96 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/nurbs/Bin.java @@ -0,0 +1,155 @@ +package com.sun.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 1.1 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class holding trimming arcs + * @author Tomas Hrasky + * + */ +public class Bin { + + /** + * Head of linked list of arcs + */ + private Arc head; + + /** + * Current arc + */ + private Arc current; + + /** + * Indicates whether there are any Arcs in linked list + * @return true if there are any Arcs in linked list + */ + public boolean isnonempty() { + // DONE + return this.head != null ? true : false; + } + + /** + * Adds and arc to linked list + * @param jarc added arc + */ + public void addarc(Arc jarc) { + // DONE + // if (head == null) + // head = jarc; + // else { + jarc.link = head; + head = jarc; + // } + + } + + /** + * Returns number of arcs in linked list + * @return number of arcs + */ + public int numarcs() { + // DONE + int count = 0; + for (Arc jarc = firstarc(); jarc != null; jarc = nextarc()) + count++; + return count; + } + + /** + * Removes first arc in list + * @return new linked list head + */ + public Arc removearc() { + // DONE + Arc jarc = head; + if (jarc != null) + head = jarc.link; + return jarc; + + } + + /** + * Consolidates linked list + */ + public void adopt() { + // DONE + markall(); + + Arc orphan; + while ((orphan = removearc()) != null) { + for (Arc parent = orphan.next; !parent.equals(orphan); parent = parent.next) { + if (!parent.ismarked()) { + orphan.link = parent.link; + parent.link = orphan; + orphan.clearmark(); + break; + } + } + } + + } + + /** + * Marks all arc in linked list + */ + private void markall() { + // DONE + for (Arc jarc = firstarc(); jarc != null; jarc = nextarc()) + jarc.setmark(); + } + + /** + * Returns first arc in linked list + * @return first arc in linked list + */ + private Arc firstarc() { + // DONE + current = head; + return nextarc(); + } + + /** + * Returns next arc in linked list + * @return next arc + * + */ + private Arc nextarc() { + // DONE + Arc jarc = current; + if (jarc != null) + current = jarc.link; + return jarc; + } +} diff --git a/src/classes/com/sun/opengl/impl/glu/nurbs/Breakpt.java b/src/classes/com/sun/opengl/impl/glu/nurbs/Breakpt.java new file mode 100755 index 000000000..9cccc5102 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/nurbs/Breakpt.java @@ -0,0 +1,59 @@ +package com.sun.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 1.1 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class holding break point parameters + * + * @author Tomas Hrasky + * + */ +public class Breakpt { + + /** + * Breakpoint multiplicity + */ + public int multi; + + /** + * Breakpint value + */ + public float value; + + /** + * Breakpoint deficit (how many times it has to be added) + */ + public int def; +} diff --git a/src/classes/com/sun/opengl/impl/glu/nurbs/CArrayOfArcs.java b/src/classes/com/sun/opengl/impl/glu/nurbs/CArrayOfArcs.java new file mode 100755 index 000000000..3d6e1d47f --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/nurbs/CArrayOfArcs.java @@ -0,0 +1,194 @@ +package com.sun.opengl.impl.glu.nurbs; + +/** + * Class replacing C language pointer + * + * @author Tomas Hrasky + * + */ +public class CArrayOfArcs { + /** + * Underlaying array + */ + private Arc[] array; + + /** + * Pointer to array member + */ + private int pointer; + + /** + * Don't check for array borders? + */ + private boolean noCheck = true; + + /** + * Makes new CArray + * + * @param array + * underlaying array + * @param pointer + * pointer (index) to array + */ + public CArrayOfArcs(Arc[] array, int pointer) { + this.array = array; + // this.pointer=pointer; + setPointer(pointer); + } + + /** + * Makes new CArray from other CArray + * + * @param carray + * reference array + */ + public CArrayOfArcs(CArrayOfArcs carray) { + this.array = carray.array; + // this.pointer=carray.pointer; + setPointer(carray.pointer); + } + + /** + * Makes new CArray with pointer set to 0 + * + * @param ctlarray + * underlaying array + */ + public CArrayOfArcs(Arc[] ctlarray) { + this.array = ctlarray; + this.pointer = 0; + } + + /** + * Returns element at pointer + * + * @return element at pointer + */ + public Arc get() { + return array[pointer]; + } + + /** + * Increases pointer by one (++) + */ + public void pp() { + // pointer++; + setPointer(pointer + 1); + } + + /** + * Sets element at pointer + * + * @param f + * desired value + */ + public void set(Arc f) { + array[pointer] = f; + + } + + /** + * Returns array element at specified index + * + * @param i + * array index + * @return element at index + */ + public Arc get(int i) { + return array[i]; + } + + /** + * Returns array element at specified index relatively to pointer + * + * @param i + * relative index + * @return element at relative index + */ + public Arc getRelative(int i) { + return array[pointer + i]; + } + + /** + * Sets value of element at specified index relatively to pointer + * + * @param i + * relative index + * @param value + * value to be set + */ + public void setRelative(int i, Arc value) { + array[pointer + i] = value; + } + + /** + * Lessens pointer by value + * + * @param i + * lessen by + */ + public void lessenPointerBy(int i) { + // pointer-=i; + setPointer(pointer - i); + } + + /** + * Returns pointer value + * + * @return pointer value + */ + public int getPointer() { + return pointer; + } + + /** + * Sets ponter value + * + * @param pointer + * pointer value to be set + */ + public void setPointer(int pointer) { + if (!noCheck && pointer > array.length) + throw new IllegalArgumentException("Pointer " + pointer + + " out of bounds " + array.length); + this.pointer = pointer; + } + + /** + * Raises pointer by value + * + * @param i + * raise by + */ + public void raisePointerBy(int i) { + // pointer+=i; + setPointer(pointer + i); + } + + /** + * Lessens ponter by one (--) + */ + public void mm() { + // pointer--; + setPointer(pointer - 1); + } + + /** + * Returns underlaying array + * + * @return underlaying array + */ + public Arc[] getArray() { + return array; + } + + /** + * Sets underlaying array + * + * @param array + * underlaying array + */ + public void setArray(Arc[] array) { + this.array = array; + } +} diff --git a/src/classes/com/sun/opengl/impl/glu/nurbs/CArrayOfBreakpts.java b/src/classes/com/sun/opengl/impl/glu/nurbs/CArrayOfBreakpts.java new file mode 100755 index 000000000..f5932d954 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/nurbs/CArrayOfBreakpts.java @@ -0,0 +1,130 @@ +package com.sun.opengl.impl.glu.nurbs; + +/** + * Class replacing C language pointer + * + * @author Tomas Hrasky + * + */ +public class CArrayOfBreakpts { + /** + * Underlaying array + */ + private Breakpt[] pole; + + /** + * Pointer to array member + */ + private int pointer; + + /** + * Makes new CArray + * + * @param array + * underlaying array + * @param pointer + * pointer (index) to array + */ + public CArrayOfBreakpts(Breakpt[] array, int pointer) { + this.pole = array; + this.pointer = pointer; + } + + /** + * Makes new CArray from other CArray + * + * @param carray + * reference array + */ + public CArrayOfBreakpts(CArrayOfBreakpts carray) { + this.pole = carray.pole; + this.pointer = carray.pointer; + } + + /** + * Returns element at pointer + * + * @return element at pointer + */ + public Breakpt get() { + return pole[pointer]; + } + + /** + * Increases pointer by one (++) + */ + public void pp() { + pointer++; + } + + /** + * Sets element at pointer + * + * @param f + * desired value + */ + public void set(Breakpt f) { + pole[pointer] = f; + + } + + /** + * Returns array element at specified index + * + * @param i + * array index + * @return element at index + */ + public Breakpt get(int i) { + return pole[i]; + } + + /** + * Lessens pointer by value + * + * @param i + * lessen by + */ + public void lessenPointerBy(int i) { + pointer -= i; + + } + + /** + * Returns pointer value + * + * @return pointer value + */ + public int getPointer() { + return pointer; + } + + /** + * Sets ponter value + * + * @param pointer + * pointer value to be set + */ + public void setPointer(int pointer) { + this.pointer = pointer; + } + + /** + * Raises pointer by value + * + * @param i + * raise by + */ + public void raisePointerBy(int i) { + pointer += i; + + } + + /** + * Lessens ponter by one (--) + */ + public void mm() { + pointer--; + + } +} diff --git a/src/classes/com/sun/opengl/impl/glu/nurbs/CArrayOfFloats.java b/src/classes/com/sun/opengl/impl/glu/nurbs/CArrayOfFloats.java new file mode 100755 index 000000000..fb3fac69b --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/nurbs/CArrayOfFloats.java @@ -0,0 +1,195 @@ +package com.sun.opengl.impl.glu.nurbs; + +/** + * Class replacing C language pointer + * + * @author Tomas Hrasky + * + */ +public class CArrayOfFloats { + + /** + * Underlaying array + */ + private float[] array; + + /** + * Pointer to array member + */ + private int pointer; + + /** + * Don't check for array borders? + */ + private boolean noCheck = true; + + /** + * Makes new CArray + * + * @param array + * underlaying array + * @param pointer + * pointer (index) to array + */ + public CArrayOfFloats(float[] array, int pointer) { + this.array = array; + // this.pointer=pointer; + setPointer(pointer); + } + + /** + * Makes new CArray from other CArray + * + * @param carray + * reference array + */ + public CArrayOfFloats(CArrayOfFloats carray) { + this.array = carray.array; + // this.pointer=carray.pointer; + setPointer(carray.pointer); + } + + /** + * Makes new CArray with pointer set to 0 + * + * @param ctlarray + * underlaying array + */ + public CArrayOfFloats(float[] ctlarray) { + this.array = ctlarray; + this.pointer = 0; + } + + /** + * Returns element at pointer + * + * @return element at pointer + */ + public float get() { + return array[pointer]; + } + + /** + * Increases pointer by one (++) + */ + public void pp() { + // pointer++; + setPointer(pointer + 1); + } + + /** + * Sets element at pointer + * + * @param f + * desired value + */ + public void set(float f) { + array[pointer] = f; + + } + + /** + * Returns array element at specified index + * + * @param i + * array index + * @return element at index + */ + public float get(int i) { + return array[i]; + } + + /** + * Returns array element at specified index relatively to pointer + * + * @param i + * relative index + * @return element at relative index + */ + public float getRelative(int i) { + return array[pointer + i]; + } + + /** + * Sets value of element at specified index relatively to pointer + * + * @param i + * relative index + * @param value + * value to be set + */ + public void setRelative(int i, float value) { + array[pointer + i] = value; + } + + /** + * Lessens pointer by value + * + * @param i + * lessen by + */ + public void lessenPointerBy(int i) { + // pointer-=i; + setPointer(pointer - i); + } + + /** + * Returns pointer value + * + * @return pointer value + */ + public int getPointer() { + return pointer; + } + + /** + * Sets ponter value + * + * @param pointer + * pointer value to be set + */ + public void setPointer(int pointer) { + if (!noCheck && pointer > array.length) + throw new IllegalArgumentException("Pointer " + pointer + + " out of bounds " + array.length); + this.pointer = pointer; + } + + /** + * Raises pointer by value + * + * @param i + * raise by + */ + public void raisePointerBy(int i) { + // pointer+=i; + setPointer(pointer + i); + } + + /** + * Lessens ponter by one (--) + */ + public void mm() { + // pointer--; + setPointer(pointer - 1); + } + + /** + * Returns underlaying array + * + * @return underlaying array + */ + public float[] getArray() { + return array; + } + + /** + * Sets underlaying array + * + * @param array + * underlaying array + */ + public void setArray(float[] array) { + this.array = array; + } +} diff --git a/src/classes/com/sun/opengl/impl/glu/nurbs/CArrayOfQuiltspecs.java b/src/classes/com/sun/opengl/impl/glu/nurbs/CArrayOfQuiltspecs.java new file mode 100755 index 000000000..fed301895 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/nurbs/CArrayOfQuiltspecs.java @@ -0,0 +1,160 @@ +package com.sun.opengl.impl.glu.nurbs; + +/** + * Class replacing C language pointer + * + * @author Tomas Hrasky + * + */ +public class CArrayOfQuiltspecs { + /** + * Underlaying array + */ + private Quiltspec[] array; + + /** + * Pointer to array member + */ + private int pointer; + + /** + * Makes new CArray + * + * @param array + * underlaying array + * @param pointer + * pointer (index) to array + */ + public CArrayOfQuiltspecs(Quiltspec[] array, int pointer) { + this.array = array; + this.pointer = pointer; + } + + /** + * Makes new CArray from other CArray + * + * @param carray + * reference array + */ + public CArrayOfQuiltspecs(CArrayOfQuiltspecs carray) { + this.array = carray.array; + this.pointer = carray.pointer; + } + + /** + * Makes new CArray with pointer set to 0 + * + * @param array + * underlaying array + */ + public CArrayOfQuiltspecs(Quiltspec[] array) { + this.array = array; + this.pointer = 0; + } + + /** + * Returns element at pointer + * + * @return element at pointer + */ + public Quiltspec get() { + return array[pointer]; + } + + /** + * Increases pointer by one (++) + */ + public void pp() { + pointer++; + } + + /** + * Sets element at pointer + * + * @param f + * desired value + */ + public void set(Quiltspec f) { + array[pointer] = f; + + } + + /** + * Returns array element at specified index + * + * @param i + * array index + * @return element at index + */ + public Quiltspec get(int i) { + return array[i]; + } + + /** + * Lessens pointer by value + * + * @param i + * lessen by + */ + public void lessenPointerBy(int i) { + pointer -= i; + + } + + /** + * Returns pointer value + * + * @return pointer value + */ + public int getPointer() { + return pointer; + } + + /** + * Sets ponter value + * + * @param pointer + * pointer value to be set + */ + public void setPointer(int pointer) { + this.pointer = pointer; + } + + /** + * Raises pointer by value + * + * @param i + * raise by + */ + public void raisePointerBy(int i) { + pointer += i; + + } + + /** + * Lessens ponter by one (--) + */ + public void mm() { + pointer--; + + } + + /** + * Returns underlaying array + * + * @return underlaying array + */ + public Quiltspec[] getArray() { + return array; + } + + /** + * Sets underlaying array + * + * @param array + * underlaying array + */ + public void setArray(Quiltspec[] array) { + this.array = array; + } +} diff --git a/src/classes/com/sun/opengl/impl/glu/nurbs/Curve.java b/src/classes/com/sun/opengl/impl/glu/nurbs/Curve.java new file mode 100755 index 000000000..318c8416c --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/nurbs/Curve.java @@ -0,0 +1,238 @@ +package com.sun.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 1.1 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class holding curve definition + * @author Tomáš Hráský + * + */ +public class Curve { + + /** + * Maximum coordinates per control point + */ + private static final int MAXCOORDS = 5; + + /** + * Max curve order + */ + private static final int MAXORDER = 24; + + /** + * Next curve in linked list + */ + public Curve next; + + /** + * OpenGL maps + */ + private Mapdesc mapdesc; + + /** + * Does the curve need sampling + */ + private boolean needsSampling; + + /** + * Culling + */ + private int cullval; + + /** + * Number of coords + */ + private int stride; + + /** + * Curve order + */ + private int order; + + /** + * Holds conversion range borders + */ + private float[] range; + + /** + * Subdivision stepsize + */ + public float stepsize; + + /** + * Minimal subdivision stepsize + */ + private float minstepsize; + + /** + * Sampling points + */ + float[] spts; + + /** + * Makes new Curve + * + * @param geo + * @param pta + * @param ptb + * @param c + * next curve in linked list + */ + public Curve(Quilt geo, float[] pta, float[] ptb, Curve c) { + + spts = new float[MAXORDER * MAXCOORDS]; + + mapdesc = geo.mapdesc; + + next = c; + needsSampling = mapdesc.isRangeSampling() ? true : false; + + cullval = mapdesc.isCulling() ? Subdivider.CULL_ACCEPT + : Subdivider.CULL_TRIVIAL_REJECT; + order = geo.qspec.get(0).order; + stride = MAXCOORDS; + + // CArrayOfFloats ps = geo.cpts; + CArrayOfFloats ps = new CArrayOfFloats(geo.cpts.getArray(), 0); + CArrayOfQuiltspecs qs = geo.qspec; + ps.raisePointerBy(qs.get().offset); + ps.raisePointerBy(qs.get().index * qs.get().order * qs.get().stride); + + if (needsSampling) { + mapdesc.xformSampling(ps, qs.get().order, qs.get().stride, spts, + stride); + } + if (cullval == Subdivider.CULL_ACCEPT) { + // System.out.println("TODO curve.Curve-cullval"); + // mapdesc.xformCulling(ps,qs.get().order,qs.get().stride,cpts,stride); + } + + range = new float[3]; + range[0] = qs.get().breakpoints[qs.get().index]; + range[1] = qs.get().breakpoints[qs.get().index + 1]; + range[2] = range[1] - range[0]; + // TODO it is necessary to solve problem with "this" pointer here + if (range[0] != pta[0]) { + // System.out.println("TODO curve.Curve-range0"); + // Curve lower=new Curve(this,pta,0); + // lower.next=next; + // this=lower; + } + if (range[1] != ptb[0]) { + // System.out.println("TODO curve.Curve-range1"); + // Curve lower=new Curve(this,ptb,0); + } + } + + /** + * Checks culling type + * @return Subdivider.CULL_ACCEPT + */ + public int cullCheck() { + if (cullval == Subdivider.CULL_ACCEPT) { + // System.out.println("TODO curve.cullval"); + // cullval=mapdesc.cullCheck(cpts,order,stride); + } + // TODO compute cullval and return the computed value + // return cullval; + return Subdivider.CULL_ACCEPT; + } + + /** + * Computes subdivision step size + */ + public void getStepSize() { + minstepsize = 0; + if (mapdesc.isConstantSampling()) { + setstepsize(mapdesc.maxrate); + } else if (mapdesc.isDomainSampling()) { + setstepsize(mapdesc.maxrate * range[2]); + } else { + assert (order <= MAXORDER); + + float tmp[][] = new float[MAXORDER][MAXCOORDS]; + + int tstride = (MAXORDER); + + int val = 0; + // mapdesc.project(spts,stride,tmp,tstride,order); + + // System.out.println("TODO curve.getsptepsize mapdesc.project"); + + if (val == 0) { + setstepsize(mapdesc.maxrate); + } else { + float t = mapdesc.getProperty(NurbsConsts.N_PIXEL_TOLERANCE); + if (mapdesc.isParametricDistanceSampling()) { + // System.out.println("TODO curve.getstepsize - parametric"); + } else if (mapdesc.isPathLengthSampling()) { + // System.out.println("TODO curve.getstepsize - pathlength"); + } else { + setstepsize(mapdesc.maxrate); + } + } + + } + + } + + /** + * Sets maximum subdivision step size + * @param max maximum subdivision step size + */ + private void setstepsize(float max) { + // DONE + stepsize = (max >= 1) ? (range[2] / max) : range[2]; + minstepsize = stepsize; + } + + /** + * Clamps the curve + */ + public void clamp() { + // DONE + if (stepsize < minstepsize) + stepsize = mapdesc.clampfactor * minstepsize; + } + + /** + * Tells whether curve needs subdivision + * + * @return curve needs subdivison + */ + public boolean needsSamplingSubdivision() { + return (stepsize < minstepsize); + } +} diff --git a/src/classes/com/sun/opengl/impl/glu/nurbs/CurveEvaluator.java b/src/classes/com/sun/opengl/impl/glu/nurbs/CurveEvaluator.java new file mode 100755 index 000000000..a6393ddf4 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/nurbs/CurveEvaluator.java @@ -0,0 +1,86 @@ +package com.sun.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 1.1 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class rendering curves with OpenGL + * @author Tomáš Hráský + * + */ +public interface CurveEvaluator { + /** + * Pushes eval bit + */ + public void bgnmap1f(); + + /** + * Pops all OpenGL attributes + */ + public void endmap1f() ; + + /** + * Initializes opengl evaluator + * @param type curve type + * @param ulo lowest u + * @param uhi highest u + * @param stride control point coords + * @param order curve order + * @param ps control points + */ + public void map1f(int type, float ulo, float uhi, int stride, int order, + CArrayOfFloats ps) ; + + /** + * Calls opengl enable + * @param type what to enable + */ + public void enable(int type) ; + + /** + * Calls glMapGrid1f + * @param nu steps + * @param u1 low u + * @param u2 high u + */ + public void mapgrid1f(int nu, float u1, float u2) ; + + /** + * Evaluates a curve using glEvalMesh1f + * @param style Backend.N_MESHFILL/N_MESHLINE/N_MESHPOINT + * @param from lowest param + * @param to highest param + */ + public void mapmesh1f(int style, int from, int to) ; +} diff --git a/src/classes/com/sun/opengl/impl/glu/nurbs/Curvelist.java b/src/classes/com/sun/opengl/impl/glu/nurbs/Curvelist.java new file mode 100755 index 000000000..fdce39b46 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/nurbs/Curvelist.java @@ -0,0 +1,121 @@ +package com.sun.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 1.1 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class for woking with linked list of curves + * @author Tomas Hrasky + * + */ +public class Curvelist { + + /** + * Head of linked list + */ + private Curve curve; + + /** + * Holds conversion range borders + */ + float[] range; + + /** + * Subdivision step size + */ + public float stepsize; + + /** + * Do curves need subdivision? + */ + private boolean needsSubdivision; + + /** + * Makes new instance on top of specified lis of Quilts + * @param qlist underlaying list of quilts + * @param pta range start + * @param ptb range end + */ + public Curvelist(Quilt qlist, float[] pta, float[] ptb) { + // DONE + curve = null; + range = new float[3]; + + for (Quilt q = qlist; q != null; q = q.next) { + curve = new Curve(q, pta, ptb, curve); + } + range[0] = pta[0]; + range[1] = ptb[0]; + range[2] = range[1] - range[0]; + } + + /** + * Compute step size + */ + public void getstepsize() { + // DONE + stepsize = range[2]; + Curve c; + for (c = curve; c != null; c = c.next) { + c.getStepSize(); + c.clamp(); + stepsize = (c.stepsize < stepsize) ? c.stepsize : stepsize; + if (c.needsSamplingSubdivision()) + break; + } + needsSubdivision = (c != null) ? true : false; + + } + + /** + * Indicates whether curves need subdivision + * @return curves need subdivision + */ + public boolean needsSamplingSubdivision() { + // DONE + return needsSubdivision; + } + + /** + * Checks for culling + * @return Subdivider.CULL_TRIVIAL_REJECT or Subdivider.CULL_ACCEPT + */ + public int cullCheck() { + // DONE + for (Curve c = curve; c != null; c = c.next) + if (c.cullCheck() == Subdivider.CULL_TRIVIAL_REJECT) + return Subdivider.CULL_TRIVIAL_REJECT; + return Subdivider.CULL_ACCEPT; + } +} diff --git a/src/classes/com/sun/opengl/impl/glu/nurbs/DisplayList.java b/src/classes/com/sun/opengl/impl/glu/nurbs/DisplayList.java new file mode 100755 index 000000000..735c36edf --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/nurbs/DisplayList.java @@ -0,0 +1,56 @@ +package com.sun.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 1.1 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +import java.lang.reflect.Method; + +/** + * Display list + * @author Tomas Hrasky + * + */ +public class DisplayList { + + /** + * Append action to the display list + * @param src source object to invoke method on + * @param m invoked method + * @param arg method argument + */ + public void append(Object src, Method m, Object arg) { + // TODO Auto-generated method stub + // System.out.println("TODO displaylist append"); + } +} diff --git a/src/classes/com/sun/opengl/impl/glu/nurbs/Flist.java b/src/classes/com/sun/opengl/impl/glu/nurbs/Flist.java new file mode 100755 index 000000000..d9e798854 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/nurbs/Flist.java @@ -0,0 +1,130 @@ +package com.sun.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 1.1 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +import java.util.Arrays; + +/** + * List of breakpoints + * @author Tomas Hrasky + * + */ +public class Flist { + + /** + * Data elements end index + * + */ + public int end; + + /** + *Data elements start index + */ + public int start; + + /** + * Breakpoint values + */ + public float[] pts; + + /** + * Number of array fields + */ + private int npts; + + /** + * Grows list + * @param maxpts maximum desired size + */ + public void grow(int maxpts) { + // DONE + if (npts < maxpts) { + // npts=2*maxpts; + npts = maxpts; + pts = new float[npts]; + } + start = 0; + end = 0; + } + + /** + * Removes duplicate array elemnts + */ + public void filter() { + // INFO the aim of this method is to remove duplicates from array + + Arrays.sort(pts); + + start = 0; + + int j = 0; + + for (int i = 1; i < end; i++) { + if (pts[i] == pts[i - j - 1]) + j++; + pts[i - j] = pts[i]; + } + + end -= j; + + } + + /** + * Sets start and and to real start and end of array elements + * @param from start from + * @param to end at + */ + public void taper(float from, float to) { + // DONE + + while (pts[start] != from) { + start++; + } + + while (pts[end - 1] != to) { + end--; + } + + } + + /** + * Adds breakpoint value + * @param f value + */ + public void add(float f) { + //DONE + pts[end++] = f; + } +} diff --git a/src/classes/com/sun/opengl/impl/glu/nurbs/Knotspec.java b/src/classes/com/sun/opengl/impl/glu/nurbs/Knotspec.java new file mode 100755 index 000000000..bcb55388d --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/nurbs/Knotspec.java @@ -0,0 +1,557 @@ +package com.sun.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 1.1 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Knot vector specification + * + * @author Tomas Hrasky + * + */ +public class Knotspec { + + /** + * Begin of input knots + */ + public CArrayOfFloats inkbegin; + + /** + * End of input knots + */ + public CArrayOfFloats inkend; + + /** + * Stride before knot operations + */ + public int prestride; + + /** + * Curve order + */ + public int order; + + /** + * Next knot specification in linked list (used in surfaces) + */ + public Knotspec next; + + /** + * Last knot + */ + public CArrayOfFloats klast; + + /** + * First knot + */ + CArrayOfFloats kfirst; + + /** + * Beginning of breakpoints + */ + CArrayOfBreakpts bbegin; + + /** + * End of breakpoints + */ + CArrayOfBreakpts bend; + + /** + * Considered left end knot + */ + CArrayOfFloats kleft; + + /** + * Considered right end knot + */ + CArrayOfFloats kright; + + /** + * Offset before knot operations + */ + int preoffset; + + /** + * Control points array Length after knot operations + */ + int postwidth; + + /** + * Beginning of coeficients array + */ + private CArrayOfFloats sbegin; + + /** + * Beginning of output knots + */ + private CArrayOfFloats outkbegin; + + /** + * End of output knots + */ + private CArrayOfFloats outkend; + + /** + * Control points aray length before knot operations + */ + int prewidth; + + /** + * Offset after knot operations + */ + int postoffset; + + /** + * Number of control points' coordinates after knot operations + */ + public int poststride; + + /** + * Number of control points' coordinates + */ + public int ncoords; + + /** + * Tell whether knotspec has already benn transformed + */ + public boolean istransformed; + + /** + * Knotspec to be transformed + */ + public Knotspec kspectotrans; + + /** + * Finds knot border of knot insertion and required multiplicities + */ + public void preselect() { + // DONE + float kval; + + klast = new CArrayOfFloats(inkend); + klast.lessenPointerBy(order); + for (kval = klast.get(); klast.getPointer() != inkend.getPointer(); klast + .pp()) { + if (!Knotvector.identical(klast.get(), kval)) + break; + } + + kfirst = new CArrayOfFloats(inkbegin); + kfirst.raisePointerBy(order - 1); + for (kval = kfirst.get(); kfirst.getPointer() != inkend.getPointer(); kfirst + .pp()) { + if (!Knotvector.identical(kfirst.get(), kval)) + break; + } + + CArrayOfFloats k = new CArrayOfFloats(kfirst); + k.mm(); + + for (; k.getPointer() >= inkbegin.getPointer(); k.mm()) + if (!Knotvector.identical(kval, k.get())) + break; + k.pp(); + + Breakpt[] bbeginArray = new Breakpt[(klast.getPointer() - kfirst + .getPointer()) + 1]; + for (int i = 0; i < bbeginArray.length; i++) + bbeginArray[i] = new Breakpt(); + bbegin = new CArrayOfBreakpts(bbeginArray, 0); + bbegin.get().multi = kfirst.getPointer() - k.getPointer(); + bbegin.get().value = kval; + + bend = new CArrayOfBreakpts(bbegin); + kleft = new CArrayOfFloats(kfirst); + kright = new CArrayOfFloats(kfirst); + + } + + /** + * Perpares knotspec for transformation + */ + public void select() { + // DONE + breakpoints(); + knots(); + factors(); + + preoffset = kleft.getPointer() - (inkbegin.getPointer() + order); + postwidth = ((bend.getPointer() - bbegin.getPointer()) * order); + prewidth = (outkend.getPointer() - outkbegin.getPointer()) - order; + postoffset = (bbegin.get().def > 1) ? (bbegin.get().def - 1) : 0; + + } + + /** + * Computes alpha factors for computing new control points + */ + private void factors() { + // DONE + CArrayOfFloats mid = new CArrayOfFloats(outkend.getArray(), (outkend + .getPointer() - 1) + - order + bend.get().multi); + + CArrayOfFloats fptr = null; + if (sbegin != null) + fptr = new CArrayOfFloats(sbegin); + + for (CArrayOfBreakpts bpt = new CArrayOfBreakpts(bend); bpt + .getPointer() >= bbegin.getPointer(); bpt.mm()) { + mid.lessenPointerBy(bpt.get().multi); + int def = bpt.get().def - 1; + if (def < 0) + continue; + float kv = bpt.get().value; + + CArrayOfFloats kf = new CArrayOfFloats(mid.getArray(), (mid + .getPointer() - def) + + (order - 1)); + for (CArrayOfFloats kl = new CArrayOfFloats(kf.getArray(), kf + .getPointer() + + def); kl.getPointer() != kf.getPointer(); kl.mm()) { + CArrayOfFloats kh, kt; + for (kt = new CArrayOfFloats(kl), kh = new CArrayOfFloats(mid); kt + .getPointer() != kf.getPointer(); kh.mm(), kt.mm()) { + fptr.set((kv - kh.get()) / (kt.get() - kh.get())); + fptr.pp(); + } + kl.set(kv); + } + } + + } + + /** + * Makes new knot vector + */ + private void knots() { + // DONE + CArrayOfFloats inkpt = new CArrayOfFloats(kleft.getArray(), kleft + .getPointer() + - order); + CArrayOfFloats inkend = new CArrayOfFloats(kright.getArray(), kright + .getPointer() + + bend.get().def); + + outkbegin = new CArrayOfFloats(new float[inkend.getPointer() + - inkpt.getPointer()], 0); + CArrayOfFloats outkpt; + for (outkpt = new CArrayOfFloats(outkbegin); inkpt.getPointer() != inkend + .getPointer(); inkpt.pp(), outkpt.pp()) { + outkpt.set(inkpt.get()); + } + outkend = new CArrayOfFloats(outkpt); + } + + /** + * Analyzes breakpoints + */ + private void breakpoints() { + // DONE + CArrayOfBreakpts ubpt = new CArrayOfBreakpts(bbegin); + CArrayOfBreakpts ubend = new CArrayOfBreakpts(bend); + int nfactors = 0; + + ubpt.get().value = ubend.get().value; + ubpt.get().multi = ubend.get().multi; + + kleft = new CArrayOfFloats(kright); + + for (; kright.getPointer() != klast.getPointer(); kright.pp()) { + if (Knotvector.identical(kright.get(), ubpt.get().value)) { + ubpt.get().multi++; + } else { + ubpt.get().def = order - ubpt.get().multi; + nfactors += (ubpt.get().def * (ubpt.get().def - 1)) / 2; + ubpt.pp(); + ubpt.get().value = kright.get(); + ubpt.get().multi = 1; + } + } + ubpt.get().def = order - ubpt.get().multi; + nfactors += (ubpt.get().def * (ubpt.get().def - 1)) / 2; + + bend = new CArrayOfBreakpts(ubpt); + + if (nfactors > 0) { + sbegin = new CArrayOfFloats(new float[nfactors], 0); + } else { + sbegin = null; + } + + } + + /** + * Copies control points + * + * @param _inpt + * input control points + * @param _outpt + * output control points + */ + public void copy(CArrayOfFloats _inpt, CArrayOfFloats _outpt) { + CArrayOfFloats inpt = new CArrayOfFloats(_inpt); + CArrayOfFloats outpt = new CArrayOfFloats(_outpt); + + inpt.raisePointerBy(preoffset); + if (next != null) { + for (CArrayOfFloats lpt = new CArrayOfFloats(outpt.getArray(), + outpt.getPointer() + prewidth); outpt.getPointer() != lpt + .getPointer(); outpt.raisePointerBy(poststride)) { + next.copy(inpt, outpt); + inpt.raisePointerBy(prestride); + } + + } else { + for (CArrayOfFloats lpt = new CArrayOfFloats(outpt.getArray(), + outpt.getPointer() + prewidth); outpt.getPointer() != lpt + .getPointer(); outpt.raisePointerBy(poststride)) { + pt_io_copy(outpt, inpt); + inpt.raisePointerBy(prestride); + } + } + + } + + /** + * Copies one control point to other + * + * @param topt + * source control point + * @param frompt + * destination control point + */ + private void pt_io_copy(CArrayOfFloats topt, CArrayOfFloats frompt) { + // DONE + switch (ncoords) { + case 4: + topt.setRelative(3, frompt.getRelative(3)); + case 3: + topt.setRelative(2, frompt.getRelative(2)); + case 2: + topt.setRelative(1, frompt.getRelative(1)); + case 1: + topt.set(frompt.get()); + break; + default: + // TODO break with copying in general case + // System.out.println("TODO knotspec.pt_io_copy"); + break; + } + + } + + /** + * Inserts a knot + * + * @param _p + * inserted knot + */ + public void transform(CArrayOfFloats _p) { + CArrayOfFloats p = new CArrayOfFloats(_p); + // DONE + if (next != null) {//surface code + if (this.equals(kspectotrans)) { + next.transform(p); + } else { + if (istransformed) { + p.raisePointerBy(postoffset); + for (CArrayOfFloats pend = new CArrayOfFloats(p.getArray(), + p.getPointer() + postwidth); p.getPointer() != pend + .getPointer(); p.raisePointerBy(poststride)) + next.transform(p); + + } else { + CArrayOfFloats pend = new CArrayOfFloats(p.getArray(), p + .getPointer() + + prewidth); + for (; p.getPointer() != pend.getPointer(); p + .raisePointerBy(poststride)) + next.transform(p); + } + } + + } else {//code for curve + if (this.equals(kspectotrans)) { + insert(p); + } else { + if (istransformed) { + p.raisePointerBy(postoffset); + for (CArrayOfFloats pend = new CArrayOfFloats(p.getArray(), + p.getPointer() + postwidth); p.getPointer() != pend + .getPointer(); p.raisePointerBy(poststride)) { + kspectotrans.insert(p); + } + } else { + CArrayOfFloats pend = new CArrayOfFloats(p.getArray(), p + .getPointer() + + prewidth); + for (; p.getPointer() != pend.getPointer(); p + .raisePointerBy(poststride)) + kspectotrans.insert(p); + } + } + } + + } + + /** + * Inserts a knot and computes new control points + * + * @param p + * inserted knot + */ + private void insert(CArrayOfFloats p) { + // DONE + CArrayOfFloats fptr = null; + if (sbegin != null) + fptr = new CArrayOfFloats(sbegin); + CArrayOfFloats srcpt = new CArrayOfFloats(p.getArray(), p.getPointer() + + prewidth - poststride); + // CArrayOfFloats srcpt = new CArrayOfFloats(p.getArray(), prewidth - + // poststride); + CArrayOfFloats dstpt = new CArrayOfFloats(p.getArray(), p.getPointer() + + postwidth + postoffset - poststride); + // CArrayOfFloats dstpt = new CArrayOfFloats(p.getArray(), postwidth + + // postoffset - poststride); + CArrayOfBreakpts bpt = new CArrayOfBreakpts(bend); + + for (CArrayOfFloats pend = new CArrayOfFloats(srcpt.getArray(), srcpt + .getPointer() + - poststride * bpt.get().def); srcpt.getPointer() != pend + .getPointer(); pend.raisePointerBy(poststride)) { + CArrayOfFloats p1 = new CArrayOfFloats(srcpt); + for (CArrayOfFloats p2 = new CArrayOfFloats(srcpt.getArray(), srcpt + .getPointer() + - poststride); p2.getPointer() != pend.getPointer(); p1 + .setPointer(p2.getPointer()), p2 + .lessenPointerBy(poststride)) { + pt_oo_sum(p1, p1, p2, fptr.get(), 1.0 - fptr.get()); + fptr.pp(); + } + } + bpt.mm(); + for (; bpt.getPointer() >= bbegin.getPointer(); bpt.mm()) { + + for (int multi = bpt.get().multi; multi > 0; multi--) { + pt_oo_copy(dstpt, srcpt); + dstpt.lessenPointerBy(poststride); + srcpt.lessenPointerBy(poststride); + } + for (CArrayOfFloats pend = new CArrayOfFloats(srcpt.getArray(), + srcpt.getPointer() - poststride * bpt.get().def); srcpt + .getPointer() != pend.getPointer(); pend + .raisePointerBy(poststride), dstpt + .lessenPointerBy(poststride)) { + pt_oo_copy(dstpt, srcpt); + CArrayOfFloats p1 = new CArrayOfFloats(srcpt); + + for (CArrayOfFloats p2 = new CArrayOfFloats(srcpt.getArray(), + srcpt.getPointer() - poststride); p2.getPointer() != pend + .getPointer(); p1.setPointer(p2.getPointer()), p2 + .lessenPointerBy(poststride)) { + pt_oo_sum(p1, p1, p2, fptr.get(), 1.0 - fptr.get()); + fptr.pp(); + } + } + } + } + + /** + * Copies one control point to another + * + * @param topt + * source ctrl point + * @param frompt + * distance ctrl point + */ + private void pt_oo_copy(CArrayOfFloats topt, CArrayOfFloats frompt) { + // DONE + // this is a "trick" with case - "break" is omitted so it comes through all cases + switch (ncoords) { + case 4: + topt.setRelative(3, frompt.getRelative(3)); + case 3: + topt.setRelative(2, frompt.getRelative(2)); + case 2: + topt.setRelative(1, frompt.getRelative(1)); + case 1: + topt.setRelative(0, frompt.getRelative(0)); + break; + default: + // default uses memcpy but it is not needed (we probably won't have more than 4 coords) + // TODO not sure about it + break; + } + + } + + /** + * Computes new control point + * + * @param x + * first point + * @param y + * second point + * @param z + * third pont + * @param a + * alpha + * @param b + * 1 - alpha + */ + private void pt_oo_sum(CArrayOfFloats x, CArrayOfFloats y, + CArrayOfFloats z, float a, double b) { + // DONE + switch (ncoords) { + case 4: + x.setRelative(3, (float) (a * y.getRelative(3) + b + * z.getRelative(3))); + case 3: + x.setRelative(2, (float) (a * y.getRelative(2) + b + * z.getRelative(2))); + case 2: + x.setRelative(1, (float) (a * y.getRelative(1) + b + * z.getRelative(1))); + case 1: + x.setRelative(0, (float) (a * y.getRelative(0) + b + * z.getRelative(0))); + break; + default: + //no need of default - see previous method and its case statement + // System.out.println("TODO pt_oo_sum default"); + break; + } + } +} diff --git a/src/classes/com/sun/opengl/impl/glu/nurbs/Knotvector.java b/src/classes/com/sun/opengl/impl/glu/nurbs/Knotvector.java new file mode 100755 index 000000000..c7c3d4578 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/nurbs/Knotvector.java @@ -0,0 +1,179 @@ +package com.sun.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 1.1 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Knot vector used in curve specification + * + * @author Tomas Hrasky + * + */ +public class Knotvector { + + /** + * Tolerance used when comparing knots - when difference is smaller, knots + * are considered equal + */ + public static final float TOLERANCE = 1.0e-5f; + + /** + * Maximum curve order + */ + private static final int MAXORDER = 24; + + /** + * Number of knots + */ + int knotcount; + + /** + * Number of control points' coordinates + */ + int stride; + + /** + * Curve order + */ + int order; + + /** + * Knots + */ + float[] knotlist; + + /** + * Makes new knotvector + * + * @param nknots + * number of knots + * @param stride + * number of ctrl points' corrdinates + * @param order + * curve order + * @param knot + * knots + */ + public Knotvector(int nknots, int stride, int order, float[] knot) { + // DONE + init(nknots, stride, order, knot); + } + + /** + * Initializes knotvector + * + * @param nknots + * number of knots + * @param stride + * number of ctrl points' corrdinates + * @param order + * curve order + * @param knot + * knots + */ + public void init(int nknots, int stride, int order, float[] knot) { + // DONE + this.knotcount = nknots; + this.stride = stride; + this.order = order; + this.knotlist = new float[nknots]; + for (int i = 0; i < nknots; i++) { + this.knotlist[i] = knot[i]; + } + + } + + /** + * Validates knot vector parameters + * + * @return knot vector validity + */ + public int validate() { + int kindex = knotcount - 1; + if (order < 1 || order > MAXORDER) { + return 1; + } + if (knotcount < 2 * order) { + return 2; + } + if (identical(knotlist[kindex - (order - 1)], knotlist[order - 1])) { + return 3; + } + for (int i = 0; i < kindex; i++) { + if (knotlist[i] > knotlist[i + 1]) + return 4; + } + int multi = 1; + for (; kindex >= 1; kindex--) { + if (knotlist[kindex] - knotlist[kindex - 1] < TOLERANCE) { + multi++; + continue; + } + if (multi > order) { + return 5; + } + multi = 1; + } + if (multi > order) { + return 5; + } + + return 0; + } + + /** + * Show specified message + * + * @param msg + * message to be shown + */ + public void show(String msg) { + // TODO Auto-generated method stub + // System.out.println("TODO knotvector.show"); + + } + + /** + * Compares two knots for equality + * + * @param a + * first knot + * @param b + * second knot + * @return knots are/are not equal + */ + public static boolean identical(float a, float b) { + return ((a - b) < TOLERANCE) ? true : false; + } +} diff --git a/src/classes/com/sun/opengl/impl/glu/nurbs/Mapdesc.java b/src/classes/com/sun/opengl/impl/glu/nurbs/Mapdesc.java new file mode 100755 index 000000000..8b52a4a8a --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/nurbs/Mapdesc.java @@ -0,0 +1,442 @@ +package com.sun.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 1.1 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class holding properties of OpenGL map + * @author Tomas Hrasky + * + */ +public class Mapdesc { + + /** + * Maximum control point coords + */ + private static final int MAXCOORDS = 5; + + /** + * Next description in list + */ + public Mapdesc next; + + /** + * Is map rational + */ + public int isrational; + + /** + * Number of control point coords + */ + public int ncoords; + + /** + * Map type + */ + private int type; + + /** + * Number of homogenous coords + */ + private int hcoords; + + /** + * Number of inhomogenous coords + */ + private int inhcoords; + + /** + * Not used + */ + private int mask; + + /** + * Value of N_PIXEL_TOLERANCE property + */ + private float pixel_tolerance; + + /** + * Value of N_ERROR_TOLERANCE property + */ + private float error_tolerance; + + /** + * Value of N_BBOX_SUBDIVIDING property + */ + private float bbox_subdividing; + + /** + * Value of N_CULLING property + */ + private float culling_method; + + /** + * Value of N_SAMPLINGMETHOD property + */ + private float sampling_method; + + /** + * Value of N_CLAMPFACTOR property + */ + float clampfactor; + + /** + * Value of N_MINSAVINGS property + */ + private float minsavings; + + /** + * Steps in u direction + */ + private float s_steps; + + /** + * Steps in v direction + */ + private float t_steps; + + /** + * Maximal step + */ + float maxrate; + + /** + * Maximal u direction step + */ + private float maxsrate; + + /** + * Maximal v direction step + */ + private float maxtrate; + + /** + * Not used + */ + private float[][] bmat; + + /** + * Sampling matrix + */ + private float[][] smat; + + /** + * Not used + */ + private float[][] cmat; + + /** + * Not used + */ + private float[] bboxsize; + + /** + * Makes new mapdesc + * @param type map type + * @param rational is rational + * @param ncoords number of control points coords + * @param backend backend object + */ + public Mapdesc(int type, int rational, int ncoords, Backend backend) { + // DONE + this.type = type; + this.isrational = rational; + this.ncoords = ncoords; + this.hcoords = ncoords + (isrational > 0 ? 0 : 1); + this.inhcoords = ncoords - (isrational > 0 ? 1 : 0); + this.mask = ((1 << (inhcoords * 2)) - 1); + next = null; + + assert (hcoords <= MAXCOORDS); + assert (inhcoords >= 1); + + pixel_tolerance = 1f; + error_tolerance = 1f; + bbox_subdividing = NurbsConsts.N_NOBBOXSUBDIVISION; + culling_method = NurbsConsts.N_NOCULLING; + sampling_method = NurbsConsts.N_NOSAMPLING; + clampfactor = NurbsConsts.N_NOCLAMPING; + minsavings = NurbsConsts.N_NOSAVINGSSUBDIVISION; + s_steps = 0f; + t_steps = 0f; + + maxrate = (s_steps < 0) ? 0 : s_steps; + maxsrate = (s_steps < 0) ? 0 : s_steps; + maxtrate = (t_steps < 0) ? 0 : t_steps; + bmat = new float[MAXCOORDS][MAXCOORDS]; + cmat = new float[MAXCOORDS][MAXCOORDS]; + smat = new float[MAXCOORDS][MAXCOORDS]; + + identify(bmat); + identify(cmat); + identify(smat); + bboxsize = new float[MAXCOORDS]; + for (int i = 0; i < inhcoords; i++) + bboxsize[i] = 1; + } + + /** + * Make matrix identity matrix + * @param arr matrix + */ + private void identify(float[][] arr) { + // DONE + for (int i = 0; i < MAXCOORDS; i++) + for (int j = 0; j < MAXCOORDS; j++) + arr[i][j] = 0; + for (int i = 0; i < MAXCOORDS; i++) + arr[i][i] = 1; + + } + + /** + * Tells whether tag is property tag + * @param tag property tag + * @return is/is not property + */ + public boolean isProperty(int tag) { + boolean ret; + switch (tag) { + case NurbsConsts.N_PIXEL_TOLERANCE: + case NurbsConsts.N_ERROR_TOLERANCE: + case NurbsConsts.N_CULLING: + case NurbsConsts.N_BBOX_SUBDIVIDING: + case NurbsConsts.N_S_STEPS: + case NurbsConsts.N_T_STEPS: + case NurbsConsts.N_SAMPLINGMETHOD: + case NurbsConsts.N_CLAMPFACTOR: + case NurbsConsts.N_MINSAVINGS: + ret = true; + break; + default: + ret = false; + break; + } + return ret; + } + + /** + * Returns number of control points' coords + * @return number of control points' coords + */ + public int getNCoords() { + return ncoords; + } + + /** + * Returns map type + * @return map type + */ + public int getType() { + return type; + } + + /** + * Tells whether map is range sampling + * @return is map range sampling + */ + public boolean isRangeSampling() { + // DONE + return (isParametricDistanceSampling() || isPathLengthSampling() + || isSurfaceAreaSampling() || isObjectSpaceParaSampling() || isObjectSpacePathSampling()); + } + + /** + * Tells whether map is object space sampling + * @return is map object space sampling + */ + private boolean isObjectSpacePathSampling() { + // DONE + return sampling_method == NurbsConsts.N_OBJECTSPACE_PATH; + } + + /** + * Tells whether map is object space parasampling + * @return is map object space parasampling + */ + private boolean isObjectSpaceParaSampling() { + // DONE + return sampling_method == NurbsConsts.N_OBJECTSPACE_PARA; + } + + /** + * Tells whether map is area sampling surface + * @return is map area sampling surface + */ + private boolean isSurfaceAreaSampling() { + // DONE + return sampling_method == NurbsConsts.N_SURFACEAREA; + } + + /** + * Tells whether map is path length sampling + * @return is map path length sampling + */ + boolean isPathLengthSampling() { + // DONE + return sampling_method == NurbsConsts.N_PATHLENGTH; + } + + /** + * Tells whether map is parametric distance sampling + * @return is map parametric distance sampling + */ + boolean isParametricDistanceSampling() { + // DONE + return sampling_method == NurbsConsts.N_PARAMETRICDISTANCE; + } + + /** + * Tells whether map is culling + * @return is map culling + */ + public boolean isCulling() { + // DONE + return culling_method != NurbsConsts.N_NOCULLING ? true : false; + } + + /** + * Tells whether map is constantly sampling + * @return is map constant sampling + */ + public boolean isConstantSampling() { + return (sampling_method == NurbsConsts.N_FIXEDRATE) ? true : false; + } + + /** + * Tells whether map is domain sampling + * @return is map domain sampling + */ + public boolean isDomainSampling() { + return (sampling_method == NurbsConsts.N_DOMAINDISTANCE) ? true : false; + } + + /** + * Returns property of specified tag value + * @param tag property tag + * @return property value + */ + public float getProperty(int tag) { + // TODO Auto-generated method stub + // System.out.println("TODO mapdesc.getproperty"); + return 0; + } + + /** + * Sets property with given tag + * @param tag property tag + * @param value desired value + */ + public void setProperty(int tag, float value) { + // TODO Auto-generated method stub + switch (tag) { + case NurbsConsts.N_PIXEL_TOLERANCE: + pixel_tolerance = value; + break; + case NurbsConsts.N_ERROR_TOLERANCE: + error_tolerance = value; + break; + case NurbsConsts.N_CULLING: + culling_method = value; + break; + case NurbsConsts.N_BBOX_SUBDIVIDING: + if (value <= 0) + value = NurbsConsts.N_NOBBOXSUBDIVISION; + bbox_subdividing = value; + break; + case NurbsConsts.N_S_STEPS: + if (value < 0) + value = 0; + s_steps = value; + maxrate = value; + maxsrate = value; + break; + case NurbsConsts.N_T_STEPS: + if (value < 0) + value = 0; + t_steps = value; + maxtrate = value; + break; + case NurbsConsts.N_SAMPLINGMETHOD: + sampling_method = value; + break; + case NurbsConsts.N_CLAMPFACTOR: + if (value < 0) + value = 0; + clampfactor = value; + break; + case NurbsConsts.N_MINSAVINGS: + if (value <= 0) + value = NurbsConsts.N_NOSAVINGSSUBDIVISION; + minsavings = value; + break; + } + } + + /** + * Samples curve + * @param pts control points + * @param order curve order + * @param stride number of control points' coordinates + * @param sp breakpoints + * @param outstride output number of control points' coordinates + */ + public void xformSampling(CArrayOfFloats pts, int order, int stride, + float[] sp, int outstride) { + // DONE + xFormMat(smat, pts, order, stride, sp, outstride); + } + + /** + * Empty method + * @param mat sampling matrix + * @param pts ontrol points + * @param order curve order + * @param stride number of control points' coordinates + * @param cp breakpoints + * @param outstride output number of control points' coordinates + */ + private void xFormMat(float[][] mat, CArrayOfFloats pts, int order, + int stride, float[] cp, int outstride) { + // TODO Auto-generated method stub + + // System.out.println("TODO mapdsc.xformmat ; change cp from float[] to carrayoffloats"); + + if (isrational > 0) { + + } else { + + } + } +} diff --git a/src/classes/com/sun/opengl/impl/glu/nurbs/Maplist.java b/src/classes/com/sun/opengl/impl/glu/nurbs/Maplist.java new file mode 100755 index 000000000..3b6e22ea5 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/nurbs/Maplist.java @@ -0,0 +1,122 @@ +package com.sun.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 1.1 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class holding list of Mapdescs + * @author Tomáš Hráský + * + */ +public class Maplist { + /** + * Head of linked list + */ + private Mapdesc maps; + + /** + * Backend class + */ + private Backend backend; + + /** + * Makes new Maplist + * @param backend Backend class + */ + public Maplist(Backend backend) { + this.backend = backend; + } + + /** + * Sets linked list beginning to null + */ + public void initialize() { + // TODO mapdespool.clear ? + maps = null; + } + + /** + * Defines new Mapdesc if it is not defined and appends it to linked list + * @param type map type + * @param rational is map rational + * @param ncoords number of coords + */ + public void define(int type, int rational, int ncoords) { + // DONE + Mapdesc m = locate(type); + assert (m == null || (m.isrational == rational && m.ncoords == ncoords)); + add(type, rational, ncoords); + + } + + /** + * Adds new Mapdesc to linked list + * @param type map type + * @param rational is map rational + * @param ncoords number of coords + */ + private void add(int type, int rational, int ncoords) { + // DONE + Mapdesc map = new Mapdesc(type, rational, ncoords, backend); + if (maps == null) { + maps = map; + } else { + map.next = maps; + maps = map; + } + } + + /** + * Tries to find Mapdesc in linked list + * @param type map type + * @return Mapdesc of type or null if there is no such map + */ + public Mapdesc locate(int type) { + // DONE + Mapdesc m = null; + for (m = maps; m != null; m = m.next) + if (m.getType() == type) + break; + return m; + } + + /** + * Alias for locate + * @param type maptype + * @return Mapdesc of type or null if there is no such map + */ + public Mapdesc find(int type) { + return locate(type); + } +} diff --git a/src/classes/com/sun/opengl/impl/glu/nurbs/NurbsConsts.java b/src/classes/com/sun/opengl/impl/glu/nurbs/NurbsConsts.java new file mode 100755 index 000000000..c98e74b7c --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/nurbs/NurbsConsts.java @@ -0,0 +1,184 @@ +package com.sun.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 1.1 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class hodling NURBS constants as seen in OpenGL GLU documentation + * @author JOGL project + * + */ +public class NurbsConsts { + /* + * NURBS Properties - one set per map, each takes a single INREAL arg + */ + public static final int N_SAMPLING_TOLERANCE = 1; + + public static final int N_S_RATE = 6; + + public static final int N_T_RATE = 7; + + public static final int N_CLAMPFACTOR = 13; + + public static final float N_NOCLAMPING = 0.0f; + + public static final int N_MINSAVINGS = 14; + + public static final float N_NOSAVINGSSUBDIVISION = 0.0f; + + /* + * NURBS Properties - one set per map, each takes an enumerated value + */ + public static final int N_CULLING = 2; + + public static final float N_NOCULLING = 0.0f; + + public static final float N_CULLINGON = 1.0f; + + public static final int N_SAMPLINGMETHOD = 10; + + public static final float N_NOSAMPLING = 0.0f; + + public static final float N_FIXEDRATE = 3.0f; + + public static final float N_DOMAINDISTANCE = 2.0f; + + public static final float N_PARAMETRICDISTANCE = 5.0f; + + public static final float N_PATHLENGTH = 6.0f; + + public static final float N_SURFACEAREA = 7.0f; + + public static final float N_OBJECTSPACE_PARA = 8.0f; + + public static final float N_OBJECTSPACE_PATH = 9.0f; + + public static final int N_BBOX_SUBDIVIDING = 17; + + public static final float N_NOBBOXSUBDIVISION = 0.0f; + + public static final float N_BBOXTIGHT = 1.0f; + + public static final float N_BBOXROUND = 2.0f; + + /* + * NURBS Rendering Properties - one set per renderer each takes an + * enumerated value + */ + public static final int N_DISPLAY = 3; + + public static final int N_FILL = 1; + + public static final int N_OUTLINE_POLY = 2; + + public static final int N_OUTLINE_TRI = 3; + + public static final int N_OUTLINE_QUAD = 4; + + public static final int N_OUTLINE_PATCH = 5; + + public static final int N_OUTLINE_PARAM = 6; + + public static final int N_OUTLINE_PARAM_S = 7; + + public static final int N_OUTLINE_PARAM_ST = 8; + + public static final int N_OUTLINE_SUBDIV = 9; + + public static final int N_OUTLINE_SUBDIV_S = 10; + + public static final int N_OUTLINE_SUBDIV_ST = 11; + + public static final int N_ISOLINE_S = 12; + + public static final int N_ERRORCHECKING = 4; + + public static final int N_NOMSG = 0; + + public static final int N_MSG = 1; + + /* GL 4.0 propeties not defined above */ + + public static final int N_PIXEL_TOLERANCE = N_SAMPLING_TOLERANCE; + + public static final int N_ERROR_TOLERANCE = 20; + + public static final int N_SUBDIVISIONS = 5; + + public static final int N_TILES = 8; + + public static final int N_TMP1 = 9; + + public static final int N_TMP2 = N_SAMPLINGMETHOD; + + public static final int N_TMP3 = 11; + + public static final int N_TMP4 = 12; + + public static final int N_TMP5 = N_CLAMPFACTOR; + + public static final int N_TMP6 = N_MINSAVINGS; + + public static final int N_S_STEPS = N_S_RATE; + + public static final int N_T_STEPS = N_T_RATE; + + /* + * NURBS Rendering Properties - one set per map, each takes an INREAL matrix + * argument + */ + public static final int N_CULLINGMATRIX = 1; + + public static final int N_SAMPLINGMATRIX = 2; + + public static final int N_BBOXMATRIX = 3; + + /* + * NURBS Rendering Properties - one set per map, each takes an INREAL vector + * argument + */ + public static final int N_BBOXSIZE = 4; + + /* type argument for trimming curves */ + + public static final int N_P2D = 0x8; + + public static final int N_P2DR = 0xd; + + public static final int N_MESHLINE = 1; + + public static final int N_MESHFILL = 0; + + public static final int N_MESHPOINT = 2; +} diff --git a/src/classes/com/sun/opengl/impl/glu/nurbs/O_curve.java b/src/classes/com/sun/opengl/impl/glu/nurbs/O_curve.java new file mode 100755 index 000000000..b130226c4 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/nurbs/O_curve.java @@ -0,0 +1,63 @@ +package com.sun.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 1.1 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Struct holding curve links + * @author Tomáš Hráský + * + */ +public class O_curve { + + /** + * Curve type + */ + public int curvetype; + + /** + * Next curve in linked list + */ + public O_curve next; + + /** + * Curve of picewiselinear type + */ + public O_pwlcurve o_pwlcurve; + + /** + * NURBS curve + */ + public O_nurbscurve o_nurbscurve; +} diff --git a/src/classes/com/sun/opengl/impl/glu/nurbs/O_nurbscurve.java b/src/classes/com/sun/opengl/impl/glu/nurbs/O_nurbscurve.java new file mode 100755 index 000000000..68bf60b27 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/nurbs/O_nurbscurve.java @@ -0,0 +1,80 @@ +package com.sun.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 1.1 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * NURBS curve object + * @author Tomáš Hráský + * + */ +public class O_nurbscurve { + + /** + * List of bezier curves + */ + public Quilt bezier_curves; + + /** + * Curve type + */ + public int type; + + /** + * Was curve used ? + */ + public boolean used; + + /** + * Parent curve + */ + public O_curve owner; + + /** + * Next curve in list + */ + public O_nurbscurve next; + + /** + * Makes new O_nurbscurve + * @param realType type of curve + */ + public O_nurbscurve(int realType) { + // DONE + this.type = realType; + this.owner = null; + this.next = null; + this.used = false; + } +} diff --git a/src/classes/com/sun/opengl/impl/glu/nurbs/O_nurbssurface.java b/src/classes/com/sun/opengl/impl/glu/nurbs/O_nurbssurface.java new file mode 100755 index 000000000..1cbaa6ccc --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/nurbs/O_nurbssurface.java @@ -0,0 +1,79 @@ +package com.sun.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 1.1 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * NURBS surface object + * @author Tomáš Hráský + * + */ +public class O_nurbssurface { + + /** + * List of bezier patches forming NURBS surface + */ + public Quilt bezier_patches; + + /** + * Was surface used + */ + public boolean used; + + /** + * Parent O_surface + */ + public O_surface owner; + + /** + * Next surface in list + */ + public O_nurbssurface next; + + /** + * Surface type + */ + private int type; + + /** + * Makes new O_nurbssurface of type + * @param type surface type + */ + public O_nurbssurface(int type) { + this.type = type; + this.owner = null; + this.next = null; + this.used = false; + } +} diff --git a/src/classes/com/sun/opengl/impl/glu/nurbs/O_pwlcurve.java b/src/classes/com/sun/opengl/impl/glu/nurbs/O_pwlcurve.java new file mode 100755 index 000000000..4dec066d6 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/nurbs/O_pwlcurve.java @@ -0,0 +1,44 @@ +package com.sun.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 1.1 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Empty class + * @author Tomáš Hráský + * + */ +public class O_pwlcurve { + +} diff --git a/src/classes/com/sun/opengl/impl/glu/nurbs/O_surface.java b/src/classes/com/sun/opengl/impl/glu/nurbs/O_surface.java new file mode 100755 index 000000000..4ef680c2f --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/nurbs/O_surface.java @@ -0,0 +1,52 @@ +package com.sun.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 1.1 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Surface object + * @author Tomáš Hráský + * + */ +public class O_surface { + /** + * NURBS surface + */ + public O_nurbssurface o_nurbssurface; + + /** + * Trims + */ + public O_trim o_trim; +} diff --git a/src/classes/com/sun/opengl/impl/glu/nurbs/O_trim.java b/src/classes/com/sun/opengl/impl/glu/nurbs/O_trim.java new file mode 100755 index 000000000..c1f61ebab --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/nurbs/O_trim.java @@ -0,0 +1,44 @@ +package com.sun.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 1.1 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Empty class + * @author Tomáš Hráský + * + */ +public class O_trim { + +} diff --git a/src/classes/com/sun/opengl/impl/glu/nurbs/Patch.java b/src/classes/com/sun/opengl/impl/glu/nurbs/Patch.java new file mode 100755 index 000000000..f15ad1f92 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/nurbs/Patch.java @@ -0,0 +1,54 @@ +package com.sun.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 1.1 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Empty class + * @author Tomas Hrasky + * + */ +public class Patch { + + /** + * Empty constructor + * @param q + * @param pta + * @param ptb + * @param patch + */ + public Patch(Quilt q, float[] pta, float[] ptb, Patch patch) { + // System.out.println("TODO patch.constructor"); + } +} diff --git a/src/classes/com/sun/opengl/impl/glu/nurbs/Patchlist.java b/src/classes/com/sun/opengl/impl/glu/nurbs/Patchlist.java new file mode 100755 index 000000000..b2b9033ec --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/nurbs/Patchlist.java @@ -0,0 +1,145 @@ +package com.sun.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 1.1 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * List of patches + * @author Tomáš Hráský + * + */ +public class Patchlist { + + /** + * Array of ranges + */ + public Pspec[] pspec; + + /** + * head of list of patches + */ + private Patch patch; + + /** + * Makes new list of patches + * @param quilts list of quilts + * @param pta low border + * @param ptb high border + */ + public Patchlist(Quilt quilts, float[] pta, float[] ptb) { + // DONE + patch = null; + + for (Quilt q = quilts; q != null; q = q.next) + patch = new Patch(q, pta, ptb, patch); + pspec[0] = new Pspec(); + pspec[0].range[0] = pta[0]; + pspec[0].range[1] = ptb[0]; + pspec[0].range[2] = ptb[0] - pta[0]; + pspec[1] = new Pspec(); + pspec[1].range[0] = pta[1]; + pspec[1].range[1] = ptb[1]; + pspec[1].range[2] = ptb[1] - pta[1]; + + } + + /** + * Empty constructor + * @param patchlist + * @param param + * @param mid + */ + public Patchlist(Patchlist patchlist, int param, float mid) { + // TODO Auto-generated constructor stub + // System.out.println("TODO patchlist.konstruktor 2"); + } + + /** + * Empty method + * @return 0 + */ + public int cullCheck() { + // TODO Auto-generated method stub + // System.out.println("TODO patchlist.cullcheck"); + return 0; + } + + /** + * Empty method + */ + public void getstepsize() { + // System.out.println("TODO patchlist.getsptepsize"); + // TODO Auto-generated method stub + + } + + /** + * Empty method + * @return false + */ + public boolean needsSamplingSubdivision() { + // TODO Auto-generated method stub + // System.out.println("patchlist.needsSamplingSubdivision"); + return false; + } + + /** + * Empty method + * @param i + * @return false + */ + public boolean needsSubdivision(int i) { + // TODO Auto-generated method stub + // System.out.println("TODO patchlist.needsSubdivision"); + return false; + } + + /** + * Empty method + * @return false + */ + public boolean needsNonSamplingSubdivision() { + // TODO Auto-generated method stub + // System.out.println("TODO patchlist.needsNonSamplingSubdivision"); + return false; + } + + /** + * Empty method + */ + public void bbox() { + // TODO Auto-generated method stub + // System.out.println("TODO patchlist.bbox"); + } +} diff --git a/src/classes/com/sun/opengl/impl/glu/nurbs/Property.java b/src/classes/com/sun/opengl/impl/glu/nurbs/Property.java new file mode 100755 index 000000000..e0ad1dd32 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/nurbs/Property.java @@ -0,0 +1,75 @@ +package com.sun.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 1.1 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class representing property + * + * @author Tomas Hrasky + * + */ +public class Property { + + /** + * Property type + */ + public int type; + + /** + * Property id + */ + public int tag; + + /** + * Property value + */ + public float value; + + /** + * Makes new property with given parameters + * + * @param type + * property type + * @param tag + * property id + * @param value + * property value + */ + public Property(int type, int tag, float value) { + this.type = type; + this.tag = tag; + this.value = value; + } +} diff --git a/src/classes/com/sun/opengl/impl/glu/nurbs/Pspec.java b/src/classes/com/sun/opengl/impl/glu/nurbs/Pspec.java new file mode 100755 index 000000000..5fc66fa82 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/nurbs/Pspec.java @@ -0,0 +1,47 @@ +package com.sun.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 1.1 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class holding range + * @author Tomáš Hráský + * + */ +public class Pspec { + /** + * Range + */ + public float[] range; +} diff --git a/src/classes/com/sun/opengl/impl/glu/nurbs/PwlArc.java b/src/classes/com/sun/opengl/impl/glu/nurbs/PwlArc.java new file mode 100755 index 000000000..6b8255d85 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/nurbs/PwlArc.java @@ -0,0 +1,71 @@ +package com.sun.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 1.1 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Picewiselinar trimming arc + * @author Tomáš Hráský + * + */ +public class PwlArc { + + /** + * Number of points + */ + private int npts; + + /** + * Vertexes + */ + public TrimVertex[] pts; + + /** + * Arc type + */ + private int type; + + /** + * Makes new trimming arc + * @param i num ber of vertexes + * @param p trimming vertexes array + */ + public PwlArc(int i, TrimVertex[] p) { + // DONE + this.npts = i; + this.pts = p; + type = NurbsConsts.N_P2D; + + } +} diff --git a/src/classes/com/sun/opengl/impl/glu/nurbs/Quilt.java b/src/classes/com/sun/opengl/impl/glu/nurbs/Quilt.java new file mode 100755 index 000000000..bc058b093 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/nurbs/Quilt.java @@ -0,0 +1,282 @@ +package com.sun.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 1.1 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class for converting NURBS curves and surfaces to list of bezier arcs or patches repectively + * @author Tomáš Hráský + * + */ +public class Quilt { + /** + * Maximum quilt dimension + */ + private static final int MAXDIM = 2; + + /** + * List of map descriptions + */ + Mapdesc mapdesc; + + /** + * Array of quiltspecs pointer + */ + public CArrayOfQuiltspecs qspec; + + /** + * End array of quilt specs pointer + */ + public CArrayOfQuiltspecs eqspec; + + /** + * Control points + */ + public CArrayOfFloats cpts; + + /** + * Next quilt in list + */ + public Quilt next; + + /** + * Makes new quilt with mapdesc + * @param mapdesc map description + */ + public Quilt(Mapdesc mapdesc) { + // DONE + this.mapdesc = mapdesc; + Quiltspec[] tmpquilts = new Quiltspec[MAXDIM]; + for (int i = 0; i < tmpquilts.length; i++) + tmpquilts[i] = new Quiltspec(); + this.qspec = new CArrayOfQuiltspecs(tmpquilts); + + } + + /** + * Converts NURBS surface to bezier patches + * @param sknotvector knots in u direction + * @param tknotvector knots in v direction + * @param ctrlarr control points + * @param coords control points coords + */ + public void toBezier(Knotvector sknotvector, Knotvector tknotvector, + CArrayOfFloats ctrlarr, int coords) { + Splinespec spline = new Splinespec(2); + spline.kspecinit(sknotvector, tknotvector); + spline.select(); + spline.layout(coords); + spline.setupquilt(this); + spline.copy(ctrlarr); + spline.transform(); + } + + /** + * Converts NURBS curve to list of bezier curves + * @param knots knot vector + * @param ctlarray control points + * @param ncoords number of coordinates + */ + public void toBezier(Knotvector knots, CArrayOfFloats ctlarray, int ncoords) { + // DONE + Splinespec spline = new Splinespec(1); + spline.kspecinit(knots); + spline.select(); + spline.layout(ncoords); + spline.setupquilt(this); + spline.copy(ctlarray); + spline.transform(); + } + + /** + * Walks thru all arcs/patches + * @param pta low border + * @param ptb high border + * @param backend Backend + */ + public void downloadAll(float[] pta, float[] ptb, Backend backend) { + // DONE + for (Quilt m = this; m != null; m = m.next) { + m.select(pta, ptb); + m.download(backend); + } + + } + + /** + * Renders arcs/patches + * @param backend Backend for rendering + */ + private void download(Backend backend) { + // DONE + if (getDimension() == 2) { + + CArrayOfFloats ps = new CArrayOfFloats(cpts); + ps.raisePointerBy(qspec.get(0).offset); + ps.raisePointerBy(qspec.get(1).offset); + ps.raisePointerBy(qspec.get(0).index * qspec.get(0).order + * qspec.get(0).stride); + ps.raisePointerBy(qspec.get(1).index * qspec.get(1).order + * qspec.get(1).stride); + + backend.surfpts(mapdesc.getType(), ps, qspec.get(0).stride, qspec + .get(1).stride, qspec.get(0).order, qspec.get(1).order, + qspec.get(0).breakpoints[qspec.get(0).index], + qspec.get(0).breakpoints[qspec.get(0).index + 1], qspec + .get(1).breakpoints[qspec.get(1).index], qspec + .get(1).breakpoints[qspec.get(1).index + 1]); + + } else {// code for curves + // CArrayOfFloats ps=new CArrayOfFloats(cpts); + CArrayOfFloats ps = new CArrayOfFloats(cpts.getArray(), 0); + ps.raisePointerBy(qspec.get(0).offset); + ps.raisePointerBy(qspec.get(0).index * qspec.get(0).order + * qspec.get(0).stride); + backend.curvpts(mapdesc.getType(), ps, qspec.get(0).stride, qspec + .get(0).order, + qspec.get(0).breakpoints[qspec.get(0).index], + qspec.get(0).breakpoints[qspec.get(0).index + 1]); + } + + } + + /** + * Returns quilt dimension + * @return quilt dimesion + */ + private int getDimension() { + // DONE + return eqspec.getPointer() - qspec.getPointer(); + } + + /** + * Finds Quiltspec.index + * @param pta range + * @param ptb range + */ + private void select(float[] pta, float[] ptb) { + // DONE + int dim = eqspec.getPointer() - qspec.getPointer(); + int i, j; + for (i = 0; i < dim; i++) { + for (j = qspec.get(i).width - 1; j >= 0; j--) + if (qspec.get(i).breakpoints[j] <= pta[i] + && ptb[i] <= qspec.get(i).breakpoints[j + 1]) + break; + assert (j != -1); + qspec.get(i).index = j; + } + } + + /** + * Find range according to breakpoints + * @param from low param + * @param to high param + * @param bpts breakpoints + */ + public void getRange(float[] from, float[] to, Flist bpts) { + // DONE + getRange(from, to, 0, bpts); + + } + + /** + * Find range according to breakpoints + * @param from low param + * @param to high param + * @param i from/to array index + * @param list breakpoints + */ + private void getRange(float[] from, float[] to, int i, Flist list) { + // DONE + Quilt maps = this; + from[i] = maps.qspec.get(i).breakpoints[0]; + to[i] = maps.qspec.get(i).breakpoints[maps.qspec.get(i).width]; + int maxpts = 0; + Quilt m; + for (m = maps; m != null; m = m.next) { + if (m.qspec.get(i).breakpoints[0] > from[i]) + from[i] = m.qspec.get(i).breakpoints[0]; + if (m.qspec.get(i).breakpoints[m.qspec.get(i).width] < to[i]) + to[i] = m.qspec.get(i).breakpoints[m.qspec.get(i).width]; + maxpts += m.qspec.get(i).width + 1; + } + list.grow(maxpts); + for (m = maps; m != null; m = m.next) { + for (int j = 0; j <= m.qspec.get(i).width; j++) { + list.add(m.qspec.get(i).breakpoints[j]); + } + } + list.filter(); + list.taper(from[i], to[i]); + } + + /** + * Is this quilt culled + * @return 0 or Subdivider.CULL_ACCEPT + */ + public int isCulled() { + if (mapdesc.isCulling()) { + // System.out.println("TODO quilt.isculled mapdesc.isculling"); + return 0; + } else { + return Subdivider.CULL_ACCEPT; + } + } + + /** + * Finds range for surface + * @param from low param + * @param to high param + * @param slist u direction breakpoints + * @param tlist v direction breakpoints + */ + public void getRange(float[] from, float[] to, Flist slist, Flist tlist) { + // DONE + getRange(from, to, 0, slist); + getRange(from, to, 1, tlist); + + } + + /** + * Empty method + * @param sbrkpts + * @param tbrkpts + * @param rate + */ + public void findRates(Flist sbrkpts, Flist tbrkpts, float[] rate) { + // TODO Auto-generated method stub + // System.out.println("TODO quilt.findrates"); + } +} diff --git a/src/classes/com/sun/opengl/impl/glu/nurbs/Quiltspec.java b/src/classes/com/sun/opengl/impl/glu/nurbs/Quiltspec.java new file mode 100755 index 000000000..d94986a03 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/nurbs/Quiltspec.java @@ -0,0 +1,85 @@ +package com.sun.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 1.1 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Quilt definition + * @author Tomas Hrasky + * + */ +public class Quiltspec { + + /** + * Stride between control points + */ + public int stride; + + /** + * Quilt width in breakpoints + */ + public int width; + + /** + * Quilt order + */ + public int order; + + /** + * Start offset + */ + public int offset; + + /** + * Breakpoint index + */ + public int index; + + /** + * Boundary + */ + public int[] bdry; + + /** + * Breakpoints + */ + public float[] breakpoints; + + /** + * Makes new quiltspec + */ + public Quiltspec() { + this.bdry = new int[2]; + } +} diff --git a/src/classes/com/sun/opengl/impl/glu/nurbs/README.txt b/src/classes/com/sun/opengl/impl/glu/nurbs/README.txt new file mode 100755 index 000000000..89630c71e --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/nurbs/README.txt @@ -0,0 +1,59 @@ +Unimplemented functionality + - tesselation and callbacks + - trimming + - setting NURBS properties (-> sampling etc.) +Differences from C++ source + - no pooling + - pointers to arrays are replaced by CArrayOf... classes and their methods +Unimplemented or incomplete "calltree top" methods (according to glu.def in Mesa 6.5) + gluBeginTrim + gluDeleteNurbsRenderer - won't be needed + gluEndTrim + gluGetNurbsProperty + gluLoadSamplingMatrices + gluNurbsCallback + gluNurbsCallbackData + gluNurbsCallbackDataEXT + gluNurbsCurve - TODO type switch + gluNurbsProperty + gluPwlCurve + gluQuadricCallback - not a NURBS method +As of files + - Arc[ST]dirSorter.java - unimplemented (part of tesselation) + - Backend.java:194 - wireframe quads - part of tesselation/callback + - Curve.java:141-204 - culling + - DisplayList.java:57 - append to DL - not sure whether it will be needed + - GLUnurbs.java :443,484 - error values + :445 - trimming + :512 - error handling (callback) + :530 - loadGLmatrices + :786 - nuid - nurbs object id - won't be needed I think + :803 - end trim + - GLUwNURBS.java:68,176 - NUBRS properties + - Knotspec.java :371 - copying in general case (more than 4 coords) + :517 - copying with more than 4 coords + :556 - pt_oo_sum default + - Knotvector.java:165 - show method (probably debugging) + - Mapdesc.java :354 - get property + :435 - xFormMat - change param cp to CArrayOfFloats; probably sampling functionality + - Maplist.java:68 - clear ? + - OpenGLCurveEvaluator.java :132 - tess./callback code + :168 - mapgrid1f + :190 - tess./callback code (output triangles) + - OpenGLSurfaceEvaluator.java :77 . tess./callback code + :81 - glGetIntegerValue + :114 - tess./callback code + :117 - Level of detail + :144,161,201 - tess./callback code - output triangles + - Patch.java:55 - constructor stuff ? + - Patchlist.java:55 - constructor stuff ? + :97 - cull check + :105 - step size + :115 - need of sampling subdivision + :126 - need of subdivision + :137 - need of non sampling subd. + :146 - bbox (??) + -Quilt.java :254 - culling + :282 - rates + -Subdivider.java - all TODOs - it's stuff about trimming probably + :545 - jumpbuffer - not sure purpose it exactly served in original source diff --git a/src/classes/com/sun/opengl/impl/glu/nurbs/Renderhints.java b/src/classes/com/sun/opengl/impl/glu/nurbs/Renderhints.java new file mode 100755 index 000000000..c571d9d88 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/nurbs/Renderhints.java @@ -0,0 +1,128 @@ +package com.sun.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 1.1 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class holding rendering params + * @author Tomas Hrasky + * + */ +public class Renderhints { + + /** + * Check for errors + */ + public int errorchecking; + + /** + * Maximum subdivisions + */ + public int maxsubdivisions; + + /** + * Number of subdivisions + */ + private int subdivisions; + + /** + * Display method + */ + int display_method; + + /** + * Output triangles + */ + int wiretris; + + /** + * Output quads + */ + int wirequads; + + /** + * Makes new Renderinghints + */ + public Renderhints() { + display_method = NurbsConsts.N_FILL; + errorchecking = NurbsConsts.N_MSG; + subdivisions = 6; + // tmp1=0; + } + + /** + * Set property value + * @param prop property + */ + public void setProperty(Property prop) { + switch (prop.type) { + case NurbsConsts.N_DISPLAY: + display_method = (int) prop.value; + break; + case NurbsConsts.N_ERRORCHECKING: + errorchecking = (int) prop.value; + break; + case NurbsConsts.N_SUBDIVISIONS: + subdivisions = (int) prop.value; + break; + default: + // abort - end program + break; + } + } + + /** + * Initialization + */ + public void init() { + // DONE + maxsubdivisions = subdivisions; + if (maxsubdivisions < 0) + maxsubdivisions = 0; + + if (display_method == NurbsConsts.N_FILL) { + wiretris = 0; + wirequads = 0; + } else if (display_method == NurbsConsts.N_OUTLINE_TRI) { + wiretris = 1; + wirequads = 0; + } else if (display_method == NurbsConsts.N_OUTLINE_QUAD) { + wiretris = 0; + wirequads = 1; + } else { + wiretris = 1; + wirequads = 1; + } + } +} diff --git a/src/classes/com/sun/opengl/impl/glu/nurbs/Splinespec.java b/src/classes/com/sun/opengl/impl/glu/nurbs/Splinespec.java new file mode 100755 index 000000000..35288c67d --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/nurbs/Splinespec.java @@ -0,0 +1,204 @@ +package com.sun.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 1.1 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * NURBS definition + * @author Tomas Hrasky + * + */ +public class Splinespec { + + /** + * Dimension + */ + private int dim; + + /** + * Knot vector specs + */ + private Knotspec kspec; + + /** + * Control points after conversion + */ + private CArrayOfFloats outcpts; + + /** + * Makes new Splinespec with given dimension + * @param i dimension + */ + public Splinespec(int i) { + // DONE + this.dim = i; + } + + /** + * Initializes knotspec according to knotvector + * @param knotvector basic knotvector + */ + public void kspecinit(Knotvector knotvector) { + // DONE + this.kspec = new Knotspec(); + kspec.inkbegin = new CArrayOfFloats(knotvector.knotlist, 0); + kspec.inkend = new CArrayOfFloats(knotvector.knotlist, + knotvector.knotcount); + kspec.prestride = knotvector.stride; + kspec.order = knotvector.order; + kspec.next = null; + } + + /** + * Initializes knotspec according to knotvector - SURFACE + * @param sknotvector knotvector in u dir + * @param tknotvector knotvector in v dir + */ + public void kspecinit(Knotvector sknotvector, Knotvector tknotvector) { + // DONE + this.kspec = new Knotspec(); + Knotspec tkspec = new Knotspec(); + + kspec.inkbegin = new CArrayOfFloats(sknotvector.knotlist, 0); + kspec.inkend = new CArrayOfFloats(sknotvector.knotlist, + sknotvector.knotcount); + kspec.prestride = sknotvector.stride; + kspec.order = sknotvector.order; + kspec.next = tkspec; + + tkspec.inkbegin = new CArrayOfFloats(tknotvector.knotlist, 0); + tkspec.inkend = new CArrayOfFloats(tknotvector.knotlist, + tknotvector.knotcount); + tkspec.prestride = tknotvector.stride; + tkspec.order = tknotvector.order; + tkspec.next = null; + } + + /** + * Preselect and select knotspecs + */ + public void select() { + // DONE + for (Knotspec knotspec = kspec; knotspec != null; knotspec = knotspec.next) { + knotspec.preselect(); + knotspec.select(); + } + + } + + /** + * Prepares for conversion + * @param ncoords number of coords + */ + public void layout(int ncoords) { + // DONE + int stride = ncoords; + for (Knotspec knotspec = kspec; knotspec != null; knotspec = knotspec.next) { + knotspec.poststride = stride; + stride *= (knotspec.bend.getPointer() - knotspec.bbegin + .getPointer()) + * knotspec.order + knotspec.postoffset; + knotspec.preoffset *= knotspec.prestride; + knotspec.prewidth *= knotspec.poststride; + knotspec.postwidth *= knotspec.poststride; + knotspec.postoffset *= knotspec.poststride; + knotspec.ncoords = ncoords; + } + outcpts = new CArrayOfFloats(new float[stride]); + + } + + /** + * Prepares quilt for conversion + * @param quilt quilt to work with + */ + public void setupquilt(Quilt quilt) { + // DONE + CArrayOfQuiltspecs qspec = new CArrayOfQuiltspecs(quilt.qspec); + quilt.eqspec = new CArrayOfQuiltspecs(qspec.getArray(), dim); + for (Knotspec knotspec = kspec; knotspec != null;) { + qspec.get().stride = knotspec.poststride; + qspec.get().width = knotspec.bend.getPointer() + - knotspec.bbegin.getPointer(); + qspec.get().order = knotspec.order; + qspec.get().offset = knotspec.postoffset; + qspec.get().index = 0; + qspec.get().bdry[0] = (knotspec.kleft.getPointer() == knotspec.kfirst + .getPointer()) ? 1 : 0; + qspec.get().bdry[1] = (knotspec.kright.getPointer() == knotspec.klast + .getPointer()) ? 1 : 0; + qspec.get().breakpoints = new float[qspec.get().width + 1]; + CArrayOfFloats k = new CArrayOfFloats(qspec.get().breakpoints, 0); + for (CArrayOfBreakpts bk = new CArrayOfBreakpts(knotspec.bbegin); bk + .getPointer() <= knotspec.bend.getPointer(); bk.pp()) { + k.set(bk.get().value); + k.pp(); + } + knotspec = knotspec.next; + if (knotspec != null) + qspec.pp(); + } + quilt.cpts = new CArrayOfFloats(outcpts); + quilt.next = null; + } + + /** + * Copies array of control points to output array + * @param ctlarray control points array + */ + public void copy(CArrayOfFloats ctlarray) { + // DONE + kspec.copy(ctlarray, outcpts); + + } + + /** + * Transforms knotspecs - conversion + */ + public void transform() { + // DONE + Knotspec knotspec; + outcpts.setPointer(0); + for (knotspec = kspec; knotspec != null; knotspec = knotspec.next) + knotspec.istransformed = false; + + for (knotspec = kspec; knotspec != null; knotspec = knotspec.next) { + for (Knotspec kspec2 = kspec; kspec2 != null; kspec2 = kspec2.next) + kspec2.kspectotrans = knotspec; + kspec.transform(outcpts); + knotspec.istransformed = true; + } + + } +} diff --git a/src/classes/com/sun/opengl/impl/glu/nurbs/Subdivider.java b/src/classes/com/sun/opengl/impl/glu/nurbs/Subdivider.java new file mode 100755 index 000000000..b1506d6a1 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/nurbs/Subdivider.java @@ -0,0 +1,1167 @@ +package com.sun.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 1.1 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class working with curves and surfaces + * @author Tomas Hrasky + * + */ +public class Subdivider { + /** + * Cull type + */ + public static final int CULL_TRIVIAL_REJECT = 0; + + /** + * Cull type + */ + public static final int CULL_ACCEPT = 1; + + /** + * Maximum trimming arcs + */ + private static final int MAXARCS = 10; + + /** + * Linked list of Quilts + */ + Quilt qlist; + + /** + * Object holding rendering honts information + */ + private Renderhints renderhints; + + /** + * Backend object + */ + private Backend backend; + + /** + * Number of subdivisions + */ + private int subdivisions; + + /** + * U step when using domain distance sampling + */ + private float domain_distance_u_rate; + + /** + * Use domain distance sampling + */ + private int is_domain_distance_sampling; + + /** + * Initial class holding trimming arcs + */ + private Bin initialbin; + + /** + * Not used + */ + private boolean showDegenerate; + + /** + * Is triming arc type bezier arc + */ + private boolean isArcTypeBezier; + + /** + * Breakpoints in v direction + */ + private Flist tpbrkpts; + + /** + * Breakpoints in u direction + */ + private Flist spbrkpts; + + /** + * Unused + */ + private int s_index; + + /** + * Head of linked list of trimming arcs + */ + private Arc pjarc; + + /** + * Class tesselating trimming arcs + */ + private ArcTesselator arctesselator; + + /** + * Unused + */ + private int t_index; + + /** + * Breakpoints + */ + private Flist smbrkpts; + + /** + * Not used + */ + private float[] stepsizes; + + /** + * Domain distance in V direction + */ + private float domain_distance_v_rate; + + /** + * Initializes quilt list + */ + public void beginQuilts(Backend backend) { + // DONE + qlist = null; + renderhints = new Renderhints(); + this.backend = backend; + + initialbin = new Bin(); + arctesselator = new ArcTesselator(); + } + + /** + * Adds quilt to linked list + * @param quilt added quilt + */ + public void addQuilt(Quilt quilt) { + // DONE + if (qlist == null) + qlist = quilt; + else { + quilt.next = qlist; + qlist = quilt; + } + + } + + /** + * Empty method + */ + public void endQuilts() { + // DONE + } + + /** + * Draws a surface + */ + public void drawSurfaces() { + renderhints.init(); + + if (qlist == null) { + // System.out.println("qlist is null"); + return; + } + + for (Quilt q = qlist; q != null; q = q.next) { + if (q.isCulled() == CULL_TRIVIAL_REJECT) { + freejarcs(initialbin); + return; + } + } + + float[] from = new float[2]; + float[] to = new float[2]; + + spbrkpts = new Flist(); + tpbrkpts = new Flist(); + qlist.getRange(from, to, spbrkpts, tpbrkpts); + + boolean optimize = (is_domain_distance_sampling > 0 && (renderhints.display_method != NurbsConsts.N_OUTLINE_PATCH)); + + // TODO decide whether to optimize (when there is gluNurbsProperty implemented) + optimize = true; + + if (!initialbin.isnonempty()) { + if (!optimize) { + makeBorderTrim(from, to); + } + } else { + float[] rate = new float[2]; + qlist.findRates(spbrkpts, tpbrkpts, rate); + // System.out.println("subdivider.drawsurfaces decompose"); + } + + backend.bgnsurf(renderhints.wiretris, renderhints.wirequads); + + // TODO partition test + + if (!initialbin.isnonempty() && optimize) { + + int i, j; + int num_u_steps; + int num_v_steps; + for (i = spbrkpts.start; i < spbrkpts.end - 1; i++) { + for (j = tpbrkpts.start; j < tpbrkpts.end - 1; j++) { + float[] pta = new float[2]; + float[] ptb = new float[2]; + + pta[0] = spbrkpts.pts[i]; + ptb[0] = spbrkpts.pts[i + 1]; + pta[1] = tpbrkpts.pts[j]; + ptb[1] = tpbrkpts.pts[j + 1]; + qlist.downloadAll(pta, ptb, backend); + + num_u_steps = (int) (domain_distance_u_rate * (ptb[0] - pta[0])); + num_v_steps = (int) (domain_distance_v_rate * (ptb[1] - pta[1])); + + if (num_u_steps <= 0) + num_u_steps = 1; + if (num_v_steps <= 0) + num_v_steps = 1; + + backend.surfgrid(pta[0], ptb[0], num_u_steps, ptb[1], + pta[1], num_v_steps); + backend.surfmesh(0, 0, num_u_steps, num_v_steps); + + } + } + + } else + + subdivideInS(initialbin); + + backend.endsurf(); + } + + /** + * Empty method + * @param initialbin2 + */ + private void freejarcs(Bin initialbin2) { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.freejarcs"); + } + + /** + * Subdivide in U direction + * @param source Trimming arcs source + */ + private void subdivideInS(Bin source) { + // DONE + if (renderhints.display_method == NurbsConsts.N_OUTLINE_PARAM) { + outline(source); + freejarcs(source); + } else { + setArcTypeBezier(); + setNonDegenerate(); + splitInS(source, spbrkpts.start, spbrkpts.end); + } + + } + + /** + * Split in U direction + * @param source Trimming arcs source + * @param start breakpoints start + * @param end breakpoints end + */ + private void splitInS(Bin source, int start, int end) { + // DONE + if (source.isnonempty()) { + if (start != end) { + int i = start + (end - start) / 2; + Bin left = new Bin(); + Bin right = new Bin(); + + split(source, left, right, 0, spbrkpts.pts[i]); + splitInS(left, start, i); + splitInS(right, i + 1, end); + } else { + if (start == spbrkpts.start || start == spbrkpts.end) { + freejarcs(source); + } else if (renderhints.display_method == NurbsConsts.N_OUTLINE_PARAM_S) { + outline(source); + freejarcs(source); + } else { + setArcTypeBezier(); + setNonDegenerate(); + s_index = start; + splitInT(source, tpbrkpts.start, tpbrkpts.end); + } + } + } else{ + // System.out.println("Source is empty - subdivider.splitins"); + } + } + + /** + * Split in V direction + * @param source + * @param start + * @param end + */ + private void splitInT(Bin source, int start, int end) { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.splitint"); + + if (source.isnonempty()) { + if (start != end) { + int i = start + (end - start) / 2; + Bin left = new Bin(); + Bin right = new Bin(); + split(source, left, right, 1, tpbrkpts.pts[i + 1]); + splitInT(left, start, i); + splitInT(right, i + 1, end); + } else { + if (start == tpbrkpts.start || start == tpbrkpts.end) { + freejarcs(source); + } else if (renderhints.display_method == NurbsConsts.N_OUTLINE_PARAM_ST) { + outline(source); + freejarcs(source); + } else { + t_index = start; + setArcTypeBezier(); + setDegenerate(); + + float[] pta = new float[2]; + float[] ptb = new float[2]; + + pta[0] = spbrkpts.pts[s_index - 1]; + pta[1] = tpbrkpts.pts[t_index - 1]; + + ptb[0] = spbrkpts.pts[s_index]; + ptb[1] = tpbrkpts.pts[t_index]; + qlist.downloadAll(pta, ptb, backend); + + Patchlist patchlist = new Patchlist(qlist, pta, ptb); + + samplingSplit(source, patchlist, + renderhints.maxsubdivisions, 0); + setNonDegenerate(); + setArcTypeBezier(); + } + } + } + + } + + /** + * Sample + * @param source + * @param patchlist + * @param subdivisions + * @param param + */ + private void samplingSplit(Bin source, Patchlist patchlist, + int subdivisions, int param) { + // DONE + if (!source.isnonempty()) + return; + if (patchlist.cullCheck() == CULL_TRIVIAL_REJECT) { + freejarcs(source); + return; + } + + patchlist.getstepsize(); + if (renderhints.display_method == NurbsConsts.N_OUTLINE_PATCH) { + tesselation(source, patchlist); + outline(source); + freejarcs(source); + return; + } + + tesselation(source, patchlist); + if (patchlist.needsSamplingSubdivision() && subdivisions > 0) { + if (!patchlist.needsSubdivision(0)) { + param = 1; + } else if (patchlist.needsSubdivision(1)) + param = 0; + else + param = 1 - param; + + Bin left = new Bin(); + Bin right = new Bin(); + + float mid = (float) ((patchlist.pspec[param].range[0] + patchlist.pspec[param].range[1]) * .5); + + split(source, left, right, param, mid); + Patchlist subpatchlist = new Patchlist(patchlist, param, mid); + samplingSplit(left, subpatchlist, subdivisions - 1, param); + samplingSplit(right, subpatchlist, subdivisions - 1, param); + } else { + setArcTypePwl(); + setDegenerate(); + nonSamplingSplit(source, patchlist, subdivisions, param); + setDegenerate(); + setArcTypeBezier(); + } + } + + /** + * Not used + * @param source + * @param patchlist + * @param subdivisions + * @param param + */ + private void nonSamplingSplit(Bin source, Patchlist patchlist, + int subdivisions, int param) { + // DONE + if (patchlist.needsNonSamplingSubdivision() && subdivisions > 0) { + param = 1 - param; + + Bin left = new Bin(); + Bin right = new Bin(); + + float mid = (float) ((patchlist.pspec[param].range[0] + patchlist.pspec[param].range[1]) * .5); + split(source, left, right, param, mid); + Patchlist subpatchlist = new Patchlist(patchlist, param, mid); + if (left.isnonempty()) { + if (subpatchlist.cullCheck() == CULL_TRIVIAL_REJECT) + freejarcs(left); + else + nonSamplingSplit(left, subpatchlist, subdivisions - 1, + param); + } + if (right.isnonempty()) { + if (patchlist.cullCheck() == CULL_TRIVIAL_REJECT) + freejarcs(right); + else + nonSamplingSplit(right, subpatchlist, subdivisions - 1, + param); + } + } else { + patchlist.bbox(); + backend.patch(patchlist.pspec[0].range[0], + patchlist.pspec[0].range[1], patchlist.pspec[1].range[0], + patchlist.pspec[1].range[1]); + if (renderhints.display_method == NurbsConsts.N_OUTLINE_SUBDIV) { + outline(source); + freejarcs(source); + } else { + setArcTypePwl(); + setDegenerate(); + findIrregularS(source); + monosplitInS(source, smbrkpts.start, smbrkpts.end); + } + } + + } + + /** + * Not used + * @param source + * @param start + * @param end + */ + private void monosplitInS(Bin source, int start, int end) { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.monosplitins"); + } + + /** + * Not used + * @param source + */ + private void findIrregularS(Bin source) { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.findIrregularS"); + } + + /** + * Not used + */ + private void setArcTypePwl() { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.setarctypepwl"); + } + + /** + * Not used + * @param source + * @param patchlist + */ + private void tesselation(Bin source, Patchlist patchlist) { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.tesselation"); + } + + /** + * Not used + */ + private void setDegenerate() { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.setdegenerate"); + } + + /** + * Not used + * @param bin + * @param left + * @param right + * @param param + * @param value + */ + private void split(Bin bin, Bin left, Bin right, int param, float value) { + // DONE + Bin intersections = new Bin(); + Bin unknown = new Bin(); + + partition(bin, left, intersections, right, unknown, param, value); + + int count = intersections.numarcs(); + // TODO jumpbuffer ?? + + if (count % 2 == 0) { + + Arc[] arclist = new Arc[MAXARCS]; + CArrayOfArcs list; + if (count >= MAXARCS) { + list = new CArrayOfArcs(new Arc[count]); + } else { + list = new CArrayOfArcs(arclist); + } + + CArrayOfArcs last, lptr; + Arc jarc; + + for (last = new CArrayOfArcs(list); (jarc = intersections + .removearc()) != null; last.pp()) + last.set(jarc); + + if (param == 0) {// sort into incrasing t order + ArcSdirSorter sorter = new ArcSdirSorter(this); + sorter.qsort(list, count); + + for (lptr = new CArrayOfArcs(list); lptr.getPointer() < last + .getPointer(); lptr.raisePointerBy(2)) + check_s(lptr.get(), lptr.getRelative(1)); + for (lptr = new CArrayOfArcs(list); lptr.getPointer() < last + .getPointer(); lptr.raisePointerBy(2)) + join_s(left, right, lptr.get(), lptr.getRelative(1)); + for (lptr = new CArrayOfArcs(list); lptr.getPointer() != last + .getPointer(); lptr.pp()) { + if (lptr.get().head()[0] <= value + && lptr.get().tail()[0] <= value) + left.addarc(lptr.get()); + else + right.addarc(lptr.get()); + } + + } else {// sort into decreasing s order + ArcTdirSorter sorter = new ArcTdirSorter(this); + sorter.qsort(list, count); + + for (lptr = new CArrayOfArcs(list); lptr.getPointer() < last + .getPointer(); lptr.raisePointerBy(2)) + check_t(lptr.get(), lptr.getRelative(1)); + for (lptr = new CArrayOfArcs(list); lptr.getPointer() < last + .getPointer(); lptr.raisePointerBy(2)) + join_t(left, right, lptr.get(), lptr.getRelative(1)); + for (lptr = new CArrayOfArcs(list); lptr.getPointer() != last + .getPointer(); lptr.raisePointerBy(2)) { + if (lptr.get().head()[0] <= value + && lptr.get().tail()[0] <= value) + left.addarc(lptr.get()); + else + right.addarc(lptr.get()); + } + + } + + unknown.adopt(); + } + } + + /** + * Not used + * @param left + * @param right + * @param arc + * @param relative + */ + private void join_t(Bin left, Bin right, Arc arc, Arc relative) { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.join_t"); + } + + /** + * Not used + * @param arc + * @param relative + */ + private void check_t(Arc arc, Arc relative) { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.check_t"); + } + + /** + * Not used + * @param left + * @param right + * @param jarc1 + * @param jarc2 + */ + private void join_s(Bin left, Bin right, Arc jarc1, Arc jarc2) { + // DONE + if (!jarc1.getitail()) + jarc1 = jarc1.next; + if (!jarc2.getitail()) + jarc2 = jarc2.next; + + float s = jarc1.tail()[0]; + float t1 = jarc1.tail()[1]; + float t2 = jarc2.tail()[1]; + + if (t1 == t2) { + simplelink(jarc1, jarc2); + } else { + Arc newright = new Arc(Arc.ARC_RIGHT); + Arc newleft = new Arc(Arc.ARC_LEFT); + if (isBezierArcType()) { + arctesselator.bezier(newright, s, s, t1, t2); + arctesselator.bezier(newleft, s, s, t2, t1); + } else { + arctesselator.pwl_right(newright, s, t1, t2, stepsizes[0]); + arctesselator.pwl_left(newright, s, t2, t1, stepsizes[2]); + } + link(jarc1, jarc2, newright, newleft); + left.addarc(newright); + right.addarc(newleft); + } + + } + + /** + * Not used + * @param jarc1 + * @param jarc2 + * @param newright + * @param newleft + */ + private void link(Arc jarc1, Arc jarc2, Arc newright, Arc newleft) { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.link"); + } + + /** + * Not used + * @return true + */ + private boolean isBezierArcType() { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.isbezierarc"); + return true; + } + + /** + * Not used + * @param jarc1 + * @param jarc2 + */ + private void simplelink(Arc jarc1, Arc jarc2) { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.simplelink"); + } + + /** + * Not used + * @param arc + * @param relative + */ + private void check_s(Arc arc, Arc relative) { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.check_s"); + + } + + /** + * Not used + * @param bin + * @param left + * @param intersections + * @param right + * @param unknown + * @param param + * @param value + */ + private void partition(Bin bin, Bin left, Bin intersections, Bin right, + Bin unknown, int param, float value) { + + Bin headonleft = new Bin(); + Bin headonright = new Bin(); + Bin tailonleft = new Bin(); + Bin tailonright = new Bin(); + + for (Arc jarc = bin.removearc(); jarc != null; jarc = bin.removearc()) { + float tdiff = jarc.tail()[param] - value; + float hdiff = jarc.head()[param] - value; + + if (tdiff > 0) { + if (hdiff > 0) { + right.addarc(jarc); + } else if (hdiff == 0) { + tailonright.addarc(jarc); + } else { + Arc jtemp; + switch (arc_split(jarc, param, value, 0)) { + case 2: + tailonright.addarc(jarc); + headonleft.addarc(jarc.next); + break; + // TODO rest cases + default: + System.out + .println("TODO subdivider.partition rest cases"); + break; + } + } + } else if (tdiff == 0) { + if (hdiff > 0) { + headonright.addarc(jarc); + } else if (hdiff == 0) { + unknown.addarc(jarc); + } else { + headonright.addarc(jarc); + } + } else { + if (hdiff > 0) { + // TODO rest + // System.out.println("TODO subdivider.partition rest of else"); + } else if (hdiff == 0) { + tailonleft.addarc(jarc); + } else { + left.addarc(jarc); + } + } + + } + if (param == 0) { + classify_headonleft_s(headonleft, intersections, left, value); + classify_tailonleft_s(tailonleft, intersections, left, value); + classify_headonright_s(headonright, intersections, right, value); + classify_tailonright_s(tailonright, intersections, right, value); + } else { + classify_headonleft_t(headonleft, intersections, left, value); + classify_tailonleft_t(tailonleft, intersections, left, value); + classify_headonright_t(headonright, intersections, right, value); + classify_tailonright_t(tailonright, intersections, right, value); + } + } + + /** + * Not used + * @param tailonright + * @param intersections + * @param right + * @param value + */ + private void classify_tailonright_t(Bin tailonright, Bin intersections, + Bin right, float value) { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.classify_tailonright_t"); + + } + + /** + * Not used + * @param bin + * @param in + * @param out + * @param val + */ + private void classify_tailonleft_s(Bin bin, Bin in, Bin out, float val) { + + // DONE + Arc j; + while ((j = bin.removearc()) != null) { + j.clearitail(); + + float diff = j.next.head()[0] - val; + if (diff > 0) { + in.addarc(j); + } else if (diff < 0) { + if (ccwTurn_sl(j, j.next)) + out.addarc(j); + else + in.addarc(j); + } else { + if (j.next.tail()[1] > j.next.head()[1]) + in.addarc(j); + else + out.addarc(j); + } + } + + } + + /** + * Not used + * @param bin + * @param in + * @param out + * @param val + */ + private void classify_headonright_s(Bin bin, Bin in, Bin out, float val) { + // DONE + Arc j; + while ((j = bin.removearc()) != null) { + j.setitail(); + + float diff = j.prev.tail()[0] - val; + if (diff > 0) { + if (ccwTurn_sr(j.prev, j)) + out.addarc(j); + else + in.addarc(j); + } else if (diff < 0) { + out.addarc(j); + } else { + if (j.prev.tail()[1] > j.prev.head()[1]) + out.addarc(j); + else + in.addarc(j); + } + } + } + + /** + * Not used + * @param prev + * @param j + * @return false + */ + private boolean ccwTurn_sr(Arc prev, Arc j) { + // TODO Auto-generated method stub + // System.out.println("TODO ccwTurn_sr"); + return false; + } + + /** + * Not used + * @param headonright + * @param intersections + * @param right + * @param value + */ + private void classify_headonright_t(Bin headonright, Bin intersections, + Bin right, float value) { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.classify_headonright_t"); + } + + /** + * Not used + * @param tailonleft + * @param intersections + * @param left + * @param value + */ + private void classify_tailonleft_t(Bin tailonleft, Bin intersections, + Bin left, float value) { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.classify_tailonleft_t"); + } + + /** + * Not used + * @param bin + * @param in + * @param out + * @param val + */ + private void classify_headonleft_t(Bin bin, Bin in, Bin out, float val) { + // DONE + Arc j; + while ((j = bin.removearc()) != null) { + j.setitail(); + + float diff = j.prev.tail()[1] - val; + if (diff > 0) { + out.addarc(j); + } else if (diff < 0) { + if (ccwTurn_tl(j.prev, j)) + out.addarc(j); + else + in.addarc(j); + } else { + if (j.prev.tail()[0] > j.prev.head()[0]) + out.addarc(j); + else + in.addarc(j); + } + } + } + + /** + * Not used + * @param prev + * @param j + * @return false + */ + private boolean ccwTurn_tl(Arc prev, Arc j) { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.ccwTurn_tl"); + return false; + } + + /** + * Not used + * @param bin + * @param in + * @param out + * @param val + */ + private void classify_tailonright_s(Bin bin, Bin in, Bin out, float val) { + // DONE + Arc j; + while ((j = bin.removearc()) != null) { + j.clearitail(); + + float diff = j.next.head()[0] - val; + if (diff > 0) { + if (ccwTurn_sr(j, j.next)) + out.addarc(j); + else + in.addarc(j); + } else if (diff < 0) { + in.addarc(j); + } else { + if (j.next.tail()[1] > j.next.head()[1]) + out.addarc(j); + else + in.addarc(j); + } + } + + } + + /** + * Not used + * @param bin + * @param in + * @param out + * @param val + */ + private void classify_headonleft_s(Bin bin, Bin in, Bin out, float val) { + // DONE + Arc j; + while ((j = bin.removearc()) != null) { + j.setitail(); + + float diff = j.prev.tail()[0] - val; + if (diff > 0) { + out.addarc(j); + } else if (diff < 0) { + if (ccwTurn_sl(j.prev, j)) + out.addarc(j); + else + in.addarc(j); + } else { + if (j.prev.tail()[1] > j.prev.head()[1]) + in.addarc(j); + else + out.addarc(j); + } + } + + } + + /** + * Not used + * @param prev + * @param j + * @return false + */ + private boolean ccwTurn_sl(Arc prev, Arc j) { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.ccwTurn_sl"); + return false; + } + + /** + * Not used + * @param jarc + * @param param + * @param value + * @param i + * @return 0 + */ + private int arc_split(Arc jarc, int param, float value, int i) { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.arc_split"); + return 0; + } + + /** + * Not used + */ + private void setNonDegenerate() { + // DONE + this.showDegenerate = false; + + } + + /** + * sets trimming arc default type to bezier + */ + private void setArcTypeBezier() { + // DONE + isArcTypeBezier = true; + } + + /** + * Not used + * @param source + */ + private void outline(Bin source) { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.outline"); + } + + /** + * Makes default trim along surface borders + * @param from range beginnings + * @param to range ends + */ + private void makeBorderTrim(float[] from, float[] to) { + // DONE + float smin = from[0]; + float smax = to[0]; + + float tmin = from[1]; + float tmax = to[1]; + + pjarc = null; + Arc jarc = null; + + jarc = new Arc(Arc.ARC_BOTTOM); + arctesselator.bezier(jarc, smin, smax, tmin, tmin); + initialbin.addarc(jarc); + pjarc = jarc.append(pjarc); + + jarc = new Arc(Arc.ARC_RIGHT); + arctesselator.bezier(jarc, smax, smax, tmin, tmax); + initialbin.addarc(jarc); + pjarc = jarc.append(pjarc); + + jarc = new Arc(Arc.ARC_TOP); + arctesselator.bezier(jarc, smax, smin, tmax, tmax); + initialbin.addarc(jarc); + pjarc = jarc.append(pjarc); + + jarc = new Arc(Arc.ARC_LEFT); + arctesselator.bezier(jarc, smin, smin, tmax, tmin); + initialbin.addarc(jarc); + jarc = jarc.append(pjarc); + + // assert (jarc.check() == true); + } + + /** + * Draws NURBS curve + */ + public void drawCurves() { + // DONE + float[] from = new float[1]; + float[] to = new float[1]; + + Flist bpts = new Flist(); + qlist.getRange(from, to, bpts); + + renderhints.init(); + + backend.bgncurv(); + + for (int i = bpts.start; i < bpts.end - 1; i++) { + float[] pta = new float[1]; + float[] ptb = new float[1]; + pta[0] = bpts.pts[i]; + ptb[0] = bpts.pts[i + 1]; + + qlist.downloadAll(pta, ptb, backend); + Curvelist curvelist = new Curvelist(qlist, pta, ptb); + samplingSplit(curvelist, renderhints.maxsubdivisions); + } + backend.endcurv(); + } + + /** + * Samples a curve in case of need, or sends curve to backend + * @param curvelist list of curves + * @param maxsubdivisions maximum number of subdivisions + */ + private void samplingSplit(Curvelist curvelist, int maxsubdivisions) { + if (curvelist.cullCheck() == CULL_TRIVIAL_REJECT) + return; + + curvelist.getstepsize(); + + if (curvelist.needsSamplingSubdivision() && (subdivisions > 0)) { + // TODO kód + // System.out.println("TODO subdivider-needsSamplingSubdivision"); + } else { + int nu = (int) (1 + curvelist.range[2] / curvelist.stepsize); + backend.curvgrid(curvelist.range[0], curvelist.range[1], nu); + backend.curvmesh(0, nu); + } + + } + + /** + * Sets new domain_distance_u_rate value + * @param d new domain_distance_u_rate value + + */ + public void set_domain_distance_u_rate(double d) { + // DONE + domain_distance_u_rate = (float) d; + } + + /** + * Sets new domain_distance_v_rate value + * @param d new domain_distance_v_rate value + */ + public void set_domain_distance_v_rate(double d) { + // DONE + domain_distance_v_rate = (float) d; + } + + /** + * Sets new is_domain_distance_sampling value + * @param i new is_domain_distance_sampling value + */ + public void set_is_domain_distance_sampling(int i) { + // DONE + this.is_domain_distance_sampling = i; + } +} diff --git a/src/classes/com/sun/opengl/impl/glu/nurbs/SurfaceEvaluator.java b/src/classes/com/sun/opengl/impl/glu/nurbs/SurfaceEvaluator.java new file mode 100755 index 000000000..feb3bc9a7 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/nurbs/SurfaceEvaluator.java @@ -0,0 +1,111 @@ +package com.sun.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 1.1 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class rendering surfaces with OpenGL + * @author Tomas Hrasky + * + */ +public interface SurfaceEvaluator { + + /** + * Pushes eval bit + */ + public void bgnmap2f() ; + + /** + * Sets glPolygonMode + * @param style polygon mode (N_MESHFILL/N_MESHLINE/N_MESHPOINT) + */ + public void polymode(int style) ; + + /** + * Pops all attributes + */ + public void endmap2f() ; + + /** + * Empty method + * @param ulo + * @param uhi + * @param vlo + * @param vhi + */ + public void domain2f(float ulo, float uhi, float vlo, float vhi) ; + + /** + * Defines 2D mesh + * @param nu number of steps in u direction + * @param u0 lowest u + * @param u1 highest u + * @param nv number of steps in v direction + * @param v0 lowest v + * @param v1 highest v + */ + public void mapgrid2f(int nu, float u0, float u1, int nv, float v0, float v1) ; + + /** + * Evaluates surface + * @param style surface style + * @param umin minimum U + * @param umax maximum U + * @param vmin minimum V + * @param vmax maximum V + */ + public void mapmesh2f(int style, int umin, int umax, int vmin, int vmax) ; + + /** + * Initializes evaluator + * @param type surface type + * @param ulo lowest u + * @param uhi highest u + * @param ustride number of objects between control points in u direction + * @param uorder surface order in u direction + * @param vlo lowest v + * @param vhi highest v + * @param vstride number of control points' coords + * @param vorder surface order in v direction + * @param pts control points + */ + public void map2f(int type, float ulo, float uhi, int ustride, int uorder, + float vlo, float vhi, int vstride, int vorder, CArrayOfFloats pts) ; + + /** + * Calls opengl enable + * @param type what to enable + */ + public void enable(int type) ; +} diff --git a/src/classes/com/sun/opengl/impl/glu/nurbs/TrimVertex.java b/src/classes/com/sun/opengl/impl/glu/nurbs/TrimVertex.java new file mode 100755 index 000000000..ec3f6fc10 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/nurbs/TrimVertex.java @@ -0,0 +1,56 @@ +package com.sun.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 1.1 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Holds vertex used in trim + * + * @author Tomas Hrasky + * + */ +public class TrimVertex { + + /** + * Trim vertex coords + */ + public float[] param; + + /** + * Makes new empty trim vertex + */ + public TrimVertex() { + param = new float[2]; + } +} diff --git a/src/classes/com/sun/opengl/impl/glu/registry/Registry.java b/src/classes/com/sun/opengl/impl/glu/registry/Registry.java new file mode 100644 index 000000000..f64de3a8c --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/registry/Registry.java @@ -0,0 +1,75 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 1.1 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.sun.opengl.impl.glu.registry; + +import java.util.regex.*; +import javax.media.opengl.glu.GLU; + +/** + * + * @author Administrator + */ +public class Registry { + + /** Creates a new instance of Registry */ + public Registry() { + } + + public static String gluGetString(int name) { + if( name == GLU.GLU_VERSION ) { + return( "1.3" ); + } else if( name == GLU.GLU_EXTENSIONS ) { + return( "GLU_EXT_nurbs_tessellator GLU_EXT_object_space_tess " ); + } + return( null ); + } + + public static boolean gluCheckExtension( String extName, String extString ) { + if( extName == null || extString == null ) { + return( false ); + } + return( Pattern.compile( extName + "\\b" ).matcher( extString ).find() ); + } +} diff --git a/src/classes/com/sun/opengl/impl/glu/tessellator/ActiveRegion.java b/src/classes/com/sun/opengl/impl/glu/tessellator/ActiveRegion.java new file mode 100644 index 000000000..a04c5c74b --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/tessellator/ActiveRegion.java @@ -0,0 +1,69 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 1.1 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.sun.opengl.impl.glu.tessellator; + + +class ActiveRegion { + GLUhalfEdge eUp; /* upper edge, directed right to left */ + DictNode nodeUp; /* dictionary node corresponding to eUp */ + int windingNumber; /* used to determine which regions are + * inside the polygon */ + boolean inside; /* is this region inside the polygon? */ + boolean sentinel; /* marks fake edges at t = +/-infinity */ + boolean dirty; /* marks regions where the upper or lower + * edge has changed, but we haven't checked + * whether they intersect yet */ + boolean fixUpperEdge; /* marks temporary edges introduced when + * we process a "right vertex" (one without + * any edges leaving to the right) */ +} diff --git a/src/classes/com/sun/opengl/impl/glu/tessellator/CachedVertex.java b/src/classes/com/sun/opengl/impl/glu/tessellator/CachedVertex.java new file mode 100644 index 000000000..993671c0d --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/tessellator/CachedVertex.java @@ -0,0 +1,58 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 1.1 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.sun.opengl.impl.glu.tessellator; + +class CachedVertex { + public double[] coords = new double[3]; + public Object data; +} diff --git a/src/classes/com/sun/opengl/impl/glu/tessellator/Dict.java b/src/classes/com/sun/opengl/impl/glu/tessellator/Dict.java new file mode 100644 index 000000000..d2f6e3790 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/tessellator/Dict.java @@ -0,0 +1,140 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 1.1 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.sun.opengl.impl.glu.tessellator; + +class Dict { + DictNode head; + Object frame; + DictLeq leq; + + private Dict() { + } + + static Dict dictNewDict(Object frame, DictLeq leq) { + Dict dict = new Dict(); + dict.head = new DictNode(); + + dict.head.key = null; + dict.head.next = dict.head; + dict.head.prev = dict.head; + + dict.frame = frame; + dict.leq = leq; + + return dict; + } + + static void dictDeleteDict(Dict dict) { + dict.head = null; + dict.frame = null; + dict.leq = null; + } + + static DictNode dictInsert(Dict dict, Object key) { + return dictInsertBefore(dict, dict.head, key); + } + + static DictNode dictInsertBefore(Dict dict, DictNode node, Object key) { + do { + node = node.prev; + } while (node.key != null && !dict.leq.leq(dict.frame, node.key, key)); + + DictNode newNode = new DictNode(); + newNode.key = key; + newNode.next = node.next; + node.next.prev = newNode; + newNode.prev = node; + node.next = newNode; + + return newNode; + } + + static Object dictKey(DictNode aNode) { + return aNode.key; + } + + static DictNode dictSucc(DictNode aNode) { + return aNode.next; + } + + static DictNode dictPred(DictNode aNode) { + return aNode.prev; + } + + static DictNode dictMin(Dict aDict) { + return aDict.head.next; + } + + static DictNode dictMax(Dict aDict) { + return aDict.head.prev; + } + + static void dictDelete(Dict dict, DictNode node) { + node.next.prev = node.prev; + node.prev.next = node.next; + } + + static DictNode dictSearch(Dict dict, Object key) { + DictNode node = dict.head; + + do { + node = node.next; + } while (node.key != null && !(dict.leq.leq(dict.frame, key, node.key))); + + return node; + } + + public interface DictLeq { + boolean leq(Object frame, Object key1, Object key2); + } +} diff --git a/src/classes/com/sun/opengl/impl/glu/tessellator/DictNode.java b/src/classes/com/sun/opengl/impl/glu/tessellator/DictNode.java new file mode 100644 index 000000000..1222bd948 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/tessellator/DictNode.java @@ -0,0 +1,59 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 1.1 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.sun.opengl.impl.glu.tessellator; + +class DictNode { + Object key; + DictNode next; + DictNode prev; +} diff --git a/src/classes/com/sun/opengl/impl/glu/tessellator/GLUface.java b/src/classes/com/sun/opengl/impl/glu/tessellator/GLUface.java new file mode 100644 index 000000000..f0589dbea --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/tessellator/GLUface.java @@ -0,0 +1,65 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 1.1 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.sun.opengl.impl.glu.tessellator; + +class GLUface { + public GLUface next; /* next face (never NULL) */ + public GLUface prev; /* previous face (never NULL) */ + public GLUhalfEdge anEdge; /* a half edge with this left face */ + public Object data; /* room for client's data */ + + /* Internal data (keep hidden) */ + public GLUface trail; /* "stack" for conversion to strips */ + public boolean marked; /* flag for conversion to strips */ + public boolean inside; /* this face is in the polygon interior */ +} diff --git a/src/classes/com/sun/opengl/impl/glu/tessellator/GLUhalfEdge.java b/src/classes/com/sun/opengl/impl/glu/tessellator/GLUhalfEdge.java new file mode 100644 index 000000000..1b6e81cc5 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/tessellator/GLUhalfEdge.java @@ -0,0 +1,71 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 1.1 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.sun.opengl.impl.glu.tessellator; + +class GLUhalfEdge { + public GLUhalfEdge next; /* doubly-linked list (prev==Sym->next) */ + public GLUhalfEdge Sym; /* same edge, opposite direction */ + public GLUhalfEdge Onext; /* next edge CCW around origin */ + public GLUhalfEdge Lnext; /* next edge CCW around left face */ + public GLUvertex Org; /* origin vertex (Overtex too long) */ + public com.sun.opengl.impl.glu.tessellator.GLUface Lface; /* left face */ + + /* Internal data (keep hidden) */ + public com.sun.opengl.impl.glu.tessellator.ActiveRegion activeRegion; /* a region with this upper edge (sweep.c) */ + public int winding; /* change in winding number when crossing */ + public boolean first; + + public GLUhalfEdge(boolean first) { + this.first = first; + } +} diff --git a/src/classes/com/sun/opengl/impl/glu/tessellator/GLUmesh.java b/src/classes/com/sun/opengl/impl/glu/tessellator/GLUmesh.java new file mode 100644 index 000000000..73fbe815e --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/tessellator/GLUmesh.java @@ -0,0 +1,60 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 1.1 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.sun.opengl.impl.glu.tessellator; + +class GLUmesh { + GLUvertex vHead = new GLUvertex(); /* dummy header for vertex list */ + com.sun.opengl.impl.glu.tessellator.GLUface fHead = new GLUface(); /* dummy header for face list */ + com.sun.opengl.impl.glu.tessellator.GLUhalfEdge eHead = new GLUhalfEdge(true); /* dummy header for edge list */ + com.sun.opengl.impl.glu.tessellator.GLUhalfEdge eHeadSym = new GLUhalfEdge(false); /* and its symmetric counterpart */ +} diff --git a/src/classes/com/sun/opengl/impl/glu/tessellator/GLUtessellatorImpl.java b/src/classes/com/sun/opengl/impl/glu/tessellator/GLUtessellatorImpl.java new file mode 100644 index 000000000..3a26953c8 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/tessellator/GLUtessellatorImpl.java @@ -0,0 +1,636 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 1.1 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.sun.opengl.impl.glu.tessellator; + +import com.sun.opengl.impl.glu.tessellator.*; +import javax.media.opengl.*; +import javax.media.opengl.glu.*; +import javax.media.opengl.glu.gl2.*; + +public class GLUtessellatorImpl implements GLUtessellator { + public static final int TESS_MAX_CACHE = 100; + + private int state; /* what begin/end calls have we seen? */ + + private GLUhalfEdge lastEdge; /* lastEdge->Org is the most recent vertex */ + GLUmesh mesh; /* stores the input contours, and eventually + the tessellation itself */ + + /*** state needed for projecting onto the sweep plane ***/ + + double[] normal = new double[3]; /* user-specified normal (if provided) */ + double[] sUnit = new double[3]; /* unit vector in s-direction (debugging) */ + double[] tUnit = new double[3]; /* unit vector in t-direction (debugging) */ + + /*** state needed for the line sweep ***/ + + private double relTolerance; /* tolerance for merging features */ + int windingRule; /* rule for determining polygon interior */ + boolean fatalError; /* fatal error: needed combine callback */ + + Dict dict; /* edge dictionary for sweep line */ + PriorityQ pq; /* priority queue of vertex events */ + GLUvertex event; /* current sweep event being processed */ + + /*** state needed for rendering callbacks (see render.c) ***/ + + boolean flagBoundary; /* mark boundary edges (use EdgeFlag) */ + boolean boundaryOnly; /* Extract contours, not triangles */ + GLUface lonelyTriList; + /* list of triangles which could not be rendered as strips or fans */ + + + + /*** state needed to cache single-contour polygons for renderCache() */ + + private boolean flushCacheOnNextVertex; /* empty cache on next vertex() call */ + int cacheCount; /* number of cached vertices */ + CachedVertex[] cache = new CachedVertex[TESS_MAX_CACHE]; /* the vertex data */ + + /*** rendering callbacks that also pass polygon data ***/ + private Object polygonData; /* client data for current polygon */ + + private GLUtessellatorCallback callBegin; + private GLUtessellatorCallback callEdgeFlag; + private GLUtessellatorCallback callVertex; + private GLUtessellatorCallback callEnd; +// private GLUtessellatorCallback callMesh; + private GLUtessellatorCallback callError; + private GLUtessellatorCallback callCombine; + + private GLUtessellatorCallback callBeginData; + private GLUtessellatorCallback callEdgeFlagData; + private GLUtessellatorCallback callVertexData; + private GLUtessellatorCallback callEndData; +// private GLUtessellatorCallback callMeshData; + private GLUtessellatorCallback callErrorData; + private GLUtessellatorCallback callCombineData; + + private static final double GLU_TESS_DEFAULT_TOLERANCE = 0.0; +// private static final int GLU_TESS_MESH = 100112; /* void (*)(GLUmesh *mesh) */ + private static GLUtessellatorCallback NULL_CB = new GLUtessellatorCallbackAdapter(); + +// #define MAX_FAST_ALLOC (MAX(sizeof(EdgePair), \ +// MAX(sizeof(GLUvertex),sizeof(GLUface)))) + + private GLUtessellatorImpl() { + state = TessState.T_DORMANT; + + normal[0] = 0; + normal[1] = 0; + normal[2] = 0; + + relTolerance = GLU_TESS_DEFAULT_TOLERANCE; + windingRule = GLU.GLU_TESS_WINDING_ODD; + flagBoundary = false; + boundaryOnly = false; + + callBegin = NULL_CB; + callEdgeFlag = NULL_CB; + callVertex = NULL_CB; + callEnd = NULL_CB; + callError = NULL_CB; + callCombine = NULL_CB; +// callMesh = NULL_CB; + + callBeginData = NULL_CB; + callEdgeFlagData = NULL_CB; + callVertexData = NULL_CB; + callEndData = NULL_CB; + callErrorData = NULL_CB; + callCombineData = NULL_CB; + + polygonData = null; + + for (int i = 0; i < cache.length; i++) { + cache[i] = new CachedVertex(); + } + } + + static public GLUtessellator gluNewTess() + { + return new GLUtessellatorImpl(); + } + + + private void makeDormant() { + /* Return the tessellator to its original dormant state. */ + + if (mesh != null) { + Mesh.__gl_meshDeleteMesh(mesh); + } + state = TessState.T_DORMANT; + lastEdge = null; + mesh = null; + } + + private void requireState(int newState) { + if (state != newState) gotoState(newState); + } + + private void gotoState(int newState) { + while (state != newState) { + /* We change the current state one level at a time, to get to + * the desired state. + */ + if (state < newState) { + if (state == TessState.T_DORMANT) { + callErrorOrErrorData(GLU.GLU_TESS_MISSING_BEGIN_POLYGON); + gluTessBeginPolygon(null); + } else if (state == TessState.T_IN_POLYGON) { + callErrorOrErrorData(GLU.GLU_TESS_MISSING_BEGIN_CONTOUR); + gluTessBeginContour(); + } + } else { + if (state == TessState.T_IN_CONTOUR) { + callErrorOrErrorData(GLU.GLU_TESS_MISSING_END_CONTOUR); + gluTessEndContour(); + } else if (state == TessState.T_IN_POLYGON) { + callErrorOrErrorData(GLU.GLU_TESS_MISSING_END_POLYGON); + /* gluTessEndPolygon( tess ) is too much work! */ + makeDormant(); + } + } + } + } + + public void gluDeleteTess() { + requireState(TessState.T_DORMANT); + } + + public void gluTessProperty(int which, double value) { + switch (which) { + case GLU.GLU_TESS_TOLERANCE: + if (value < 0.0 || value > 1.0) break; + relTolerance = value; + return; + + case GLU.GLU_TESS_WINDING_RULE: + int windingRule = (int) value; + if (windingRule != value) break; /* not an integer */ + + switch (windingRule) { + case GLU.GLU_TESS_WINDING_ODD: + case GLU.GLU_TESS_WINDING_NONZERO: + case GLU.GLU_TESS_WINDING_POSITIVE: + case GLU.GLU_TESS_WINDING_NEGATIVE: + case GLU.GLU_TESS_WINDING_ABS_GEQ_TWO: + this.windingRule = windingRule; + return; + default: + break; + } + + case GLU.GLU_TESS_BOUNDARY_ONLY: + boundaryOnly = (value != 0); + return; + + default: + callErrorOrErrorData(GLU.GLU_INVALID_ENUM); + return; + } + callErrorOrErrorData(GLU.GLU_INVALID_VALUE); + } + +/* Returns tessellator property */ + public void gluGetTessProperty(int which, double[] value, int value_offset) { + switch (which) { + case GLU.GLU_TESS_TOLERANCE: +/* tolerance should be in range [0..1] */ + assert (0.0 <= relTolerance && relTolerance <= 1.0); + value[value_offset] = relTolerance; + break; + case GLU.GLU_TESS_WINDING_RULE: + assert (windingRule == GLU.GLU_TESS_WINDING_ODD || + windingRule == GLU.GLU_TESS_WINDING_NONZERO || + windingRule == GLU.GLU_TESS_WINDING_POSITIVE || + windingRule == GLU.GLU_TESS_WINDING_NEGATIVE || + windingRule == GLU.GLU_TESS_WINDING_ABS_GEQ_TWO); + value[value_offset] = windingRule; + break; + case GLU.GLU_TESS_BOUNDARY_ONLY: + assert (boundaryOnly == true || boundaryOnly == false); + value[value_offset] = boundaryOnly ? 1 : 0; + break; + default: + value[value_offset] = 0.0; + callErrorOrErrorData(GLU.GLU_INVALID_ENUM); + break; + } + } /* gluGetTessProperty() */ + + public void gluTessNormal(double x, double y, double z) { + normal[0] = x; + normal[1] = y; + normal[2] = z; + } + + public void gluTessCallback(int which, GLUtessellatorCallback aCallback) { + switch (which) { + case GLU.GLU_TESS_BEGIN: + callBegin = aCallback == null ? NULL_CB : aCallback; + return; + case GLU.GLU_TESS_BEGIN_DATA: + callBeginData = aCallback == null ? NULL_CB : aCallback; + return; + case GLU.GLU_TESS_EDGE_FLAG: + callEdgeFlag = aCallback == null ? NULL_CB : aCallback; +/* If the client wants boundary edges to be flagged, + * we render everything as separate triangles (no strips or fans). + */ + flagBoundary = aCallback != null; + return; + case GLU.GLU_TESS_EDGE_FLAG_DATA: + callEdgeFlagData = callBegin = aCallback == null ? NULL_CB : aCallback; +/* If the client wants boundary edges to be flagged, + * we render everything as separate triangles (no strips or fans). + */ + flagBoundary = (aCallback != null); + return; + case GLU.GLU_TESS_VERTEX: + callVertex = aCallback == null ? NULL_CB : aCallback; + return; + case GLU.GLU_TESS_VERTEX_DATA: + callVertexData = aCallback == null ? NULL_CB : aCallback; + return; + case GLU.GLU_TESS_END: + callEnd = aCallback == null ? NULL_CB : aCallback; + return; + case GLU.GLU_TESS_END_DATA: + callEndData = aCallback == null ? NULL_CB : aCallback; + return; + case GLU.GLU_TESS_ERROR: + callError = aCallback == null ? NULL_CB : aCallback; + return; + case GLU.GLU_TESS_ERROR_DATA: + callErrorData = aCallback == null ? NULL_CB : aCallback; + return; + case GLU.GLU_TESS_COMBINE: + callCombine = aCallback == null ? NULL_CB : aCallback; + return; + case GLU.GLU_TESS_COMBINE_DATA: + callCombineData = aCallback == null ? NULL_CB : aCallback; + return; +// case GLU_TESS_MESH: +// callMesh = aCallback == null ? NULL_CB : aCallback; +// return; + default: + callErrorOrErrorData(GLU.GLU_INVALID_ENUM); + return; + } + } + + private boolean addVertex(double[] coords, Object vertexData) { + GLUhalfEdge e; + + e = lastEdge; + if (e == null) { +/* Make a self-loop (one vertex, one edge). */ + + e = Mesh.__gl_meshMakeEdge(mesh); + if (e == null) return false; + if (!Mesh.__gl_meshSplice(e, e.Sym)) return false; + } else { +/* Create a new vertex and edge which immediately follow e + * in the ordering around the left face. + */ + if (Mesh.__gl_meshSplitEdge(e) == null) return false; + e = e.Lnext; + } + +/* The new vertex is now e.Org. */ + e.Org.data = vertexData; + e.Org.coords[0] = coords[0]; + e.Org.coords[1] = coords[1]; + e.Org.coords[2] = coords[2]; + +/* The winding of an edge says how the winding number changes as we + * cross from the edge''s right face to its left face. We add the + * vertices in such an order that a CCW contour will add +1 to + * the winding number of the region inside the contour. + */ + e.winding = 1; + e.Sym.winding = -1; + + lastEdge = e; + + return true; + } + + private void cacheVertex(double[] coords, Object vertexData) { + if (cache[cacheCount] == null) { + cache[cacheCount] = new CachedVertex(); + } + + CachedVertex v = cache[cacheCount]; + + v.data = vertexData; + v.coords[0] = coords[0]; + v.coords[1] = coords[1]; + v.coords[2] = coords[2]; + ++cacheCount; + } + + + private boolean flushCache() { + CachedVertex[] v = cache; + + mesh = Mesh.__gl_meshNewMesh(); + if (mesh == null) return false; + + for (int i = 0; i < cacheCount; i++) { + CachedVertex vertex = v[i]; + if (!addVertex(vertex.coords, vertex.data)) return false; + } + cacheCount = 0; + flushCacheOnNextVertex = false; + + return true; + } + + public void gluTessVertex(double[] coords, int coords_offset, Object vertexData) { + int i; + boolean tooLarge = false; + double x; + double[] clamped = new double[3]; + + requireState(TessState.T_IN_CONTOUR); + + if (flushCacheOnNextVertex) { + if (!flushCache()) { + callErrorOrErrorData(GLU.GLU_OUT_OF_MEMORY); + return; + } + lastEdge = null; + } + for (i = 0; i < 3; ++i) { + x = coords[i+coords_offset]; + if (x < -GLU.GLU_TESS_MAX_COORD) { + x = -GLU.GLU_TESS_MAX_COORD; + tooLarge = true; + } + if (x > GLU.GLU_TESS_MAX_COORD) { + x = GLU.GLU_TESS_MAX_COORD; + tooLarge = true; + } + clamped[i] = x; + } + if (tooLarge) { + callErrorOrErrorData(GLU.GLU_TESS_COORD_TOO_LARGE); + } + + if (mesh == null) { + if (cacheCount < TESS_MAX_CACHE) { + cacheVertex(clamped, vertexData); + return; + } + if (!flushCache()) { + callErrorOrErrorData(GLU.GLU_OUT_OF_MEMORY); + return; + } + } + + if (!addVertex(clamped, vertexData)) { + callErrorOrErrorData(GLU.GLU_OUT_OF_MEMORY); + } + } + + + public void gluTessBeginPolygon(Object data) { + requireState(TessState.T_DORMANT); + + state = TessState.T_IN_POLYGON; + cacheCount = 0; + flushCacheOnNextVertex = false; + mesh = null; + + polygonData = data; + } + + + public void gluTessBeginContour() { + requireState(TessState.T_IN_POLYGON); + + state = TessState.T_IN_CONTOUR; + lastEdge = null; + if (cacheCount > 0) { +/* Just set a flag so we don't get confused by empty contours + * -- these can be generated accidentally with the obsolete + * NextContour() interface. + */ + flushCacheOnNextVertex = true; + } + } + + + public void gluTessEndContour() { + requireState(TessState.T_IN_CONTOUR); + state = TessState.T_IN_POLYGON; + } + + public void gluTessEndPolygon() { + GLUmesh mesh; + + try { + requireState(TessState.T_IN_POLYGON); + state = TessState.T_DORMANT; + + if (this.mesh == null) { + if (!flagBoundary /*&& callMesh == NULL_CB*/) { + +/* Try some special code to make the easy cases go quickly + * (eg. convex polygons). This code does NOT handle multiple contours, + * intersections, edge flags, and of course it does not generate + * an explicit mesh either. + */ + if (Render.__gl_renderCache(this)) { + polygonData = null; + return; + } + } + if (!flushCache()) throw new RuntimeException(); /* could've used a label*/ + } + +/* Determine the polygon normal and project vertices onto the plane + * of the polygon. + */ + Normal.__gl_projectPolygon(this); + +/* __gl_computeInterior( tess ) computes the planar arrangement specified + * by the given contours, and further subdivides this arrangement + * into regions. Each region is marked "inside" if it belongs + * to the polygon, according to the rule given by windingRule. + * Each interior region is guaranteed be monotone. + */ + if (!Sweep.__gl_computeInterior(this)) { + throw new RuntimeException(); /* could've used a label */ + } + + mesh = this.mesh; + if (!fatalError) { + boolean rc = true; + +/* If the user wants only the boundary contours, we throw away all edges + * except those which separate the interior from the exterior. + * Otherwise we tessellate all the regions marked "inside". + */ + if (boundaryOnly) { + rc = TessMono.__gl_meshSetWindingNumber(mesh, 1, true); + } else { + rc = TessMono.__gl_meshTessellateInterior(mesh); + } + if (!rc) throw new RuntimeException(); /* could've used a label */ + + Mesh.__gl_meshCheckMesh(mesh); + + if (callBegin != NULL_CB || callEnd != NULL_CB + || callVertex != NULL_CB || callEdgeFlag != NULL_CB + || callBeginData != NULL_CB + || callEndData != NULL_CB + || callVertexData != NULL_CB + || callEdgeFlagData != NULL_CB) { + if (boundaryOnly) { + Render.__gl_renderBoundary(this, mesh); /* output boundary contours */ + } else { + Render.__gl_renderMesh(this, mesh); /* output strips and fans */ + } + } +// if (callMesh != NULL_CB) { +// +///* Throw away the exterior faces, so that all faces are interior. +// * This way the user doesn't have to check the "inside" flag, +// * and we don't need to even reveal its existence. It also leaves +// * the freedom for an implementation to not generate the exterior +// * faces in the first place. +// */ +// TessMono.__gl_meshDiscardExterior(mesh); +// callMesh.mesh(mesh); /* user wants the mesh itself */ +// mesh = null; +// polygonData = null; +// return; +// } + } + Mesh.__gl_meshDeleteMesh(mesh); + polygonData = null; + mesh = null; + } catch (Exception e) { + e.printStackTrace(); + callErrorOrErrorData(GLU.GLU_OUT_OF_MEMORY); + } + } + + /*******************************************************/ + +/* Obsolete calls -- for backward compatibility */ + + public void gluBeginPolygon() { + gluTessBeginPolygon(null); + gluTessBeginContour(); + } + + +/*ARGSUSED*/ + public void gluNextContour(int type) { + gluTessEndContour(); + gluTessBeginContour(); + } + + + public void gluEndPolygon() { + gluTessEndContour(); + gluTessEndPolygon(); + } + + void callBeginOrBeginData(int a) { + if (callBeginData != NULL_CB) + callBeginData.beginData(a, polygonData); + else + callBegin.begin(a); + } + + void callVertexOrVertexData(Object a) { + if (callVertexData != NULL_CB) + callVertexData.vertexData(a, polygonData); + else + callVertex.vertex(a); + } + + void callEdgeFlagOrEdgeFlagData(boolean a) { + if (callEdgeFlagData != NULL_CB) + callEdgeFlagData.edgeFlagData(a, polygonData); + else + callEdgeFlag.edgeFlag(a); + } + + void callEndOrEndData() { + if (callEndData != NULL_CB) + callEndData.endData(polygonData); + else + callEnd.end(); + } + + void callCombineOrCombineData(double[] coords, Object[] vertexData, float[] weights, Object[] outData) { + if (callCombineData != NULL_CB) + callCombineData.combineData(coords, vertexData, weights, outData, polygonData); + else + callCombine.combine(coords, vertexData, weights, outData); + } + + void callErrorOrErrorData(int a) { + if (callErrorData != NULL_CB) + callErrorData.errorData(a, polygonData); + else + callError.error(a); + } + +} diff --git a/src/classes/com/sun/opengl/impl/glu/tessellator/GLUvertex.java b/src/classes/com/sun/opengl/impl/glu/tessellator/GLUvertex.java new file mode 100644 index 000000000..e97767a12 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/tessellator/GLUvertex.java @@ -0,0 +1,65 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 1.1 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.sun.opengl.impl.glu.tessellator; + +class GLUvertex { + public GLUvertex next; /* next vertex (never NULL) */ + public GLUvertex prev; /* previous vertex (never NULL) */ + public com.sun.opengl.impl.glu.tessellator.GLUhalfEdge anEdge; /* a half-edge with this origin */ + public Object data; /* client's data */ + + /* Internal data (keep hidden) */ + public double[] coords = new double[3]; /* vertex location in 3D */ + public double s, t; /* projection onto the sweep plane */ + public int pqHandle; /* to allow deletion from priority queue */ +} diff --git a/src/classes/com/sun/opengl/impl/glu/tessellator/Geom.java b/src/classes/com/sun/opengl/impl/glu/tessellator/Geom.java new file mode 100644 index 000000000..6b31cc30e --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/tessellator/Geom.java @@ -0,0 +1,318 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 1.1 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.sun.opengl.impl.glu.tessellator; + +class Geom { + private Geom() { + } + + /* Given three vertices u,v,w such that VertLeq(u,v) && VertLeq(v,w), + * evaluates the t-coord of the edge uw at the s-coord of the vertex v. + * Returns v->t - (uw)(v->s), ie. the signed distance from uw to v. + * If uw is vertical (and thus passes thru v), the result is zero. + * + * The calculation is extremely accurate and stable, even when v + * is very close to u or w. In particular if we set v->t = 0 and + * let r be the negated result (this evaluates (uw)(v->s)), then + * r is guaranteed to satisfy MIN(u->t,w->t) <= r <= MAX(u->t,w->t). + */ + static double EdgeEval(GLUvertex u, GLUvertex v, GLUvertex w) { + double gapL, gapR; + + assert (VertLeq(u, v) && VertLeq(v, w)); + + gapL = v.s - u.s; + gapR = w.s - v.s; + + if (gapL + gapR > 0) { + if (gapL < gapR) { + return (v.t - u.t) + (u.t - w.t) * (gapL / (gapL + gapR)); + } else { + return (v.t - w.t) + (w.t - u.t) * (gapR / (gapL + gapR)); + } + } + /* vertical line */ + return 0; + } + + static double EdgeSign(GLUvertex u, GLUvertex v, GLUvertex w) { + double gapL, gapR; + + assert (VertLeq(u, v) && VertLeq(v, w)); + + gapL = v.s - u.s; + gapR = w.s - v.s; + + if (gapL + gapR > 0) { + return (v.t - w.t) * gapL + (v.t - u.t) * gapR; + } + /* vertical line */ + return 0; + } + + + /*********************************************************************** + * Define versions of EdgeSign, EdgeEval with s and t transposed. + */ + + static double TransEval(GLUvertex u, GLUvertex v, GLUvertex w) { + /* Given three vertices u,v,w such that TransLeq(u,v) && TransLeq(v,w), + * evaluates the t-coord of the edge uw at the s-coord of the vertex v. + * Returns v->s - (uw)(v->t), ie. the signed distance from uw to v. + * If uw is vertical (and thus passes thru v), the result is zero. + * + * The calculation is extremely accurate and stable, even when v + * is very close to u or w. In particular if we set v->s = 0 and + * let r be the negated result (this evaluates (uw)(v->t)), then + * r is guaranteed to satisfy MIN(u->s,w->s) <= r <= MAX(u->s,w->s). + */ + double gapL, gapR; + + assert (TransLeq(u, v) && TransLeq(v, w)); + + gapL = v.t - u.t; + gapR = w.t - v.t; + + if (gapL + gapR > 0) { + if (gapL < gapR) { + return (v.s - u.s) + (u.s - w.s) * (gapL / (gapL + gapR)); + } else { + return (v.s - w.s) + (w.s - u.s) * (gapR / (gapL + gapR)); + } + } + /* vertical line */ + return 0; + } + + static double TransSign(GLUvertex u, GLUvertex v, GLUvertex w) { + /* Returns a number whose sign matches TransEval(u,v,w) but which + * is cheaper to evaluate. Returns > 0, == 0 , or < 0 + * as v is above, on, or below the edge uw. + */ + double gapL, gapR; + + assert (TransLeq(u, v) && TransLeq(v, w)); + + gapL = v.t - u.t; + gapR = w.t - v.t; + + if (gapL + gapR > 0) { + return (v.s - w.s) * gapL + (v.s - u.s) * gapR; + } + /* vertical line */ + return 0; + } + + + static boolean VertCCW(GLUvertex u, GLUvertex v, GLUvertex w) { + /* For almost-degenerate situations, the results are not reliable. + * Unless the floating-point arithmetic can be performed without + * rounding errors, *any* implementation will give incorrect results + * on some degenerate inputs, so the client must have some way to + * handle this situation. + */ + return (u.s * (v.t - w.t) + v.s * (w.t - u.t) + w.s * (u.t - v.t)) >= 0; + } + +/* Given parameters a,x,b,y returns the value (b*x+a*y)/(a+b), + * or (x+y)/2 if a==b==0. It requires that a,b >= 0, and enforces + * this in the rare case that one argument is slightly negative. + * The implementation is extremely stable numerically. + * In particular it guarantees that the result r satisfies + * MIN(x,y) <= r <= MAX(x,y), and the results are very accurate + * even when a and b differ greatly in magnitude. + */ + static double Interpolate(double a, double x, double b, double y) { + a = (a < 0) ? 0 : a; + b = (b < 0) ? 0 : b; + if (a <= b) { + if (b == 0) { + return (x + y) / 2.0; + } else { + return (x + (y - x) * (a / (a + b))); + } + } else { + return (y + (x - y) * (b / (a + b))); + } + } + + static void EdgeIntersect(GLUvertex o1, GLUvertex d1, + GLUvertex o2, GLUvertex d2, + GLUvertex v) +/* Given edges (o1,d1) and (o2,d2), compute their point of intersection. + * The computed point is guaranteed to lie in the intersection of the + * bounding rectangles defined by each edge. + */ { + double z1, z2; + + /* This is certainly not the most efficient way to find the intersection + * of two line segments, but it is very numerically stable. + * + * Strategy: find the two middle vertices in the VertLeq ordering, + * and interpolate the intersection s-value from these. Then repeat + * using the TransLeq ordering to find the intersection t-value. + */ + + if (!VertLeq(o1, d1)) { + GLUvertex temp = o1; + o1 = d1; + d1 = temp; + } + if (!VertLeq(o2, d2)) { + GLUvertex temp = o2; + o2 = d2; + d2 = temp; + } + if (!VertLeq(o1, o2)) { + GLUvertex temp = o1; + o1 = o2; + o2 = temp; + temp = d1; + d1 = d2; + d2 = temp; + } + + if (!VertLeq(o2, d1)) { + /* Technically, no intersection -- do our best */ + v.s = (o2.s + d1.s) / 2.0; + } else if (VertLeq(d1, d2)) { + /* Interpolate between o2 and d1 */ + z1 = EdgeEval(o1, o2, d1); + z2 = EdgeEval(o2, d1, d2); + if (z1 + z2 < 0) { + z1 = -z1; + z2 = -z2; + } + v.s = Interpolate(z1, o2.s, z2, d1.s); + } else { + /* Interpolate between o2 and d2 */ + z1 = EdgeSign(o1, o2, d1); + z2 = -EdgeSign(o1, d2, d1); + if (z1 + z2 < 0) { + z1 = -z1; + z2 = -z2; + } + v.s = Interpolate(z1, o2.s, z2, d2.s); + } + + /* Now repeat the process for t */ + + if (!TransLeq(o1, d1)) { + GLUvertex temp = o1; + o1 = d1; + d1 = temp; + } + if (!TransLeq(o2, d2)) { + GLUvertex temp = o2; + o2 = d2; + d2 = temp; + } + if (!TransLeq(o1, o2)) { + GLUvertex temp = o2; + o2 = o1; + o1 = temp; + temp = d2; + d2 = d1; + d1 = temp; + } + + if (!TransLeq(o2, d1)) { + /* Technically, no intersection -- do our best */ + v.t = (o2.t + d1.t) / 2.0; + } else if (TransLeq(d1, d2)) { + /* Interpolate between o2 and d1 */ + z1 = TransEval(o1, o2, d1); + z2 = TransEval(o2, d1, d2); + if (z1 + z2 < 0) { + z1 = -z1; + z2 = -z2; + } + v.t = Interpolate(z1, o2.t, z2, d1.t); + } else { + /* Interpolate between o2 and d2 */ + z1 = TransSign(o1, o2, d1); + z2 = -TransSign(o1, d2, d1); + if (z1 + z2 < 0) { + z1 = -z1; + z2 = -z2; + } + v.t = Interpolate(z1, o2.t, z2, d2.t); + } + } + + static boolean VertEq(GLUvertex u, GLUvertex v) { + return u.s == v.s && u.t == v.t; + } + + static boolean VertLeq(GLUvertex u, GLUvertex v) { + return u.s < v.s || (u.s == v.s && u.t <= v.t); + } + +/* Versions of VertLeq, EdgeSign, EdgeEval with s and t transposed. */ + + static boolean TransLeq(GLUvertex u, GLUvertex v) { + return u.t < v.t || (u.t == v.t && u.s <= v.s); + } + + static boolean EdgeGoesLeft(GLUhalfEdge e) { + return VertLeq(e.Sym.Org, e.Org); + } + + static boolean EdgeGoesRight(GLUhalfEdge e) { + return VertLeq(e.Org, e.Sym.Org); + } + + static double VertL1dist(GLUvertex u, GLUvertex v) { + return Math.abs(u.s - v.s) + Math.abs(u.t - v.t); + } +} diff --git a/src/classes/com/sun/opengl/impl/glu/tessellator/Mesh.java b/src/classes/com/sun/opengl/impl/glu/tessellator/Mesh.java new file mode 100644 index 000000000..290fb1037 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/tessellator/Mesh.java @@ -0,0 +1,734 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 1.1 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.sun.opengl.impl.glu.tessellator; + +class Mesh { + private Mesh() { + } + + /************************ Utility Routines ************************/ +/* MakeEdge creates a new pair of half-edges which form their own loop. + * No vertex or face structures are allocated, but these must be assigned + * before the current edge operation is completed. + */ + static com.sun.opengl.impl.glu.tessellator.GLUhalfEdge MakeEdge(com.sun.opengl.impl.glu.tessellator.GLUhalfEdge eNext) { + com.sun.opengl.impl.glu.tessellator.GLUhalfEdge e; + com.sun.opengl.impl.glu.tessellator.GLUhalfEdge eSym; + com.sun.opengl.impl.glu.tessellator.GLUhalfEdge ePrev; + +// EdgePair * pair = (EdgePair *) +// memAlloc(sizeof(EdgePair)); +// if (pair == NULL) return NULL; +// +// e = &pair - > e; + e = new com.sun.opengl.impl.glu.tessellator.GLUhalfEdge(true); +// eSym = &pair - > eSym; + eSym = new com.sun.opengl.impl.glu.tessellator.GLUhalfEdge(false); + + + /* Make sure eNext points to the first edge of the edge pair */ + if (!eNext.first) { + eNext = eNext.Sym; + } + + /* Insert in circular doubly-linked list before eNext. + * Note that the prev pointer is stored in Sym->next. + */ + ePrev = eNext.Sym.next; + eSym.next = ePrev; + ePrev.Sym.next = e; + e.next = eNext; + eNext.Sym.next = eSym; + + e.Sym = eSym; + e.Onext = e; + e.Lnext = eSym; + e.Org = null; + e.Lface = null; + e.winding = 0; + e.activeRegion = null; + + eSym.Sym = e; + eSym.Onext = eSym; + eSym.Lnext = e; + eSym.Org = null; + eSym.Lface = null; + eSym.winding = 0; + eSym.activeRegion = null; + + return e; + } + +/* Splice( a, b ) is best described by the Guibas/Stolfi paper or the + * CS348a notes (see mesh.h). Basically it modifies the mesh so that + * a->Onext and b->Onext are exchanged. This can have various effects + * depending on whether a and b belong to different face or vertex rings. + * For more explanation see __gl_meshSplice() below. + */ + static void Splice(com.sun.opengl.impl.glu.tessellator.GLUhalfEdge a, com.sun.opengl.impl.glu.tessellator.GLUhalfEdge b) { + com.sun.opengl.impl.glu.tessellator.GLUhalfEdge aOnext = a.Onext; + com.sun.opengl.impl.glu.tessellator.GLUhalfEdge bOnext = b.Onext; + + aOnext.Sym.Lnext = b; + bOnext.Sym.Lnext = a; + a.Onext = bOnext; + b.Onext = aOnext; + } + +/* MakeVertex( newVertex, eOrig, vNext ) attaches a new vertex and makes it the + * origin of all edges in the vertex loop to which eOrig belongs. "vNext" gives + * a place to insert the new vertex in the global vertex list. We insert + * the new vertex *before* vNext so that algorithms which walk the vertex + * list will not see the newly created vertices. + */ + static void MakeVertex(com.sun.opengl.impl.glu.tessellator.GLUvertex newVertex, + com.sun.opengl.impl.glu.tessellator.GLUhalfEdge eOrig, com.sun.opengl.impl.glu.tessellator.GLUvertex vNext) { + com.sun.opengl.impl.glu.tessellator.GLUhalfEdge e; + com.sun.opengl.impl.glu.tessellator.GLUvertex vPrev; + com.sun.opengl.impl.glu.tessellator.GLUvertex vNew = newVertex; + + assert (vNew != null); + + /* insert in circular doubly-linked list before vNext */ + vPrev = vNext.prev; + vNew.prev = vPrev; + vPrev.next = vNew; + vNew.next = vNext; + vNext.prev = vNew; + + vNew.anEdge = eOrig; + vNew.data = null; + /* leave coords, s, t undefined */ + + /* fix other edges on this vertex loop */ + e = eOrig; + do { + e.Org = vNew; + e = e.Onext; + } while (e != eOrig); + } + +/* MakeFace( newFace, eOrig, fNext ) attaches a new face and makes it the left + * face of all edges in the face loop to which eOrig belongs. "fNext" gives + * a place to insert the new face in the global face list. We insert + * the new face *before* fNext so that algorithms which walk the face + * list will not see the newly created faces. + */ + static void MakeFace(com.sun.opengl.impl.glu.tessellator.GLUface newFace, com.sun.opengl.impl.glu.tessellator.GLUhalfEdge eOrig, com.sun.opengl.impl.glu.tessellator.GLUface fNext) { + com.sun.opengl.impl.glu.tessellator.GLUhalfEdge e; + com.sun.opengl.impl.glu.tessellator.GLUface fPrev; + com.sun.opengl.impl.glu.tessellator.GLUface fNew = newFace; + + assert (fNew != null); + + /* insert in circular doubly-linked list before fNext */ + fPrev = fNext.prev; + fNew.prev = fPrev; + fPrev.next = fNew; + fNew.next = fNext; + fNext.prev = fNew; + + fNew.anEdge = eOrig; + fNew.data = null; + fNew.trail = null; + fNew.marked = false; + + /* The new face is marked "inside" if the old one was. This is a + * convenience for the common case where a face has been split in two. + */ + fNew.inside = fNext.inside; + + /* fix other edges on this face loop */ + e = eOrig; + do { + e.Lface = fNew; + e = e.Lnext; + } while (e != eOrig); + } + +/* KillEdge( eDel ) destroys an edge (the half-edges eDel and eDel->Sym), + * and removes from the global edge list. + */ + static void KillEdge(com.sun.opengl.impl.glu.tessellator.GLUhalfEdge eDel) { + com.sun.opengl.impl.glu.tessellator.GLUhalfEdge ePrev, eNext; + + /* Half-edges are allocated in pairs, see EdgePair above */ + if (!eDel.first) { + eDel = eDel.Sym; + } + + /* delete from circular doubly-linked list */ + eNext = eDel.next; + ePrev = eDel.Sym.next; + eNext.Sym.next = ePrev; + ePrev.Sym.next = eNext; + } + + +/* KillVertex( vDel ) destroys a vertex and removes it from the global + * vertex list. It updates the vertex loop to point to a given new vertex. + */ + static void KillVertex(com.sun.opengl.impl.glu.tessellator.GLUvertex vDel, com.sun.opengl.impl.glu.tessellator.GLUvertex newOrg) { + com.sun.opengl.impl.glu.tessellator.GLUhalfEdge e, eStart = vDel.anEdge; + com.sun.opengl.impl.glu.tessellator.GLUvertex vPrev, vNext; + + /* change the origin of all affected edges */ + e = eStart; + do { + e.Org = newOrg; + e = e.Onext; + } while (e != eStart); + + /* delete from circular doubly-linked list */ + vPrev = vDel.prev; + vNext = vDel.next; + vNext.prev = vPrev; + vPrev.next = vNext; + } + +/* KillFace( fDel ) destroys a face and removes it from the global face + * list. It updates the face loop to point to a given new face. + */ + static void KillFace(com.sun.opengl.impl.glu.tessellator.GLUface fDel, com.sun.opengl.impl.glu.tessellator.GLUface newLface) { + com.sun.opengl.impl.glu.tessellator.GLUhalfEdge e, eStart = fDel.anEdge; + com.sun.opengl.impl.glu.tessellator.GLUface fPrev, fNext; + + /* change the left face of all affected edges */ + e = eStart; + do { + e.Lface = newLface; + e = e.Lnext; + } while (e != eStart); + + /* delete from circular doubly-linked list */ + fPrev = fDel.prev; + fNext = fDel.next; + fNext.prev = fPrev; + fPrev.next = fNext; + } + + + /****************** Basic Edge Operations **********************/ + +/* __gl_meshMakeEdge creates one edge, two vertices, and a loop (face). + * The loop consists of the two new half-edges. + */ + public static com.sun.opengl.impl.glu.tessellator.GLUhalfEdge __gl_meshMakeEdge(com.sun.opengl.impl.glu.tessellator.GLUmesh mesh) { + com.sun.opengl.impl.glu.tessellator.GLUvertex newVertex1 = new com.sun.opengl.impl.glu.tessellator.GLUvertex(); + com.sun.opengl.impl.glu.tessellator.GLUvertex newVertex2 = new com.sun.opengl.impl.glu.tessellator.GLUvertex(); + com.sun.opengl.impl.glu.tessellator.GLUface newFace = new com.sun.opengl.impl.glu.tessellator.GLUface(); + com.sun.opengl.impl.glu.tessellator.GLUhalfEdge e; + + e = MakeEdge(mesh.eHead); + if (e == null) return null; + + MakeVertex(newVertex1, e, mesh.vHead); + MakeVertex(newVertex2, e.Sym, mesh.vHead); + MakeFace(newFace, e, mesh.fHead); + return e; + } + + +/* __gl_meshSplice( eOrg, eDst ) is the basic operation for changing the + * mesh connectivity and topology. It changes the mesh so that + * eOrg->Onext <- OLD( eDst->Onext ) + * eDst->Onext <- OLD( eOrg->Onext ) + * where OLD(...) means the value before the meshSplice operation. + * + * This can have two effects on the vertex structure: + * - if eOrg->Org != eDst->Org, the two vertices are merged together + * - if eOrg->Org == eDst->Org, the origin is split into two vertices + * In both cases, eDst->Org is changed and eOrg->Org is untouched. + * + * Similarly (and independently) for the face structure, + * - if eOrg->Lface == eDst->Lface, one loop is split into two + * - if eOrg->Lface != eDst->Lface, two distinct loops are joined into one + * In both cases, eDst->Lface is changed and eOrg->Lface is unaffected. + * + * Some special cases: + * If eDst == eOrg, the operation has no effect. + * If eDst == eOrg->Lnext, the new face will have a single edge. + * If eDst == eOrg->Lprev, the old face will have a single edge. + * If eDst == eOrg->Onext, the new vertex will have a single edge. + * If eDst == eOrg->Oprev, the old vertex will have a single edge. + */ + public static boolean __gl_meshSplice(com.sun.opengl.impl.glu.tessellator.GLUhalfEdge eOrg, com.sun.opengl.impl.glu.tessellator.GLUhalfEdge eDst) { + boolean joiningLoops = false; + boolean joiningVertices = false; + + if (eOrg == eDst) return true; + + if (eDst.Org != eOrg.Org) { + /* We are merging two disjoint vertices -- destroy eDst->Org */ + joiningVertices = true; + KillVertex(eDst.Org, eOrg.Org); + } + if (eDst.Lface != eOrg.Lface) { + /* We are connecting two disjoint loops -- destroy eDst.Lface */ + joiningLoops = true; + KillFace(eDst.Lface, eOrg.Lface); + } + + /* Change the edge structure */ + Splice(eDst, eOrg); + + if (!joiningVertices) { + com.sun.opengl.impl.glu.tessellator.GLUvertex newVertex = new com.sun.opengl.impl.glu.tessellator.GLUvertex(); + + /* We split one vertex into two -- the new vertex is eDst.Org. + * Make sure the old vertex points to a valid half-edge. + */ + MakeVertex(newVertex, eDst, eOrg.Org); + eOrg.Org.anEdge = eOrg; + } + if (!joiningLoops) { + com.sun.opengl.impl.glu.tessellator.GLUface newFace = new com.sun.opengl.impl.glu.tessellator.GLUface(); + + /* We split one loop into two -- the new loop is eDst.Lface. + * Make sure the old face points to a valid half-edge. + */ + MakeFace(newFace, eDst, eOrg.Lface); + eOrg.Lface.anEdge = eOrg; + } + + return true; + } + + +/* __gl_meshDelete( eDel ) removes the edge eDel. There are several cases: + * if (eDel.Lface != eDel.Rface), we join two loops into one; the loop + * eDel.Lface is deleted. Otherwise, we are splitting one loop into two; + * the newly created loop will contain eDel.Dst. If the deletion of eDel + * would create isolated vertices, those are deleted as well. + * + * This function could be implemented as two calls to __gl_meshSplice + * plus a few calls to memFree, but this would allocate and delete + * unnecessary vertices and faces. + */ + static boolean __gl_meshDelete(com.sun.opengl.impl.glu.tessellator.GLUhalfEdge eDel) { + com.sun.opengl.impl.glu.tessellator.GLUhalfEdge eDelSym = eDel.Sym; + boolean joiningLoops = false; + + /* First step: disconnect the origin vertex eDel.Org. We make all + * changes to get a consistent mesh in this "intermediate" state. + */ + if (eDel.Lface != eDel.Sym.Lface) { + /* We are joining two loops into one -- remove the left face */ + joiningLoops = true; + KillFace(eDel.Lface, eDel.Sym.Lface); + } + + if (eDel.Onext == eDel) { + KillVertex(eDel.Org, null); + } else { + /* Make sure that eDel.Org and eDel.Sym.Lface point to valid half-edges */ + eDel.Sym.Lface.anEdge = eDel.Sym.Lnext; + eDel.Org.anEdge = eDel.Onext; + + Splice(eDel, eDel.Sym.Lnext); + if (!joiningLoops) { + com.sun.opengl.impl.glu.tessellator.GLUface newFace = new com.sun.opengl.impl.glu.tessellator.GLUface(); + + /* We are splitting one loop into two -- create a new loop for eDel. */ + MakeFace(newFace, eDel, eDel.Lface); + } + } + + /* Claim: the mesh is now in a consistent state, except that eDel.Org + * may have been deleted. Now we disconnect eDel.Dst. + */ + if (eDelSym.Onext == eDelSym) { + KillVertex(eDelSym.Org, null); + KillFace(eDelSym.Lface, null); + } else { + /* Make sure that eDel.Dst and eDel.Lface point to valid half-edges */ + eDel.Lface.anEdge = eDelSym.Sym.Lnext; + eDelSym.Org.anEdge = eDelSym.Onext; + Splice(eDelSym, eDelSym.Sym.Lnext); + } + + /* Any isolated vertices or faces have already been freed. */ + KillEdge(eDel); + + return true; + } + + + /******************** Other Edge Operations **********************/ + +/* All these routines can be implemented with the basic edge + * operations above. They are provided for convenience and efficiency. + */ + + +/* __gl_meshAddEdgeVertex( eOrg ) creates a new edge eNew such that + * eNew == eOrg.Lnext, and eNew.Dst is a newly created vertex. + * eOrg and eNew will have the same left face. + */ + static com.sun.opengl.impl.glu.tessellator.GLUhalfEdge __gl_meshAddEdgeVertex(com.sun.opengl.impl.glu.tessellator.GLUhalfEdge eOrg) { + com.sun.opengl.impl.glu.tessellator.GLUhalfEdge eNewSym; + com.sun.opengl.impl.glu.tessellator.GLUhalfEdge eNew = MakeEdge(eOrg); + + eNewSym = eNew.Sym; + + /* Connect the new edge appropriately */ + Splice(eNew, eOrg.Lnext); + + /* Set the vertex and face information */ + eNew.Org = eOrg.Sym.Org; + { + com.sun.opengl.impl.glu.tessellator.GLUvertex newVertex = new com.sun.opengl.impl.glu.tessellator.GLUvertex(); + + MakeVertex(newVertex, eNewSym, eNew.Org); + } + eNew.Lface = eNewSym.Lface = eOrg.Lface; + + return eNew; + } + + +/* __gl_meshSplitEdge( eOrg ) splits eOrg into two edges eOrg and eNew, + * such that eNew == eOrg.Lnext. The new vertex is eOrg.Sym.Org == eNew.Org. + * eOrg and eNew will have the same left face. + */ + public static com.sun.opengl.impl.glu.tessellator.GLUhalfEdge __gl_meshSplitEdge(com.sun.opengl.impl.glu.tessellator.GLUhalfEdge eOrg) { + com.sun.opengl.impl.glu.tessellator.GLUhalfEdge eNew; + com.sun.opengl.impl.glu.tessellator.GLUhalfEdge tempHalfEdge = __gl_meshAddEdgeVertex(eOrg); + + eNew = tempHalfEdge.Sym; + + /* Disconnect eOrg from eOrg.Sym.Org and connect it to eNew.Org */ + Splice(eOrg.Sym, eOrg.Sym.Sym.Lnext); + Splice(eOrg.Sym, eNew); + + /* Set the vertex and face information */ + eOrg.Sym.Org = eNew.Org; + eNew.Sym.Org.anEdge = eNew.Sym; /* may have pointed to eOrg.Sym */ + eNew.Sym.Lface = eOrg.Sym.Lface; + eNew.winding = eOrg.winding; /* copy old winding information */ + eNew.Sym.winding = eOrg.Sym.winding; + + return eNew; + } + + +/* __gl_meshConnect( eOrg, eDst ) creates a new edge from eOrg.Sym.Org + * to eDst.Org, and returns the corresponding half-edge eNew. + * If eOrg.Lface == eDst.Lface, this splits one loop into two, + * and the newly created loop is eNew.Lface. Otherwise, two disjoint + * loops are merged into one, and the loop eDst.Lface is destroyed. + * + * If (eOrg == eDst), the new face will have only two edges. + * If (eOrg.Lnext == eDst), the old face is reduced to a single edge. + * If (eOrg.Lnext.Lnext == eDst), the old face is reduced to two edges. + */ + static com.sun.opengl.impl.glu.tessellator.GLUhalfEdge __gl_meshConnect(com.sun.opengl.impl.glu.tessellator.GLUhalfEdge eOrg, com.sun.opengl.impl.glu.tessellator.GLUhalfEdge eDst) { + com.sun.opengl.impl.glu.tessellator.GLUhalfEdge eNewSym; + boolean joiningLoops = false; + com.sun.opengl.impl.glu.tessellator.GLUhalfEdge eNew = MakeEdge(eOrg); + + eNewSym = eNew.Sym; + + if (eDst.Lface != eOrg.Lface) { + /* We are connecting two disjoint loops -- destroy eDst.Lface */ + joiningLoops = true; + KillFace(eDst.Lface, eOrg.Lface); + } + + /* Connect the new edge appropriately */ + Splice(eNew, eOrg.Lnext); + Splice(eNewSym, eDst); + + /* Set the vertex and face information */ + eNew.Org = eOrg.Sym.Org; + eNewSym.Org = eDst.Org; + eNew.Lface = eNewSym.Lface = eOrg.Lface; + + /* Make sure the old face points to a valid half-edge */ + eOrg.Lface.anEdge = eNewSym; + + if (!joiningLoops) { + com.sun.opengl.impl.glu.tessellator.GLUface newFace = new com.sun.opengl.impl.glu.tessellator.GLUface(); + + /* We split one loop into two -- the new loop is eNew.Lface */ + MakeFace(newFace, eNew, eOrg.Lface); + } + return eNew; + } + + + /******************** Other Operations **********************/ + +/* __gl_meshZapFace( fZap ) destroys a face and removes it from the + * global face list. All edges of fZap will have a null pointer as their + * left face. Any edges which also have a null pointer as their right face + * are deleted entirely (along with any isolated vertices this produces). + * An entire mesh can be deleted by zapping its faces, one at a time, + * in any order. Zapped faces cannot be used in further mesh operations! + */ + static void __gl_meshZapFace(com.sun.opengl.impl.glu.tessellator.GLUface fZap) { + com.sun.opengl.impl.glu.tessellator.GLUhalfEdge eStart = fZap.anEdge; + com.sun.opengl.impl.glu.tessellator.GLUhalfEdge e, eNext, eSym; + com.sun.opengl.impl.glu.tessellator.GLUface fPrev, fNext; + + /* walk around face, deleting edges whose right face is also null */ + eNext = eStart.Lnext; + do { + e = eNext; + eNext = e.Lnext; + + e.Lface = null; + if (e.Sym.Lface == null) { + /* delete the edge -- see __gl_MeshDelete above */ + + if (e.Onext == e) { + KillVertex(e.Org, null); + } else { + /* Make sure that e.Org points to a valid half-edge */ + e.Org.anEdge = e.Onext; + Splice(e, e.Sym.Lnext); + } + eSym = e.Sym; + if (eSym.Onext == eSym) { + KillVertex(eSym.Org, null); + } else { + /* Make sure that eSym.Org points to a valid half-edge */ + eSym.Org.anEdge = eSym.Onext; + Splice(eSym, eSym.Sym.Lnext); + } + KillEdge(e); + } + } while (e != eStart); + + /* delete from circular doubly-linked list */ + fPrev = fZap.prev; + fNext = fZap.next; + fNext.prev = fPrev; + fPrev.next = fNext; + } + + +/* __gl_meshNewMesh() creates a new mesh with no edges, no vertices, + * and no loops (what we usually call a "face"). + */ + public static com.sun.opengl.impl.glu.tessellator.GLUmesh __gl_meshNewMesh() { + com.sun.opengl.impl.glu.tessellator.GLUvertex v; + com.sun.opengl.impl.glu.tessellator.GLUface f; + com.sun.opengl.impl.glu.tessellator.GLUhalfEdge e; + com.sun.opengl.impl.glu.tessellator.GLUhalfEdge eSym; + com.sun.opengl.impl.glu.tessellator.GLUmesh mesh = new com.sun.opengl.impl.glu.tessellator.GLUmesh(); + + v = mesh.vHead; + f = mesh.fHead; + e = mesh.eHead; + eSym = mesh.eHeadSym; + + v.next = v.prev = v; + v.anEdge = null; + v.data = null; + + f.next = f.prev = f; + f.anEdge = null; + f.data = null; + f.trail = null; + f.marked = false; + f.inside = false; + + e.next = e; + e.Sym = eSym; + e.Onext = null; + e.Lnext = null; + e.Org = null; + e.Lface = null; + e.winding = 0; + e.activeRegion = null; + + eSym.next = eSym; + eSym.Sym = e; + eSym.Onext = null; + eSym.Lnext = null; + eSym.Org = null; + eSym.Lface = null; + eSym.winding = 0; + eSym.activeRegion = null; + + return mesh; + } + + +/* __gl_meshUnion( mesh1, mesh2 ) forms the union of all structures in + * both meshes, and returns the new mesh (the old meshes are destroyed). + */ + static com.sun.opengl.impl.glu.tessellator.GLUmesh __gl_meshUnion(com.sun.opengl.impl.glu.tessellator.GLUmesh mesh1, com.sun.opengl.impl.glu.tessellator.GLUmesh mesh2) { + com.sun.opengl.impl.glu.tessellator.GLUface f1 = mesh1.fHead; + com.sun.opengl.impl.glu.tessellator.GLUvertex v1 = mesh1.vHead; + com.sun.opengl.impl.glu.tessellator.GLUhalfEdge e1 = mesh1.eHead; + com.sun.opengl.impl.glu.tessellator.GLUface f2 = mesh2.fHead; + com.sun.opengl.impl.glu.tessellator.GLUvertex v2 = mesh2.vHead; + com.sun.opengl.impl.glu.tessellator.GLUhalfEdge e2 = mesh2.eHead; + + /* Add the faces, vertices, and edges of mesh2 to those of mesh1 */ + if (f2.next != f2) { + f1.prev.next = f2.next; + f2.next.prev = f1.prev; + f2.prev.next = f1; + f1.prev = f2.prev; + } + + if (v2.next != v2) { + v1.prev.next = v2.next; + v2.next.prev = v1.prev; + v2.prev.next = v1; + v1.prev = v2.prev; + } + + if (e2.next != e2) { + e1.Sym.next.Sym.next = e2.next; + e2.next.Sym.next = e1.Sym.next; + e2.Sym.next.Sym.next = e1; + e1.Sym.next = e2.Sym.next; + } + + return mesh1; + } + + +/* __gl_meshDeleteMesh( mesh ) will free all storage for any valid mesh. + */ + static void __gl_meshDeleteMeshZap(com.sun.opengl.impl.glu.tessellator.GLUmesh mesh) { + com.sun.opengl.impl.glu.tessellator.GLUface fHead = mesh.fHead; + + while (fHead.next != fHead) { + __gl_meshZapFace(fHead.next); + } + assert (mesh.vHead.next == mesh.vHead); + } + +/* __gl_meshDeleteMesh( mesh ) will free all storage for any valid mesh. + */ + public static void __gl_meshDeleteMesh(com.sun.opengl.impl.glu.tessellator.GLUmesh mesh) { + com.sun.opengl.impl.glu.tessellator.GLUface f, fNext; + com.sun.opengl.impl.glu.tessellator.GLUvertex v, vNext; + com.sun.opengl.impl.glu.tessellator.GLUhalfEdge e, eNext; + + for (f = mesh.fHead.next; f != mesh.fHead; f = fNext) { + fNext = f.next; + } + + for (v = mesh.vHead.next; v != mesh.vHead; v = vNext) { + vNext = v.next; + } + + for (e = mesh.eHead.next; e != mesh.eHead; e = eNext) { + /* One call frees both e and e.Sym (see EdgePair above) */ + eNext = e.next; + } + } + +/* __gl_meshCheckMesh( mesh ) checks a mesh for self-consistency. + */ + public static void __gl_meshCheckMesh(com.sun.opengl.impl.glu.tessellator.GLUmesh mesh) { + com.sun.opengl.impl.glu.tessellator.GLUface fHead = mesh.fHead; + com.sun.opengl.impl.glu.tessellator.GLUvertex vHead = mesh.vHead; + com.sun.opengl.impl.glu.tessellator.GLUhalfEdge eHead = mesh.eHead; + com.sun.opengl.impl.glu.tessellator.GLUface f, fPrev; + com.sun.opengl.impl.glu.tessellator.GLUvertex v, vPrev; + com.sun.opengl.impl.glu.tessellator.GLUhalfEdge e, ePrev; + + fPrev = fHead; + for (fPrev = fHead; (f = fPrev.next) != fHead; fPrev = f) { + assert (f.prev == fPrev); + e = f.anEdge; + do { + assert (e.Sym != e); + assert (e.Sym.Sym == e); + assert (e.Lnext.Onext.Sym == e); + assert (e.Onext.Sym.Lnext == e); + assert (e.Lface == f); + e = e.Lnext; + } while (e != f.anEdge); + } + assert (f.prev == fPrev && f.anEdge == null && f.data == null); + + vPrev = vHead; + for (vPrev = vHead; (v = vPrev.next) != vHead; vPrev = v) { + assert (v.prev == vPrev); + e = v.anEdge; + do { + assert (e.Sym != e); + assert (e.Sym.Sym == e); + assert (e.Lnext.Onext.Sym == e); + assert (e.Onext.Sym.Lnext == e); + assert (e.Org == v); + e = e.Onext; + } while (e != v.anEdge); + } + assert (v.prev == vPrev && v.anEdge == null && v.data == null); + + ePrev = eHead; + for (ePrev = eHead; (e = ePrev.next) != eHead; ePrev = e) { + assert (e.Sym.next == ePrev.Sym); + assert (e.Sym != e); + assert (e.Sym.Sym == e); + assert (e.Org != null); + assert (e.Sym.Org != null); + assert (e.Lnext.Onext.Sym == e); + assert (e.Onext.Sym.Lnext == e); + } + assert (e.Sym.next == ePrev.Sym + && e.Sym == mesh.eHeadSym + && e.Sym.Sym == e + && e.Org == null && e.Sym.Org == null + && e.Lface == null && e.Sym.Lface == null); + } +} diff --git a/src/classes/com/sun/opengl/impl/glu/tessellator/Normal.java b/src/classes/com/sun/opengl/impl/glu/tessellator/Normal.java new file mode 100644 index 000000000..feb13dfd4 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/tessellator/Normal.java @@ -0,0 +1,288 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 1.1 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.sun.opengl.impl.glu.tessellator; + +import javax.media.opengl.*; +import javax.media.opengl.glu.*; + +class Normal { + private Normal() { + } + + static boolean SLANTED_SWEEP = false; + static double S_UNIT_X; /* Pre-normalized */ + static double S_UNIT_Y; + private static final boolean TRUE_PROJECT = false; + + static { + if (SLANTED_SWEEP) { +/* The "feature merging" is not intended to be complete. There are + * special cases where edges are nearly parallel to the sweep line + * which are not implemented. The algorithm should still behave + * robustly (ie. produce a reasonable tesselation) in the presence + * of such edges, however it may miss features which could have been + * merged. We could minimize this effect by choosing the sweep line + * direction to be something unusual (ie. not parallel to one of the + * coordinate axes). + */ + S_UNIT_X = 0.50941539564955385; /* Pre-normalized */ + S_UNIT_Y = 0.86052074622010633; + } else { + S_UNIT_X = 1.0; + S_UNIT_Y = 0.0; + } + } + + private static double Dot(double[] u, double[] v) { + return (u[0] * v[0] + u[1] * v[1] + u[2] * v[2]); + } + + static void Normalize(double[] v) { + double len = v[0] * v[0] + v[1] * v[1] + v[2] * v[2]; + + assert (len > 0); + len = Math.sqrt(len); + v[0] /= len; + v[1] /= len; + v[2] /= len; + } + + static int LongAxis(double[] v) { + int i = 0; + + if (Math.abs(v[1]) > Math.abs(v[0])) { + i = 1; + } + if (Math.abs(v[2]) > Math.abs(v[i])) { + i = 2; + } + return i; + } + + static void ComputeNormal(GLUtessellatorImpl tess, double[] norm) { + com.sun.opengl.impl.glu.tessellator.GLUvertex v, v1, v2; + double c, tLen2, maxLen2; + double[] maxVal, minVal, d1, d2, tNorm; + com.sun.opengl.impl.glu.tessellator.GLUvertex[] maxVert, minVert; + com.sun.opengl.impl.glu.tessellator.GLUvertex vHead = tess.mesh.vHead; + int i; + + maxVal = new double[3]; + minVal = new double[3]; + minVert = new com.sun.opengl.impl.glu.tessellator.GLUvertex[3]; + maxVert = new com.sun.opengl.impl.glu.tessellator.GLUvertex[3]; + d1 = new double[3]; + d2 = new double[3]; + tNorm = new double[3]; + + maxVal[0] = maxVal[1] = maxVal[2] = -2 * GLU.GLU_TESS_MAX_COORD; + minVal[0] = minVal[1] = minVal[2] = 2 * GLU.GLU_TESS_MAX_COORD; + + for (v = vHead.next; v != vHead; v = v.next) { + for (i = 0; i < 3; ++i) { + c = v.coords[i]; + if (c < minVal[i]) { + minVal[i] = c; + minVert[i] = v; + } + if (c > maxVal[i]) { + maxVal[i] = c; + maxVert[i] = v; + } + } + } + +/* Find two vertices separated by at least 1/sqrt(3) of the maximum + * distance between any two vertices + */ + i = 0; + if (maxVal[1] - minVal[1] > maxVal[0] - minVal[0]) { + i = 1; + } + if (maxVal[2] - minVal[2] > maxVal[i] - minVal[i]) { + i = 2; + } + if (minVal[i] >= maxVal[i]) { +/* All vertices are the same -- normal doesn't matter */ + norm[0] = 0; + norm[1] = 0; + norm[2] = 1; + return; + } + +/* Look for a third vertex which forms the triangle with maximum area + * (Length of normal == twice the triangle area) + */ + maxLen2 = 0; + v1 = minVert[i]; + v2 = maxVert[i]; + d1[0] = v1.coords[0] - v2.coords[0]; + d1[1] = v1.coords[1] - v2.coords[1]; + d1[2] = v1.coords[2] - v2.coords[2]; + for (v = vHead.next; v != vHead; v = v.next) { + d2[0] = v.coords[0] - v2.coords[0]; + d2[1] = v.coords[1] - v2.coords[1]; + d2[2] = v.coords[2] - v2.coords[2]; + tNorm[0] = d1[1] * d2[2] - d1[2] * d2[1]; + tNorm[1] = d1[2] * d2[0] - d1[0] * d2[2]; + tNorm[2] = d1[0] * d2[1] - d1[1] * d2[0]; + tLen2 = tNorm[0] * tNorm[0] + tNorm[1] * tNorm[1] + tNorm[2] * tNorm[2]; + if (tLen2 > maxLen2) { + maxLen2 = tLen2; + norm[0] = tNorm[0]; + norm[1] = tNorm[1]; + norm[2] = tNorm[2]; + } + } + + if (maxLen2 <= 0) { +/* All points lie on a single line -- any decent normal will do */ + norm[0] = norm[1] = norm[2] = 0; + norm[LongAxis(d1)] = 1; + } + } + + static void CheckOrientation(GLUtessellatorImpl tess) { + double area; + com.sun.opengl.impl.glu.tessellator.GLUface f, fHead = tess.mesh.fHead; + com.sun.opengl.impl.glu.tessellator.GLUvertex v, vHead = tess.mesh.vHead; + com.sun.opengl.impl.glu.tessellator.GLUhalfEdge e; + +/* When we compute the normal automatically, we choose the orientation + * so that the the sum of the signed areas of all contours is non-negative. + */ + area = 0; + for (f = fHead.next; f != fHead; f = f.next) { + e = f.anEdge; + if (e.winding <= 0) continue; + do { + area += (e.Org.s - e.Sym.Org.s) * (e.Org.t + e.Sym.Org.t); + e = e.Lnext; + } while (e != f.anEdge); + } + if (area < 0) { +/* Reverse the orientation by flipping all the t-coordinates */ + for (v = vHead.next; v != vHead; v = v.next) { + v.t = -v.t; + } + tess.tUnit[0] = -tess.tUnit[0]; + tess.tUnit[1] = -tess.tUnit[1]; + tess.tUnit[2] = -tess.tUnit[2]; + } + } + +/* Determine the polygon normal and project vertices onto the plane + * of the polygon. + */ + public static void __gl_projectPolygon(GLUtessellatorImpl tess) { + com.sun.opengl.impl.glu.tessellator.GLUvertex v, vHead = tess.mesh.vHead; + double w; + double[] norm = new double[3]; + double[] sUnit, tUnit; + int i; + boolean computedNormal = false; + + norm[0] = tess.normal[0]; + norm[1] = tess.normal[1]; + norm[2] = tess.normal[2]; + if (norm[0] == 0 && norm[1] == 0 && norm[2] == 0) { + ComputeNormal(tess, norm); + computedNormal = true; + } + sUnit = tess.sUnit; + tUnit = tess.tUnit; + i = LongAxis(norm); + + if (TRUE_PROJECT) { +/* Choose the initial sUnit vector to be approximately perpendicular + * to the normal. + */ + Normalize(norm); + + sUnit[i] = 0; + sUnit[(i + 1) % 3] = S_UNIT_X; + sUnit[(i + 2) % 3] = S_UNIT_Y; + +/* Now make it exactly perpendicular */ + w = Dot(sUnit, norm); + sUnit[0] -= w * norm[0]; + sUnit[1] -= w * norm[1]; + sUnit[2] -= w * norm[2]; + Normalize(sUnit); + +/* Choose tUnit so that (sUnit,tUnit,norm) form a right-handed frame */ + tUnit[0] = norm[1] * sUnit[2] - norm[2] * sUnit[1]; + tUnit[1] = norm[2] * sUnit[0] - norm[0] * sUnit[2]; + tUnit[2] = norm[0] * sUnit[1] - norm[1] * sUnit[0]; + Normalize(tUnit); + } else { +/* Project perpendicular to a coordinate axis -- better numerically */ + sUnit[i] = 0; + sUnit[(i + 1) % 3] = S_UNIT_X; + sUnit[(i + 2) % 3] = S_UNIT_Y; + + tUnit[i] = 0; + tUnit[(i + 1) % 3] = (norm[i] > 0) ? -S_UNIT_Y : S_UNIT_Y; + tUnit[(i + 2) % 3] = (norm[i] > 0) ? S_UNIT_X : -S_UNIT_X; + } + +/* Project the vertices onto the sweep plane */ + for (v = vHead.next; v != vHead; v = v.next) { + v.s = Dot(v.coords, sUnit); + v.t = Dot(v.coords, tUnit); + } + if (computedNormal) { + CheckOrientation(tess); + } + } +} diff --git a/src/classes/com/sun/opengl/impl/glu/tessellator/PriorityQ.java b/src/classes/com/sun/opengl/impl/glu/tessellator/PriorityQ.java new file mode 100644 index 000000000..18f2cf32c --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/tessellator/PriorityQ.java @@ -0,0 +1,100 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 1.1 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.sun.opengl.impl.glu.tessellator; + +abstract class PriorityQ { + public static final int INIT_SIZE = 32; + + public static class PQnode { + int handle; + } + + public static class PQhandleElem { + Object key; + int node; + } + + public static interface Leq { + boolean leq(Object key1, Object key2); + } + + // #ifdef FOR_TRITE_TEST_PROGRAM +// private static boolean LEQ(PriorityQCommon.Leq leq, Object x,Object y) { +// return pq.leq.leq(x,y); +// } +// #else +/* Violates modularity, but a little faster */ +// #include "geom.h" + public static boolean LEQ(Leq leq, Object x, Object y) { + return com.sun.opengl.impl.glu.tessellator.Geom.VertLeq((com.sun.opengl.impl.glu.tessellator.GLUvertex) x, (com.sun.opengl.impl.glu.tessellator.GLUvertex) y); + } + + static PriorityQ pqNewPriorityQ(Leq leq) { + return new PriorityQSort(leq); + } + + abstract void pqDeletePriorityQ(); + + abstract boolean pqInit(); + + abstract int pqInsert(Object keyNew); + + abstract Object pqExtractMin(); + + abstract void pqDelete(int hCurr); + + abstract Object pqMinimum(); + + abstract boolean pqIsEmpty(); +// #endif +} diff --git a/src/classes/com/sun/opengl/impl/glu/tessellator/PriorityQHeap.java b/src/classes/com/sun/opengl/impl/glu/tessellator/PriorityQHeap.java new file mode 100644 index 000000000..2f856517a --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/tessellator/PriorityQHeap.java @@ -0,0 +1,262 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 1.1 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.sun.opengl.impl.glu.tessellator; + +class PriorityQHeap extends com.sun.opengl.impl.glu.tessellator.PriorityQ { + com.sun.opengl.impl.glu.tessellator.PriorityQ.PQnode[] nodes; + com.sun.opengl.impl.glu.tessellator.PriorityQ.PQhandleElem[] handles; + int size, max; + int freeList; + boolean initialized; + com.sun.opengl.impl.glu.tessellator.PriorityQ.Leq leq; + +/* really __gl_pqHeapNewPriorityQ */ + public PriorityQHeap(com.sun.opengl.impl.glu.tessellator.PriorityQ.Leq leq) { + size = 0; + max = com.sun.opengl.impl.glu.tessellator.PriorityQ.INIT_SIZE; + nodes = new com.sun.opengl.impl.glu.tessellator.PriorityQ.PQnode[com.sun.opengl.impl.glu.tessellator.PriorityQ.INIT_SIZE + 1]; + for (int i = 0; i < nodes.length; i++) { + nodes[i] = new PQnode(); + } + handles = new com.sun.opengl.impl.glu.tessellator.PriorityQ.PQhandleElem[com.sun.opengl.impl.glu.tessellator.PriorityQ.INIT_SIZE + 1]; + for (int i = 0; i < handles.length; i++) { + handles[i] = new PQhandleElem(); + } + initialized = false; + freeList = 0; + this.leq = leq; + + nodes[1].handle = 1; /* so that Minimum() returns NULL */ + handles[1].key = null; + } + +/* really __gl_pqHeapDeletePriorityQ */ + void pqDeletePriorityQ() { + handles = null; + nodes = null; + } + + void FloatDown(int curr) { + com.sun.opengl.impl.glu.tessellator.PriorityQ.PQnode[] n = nodes; + com.sun.opengl.impl.glu.tessellator.PriorityQ.PQhandleElem[] h = handles; + int hCurr, hChild; + int child; + + hCurr = n[curr].handle; + for (; ;) { + child = curr << 1; + if (child < size && LEQ(leq, h[n[child + 1].handle].key, + h[n[child].handle].key)) { + ++child; + } + + assert (child <= max); + + hChild = n[child].handle; + if (child > size || LEQ(leq, h[hCurr].key, h[hChild].key)) { + n[curr].handle = hCurr; + h[hCurr].node = curr; + break; + } + n[curr].handle = hChild; + h[hChild].node = curr; + curr = child; + } + } + + + void FloatUp(int curr) { + com.sun.opengl.impl.glu.tessellator.PriorityQ.PQnode[] n = nodes; + com.sun.opengl.impl.glu.tessellator.PriorityQ.PQhandleElem[] h = handles; + int hCurr, hParent; + int parent; + + hCurr = n[curr].handle; + for (; ;) { + parent = curr >> 1; + hParent = n[parent].handle; + if (parent == 0 || LEQ(leq, h[hParent].key, h[hCurr].key)) { + n[curr].handle = hCurr; + h[hCurr].node = curr; + break; + } + n[curr].handle = hParent; + h[hParent].node = curr; + curr = parent; + } + } + +/* really __gl_pqHeapInit */ + boolean pqInit() { + int i; + + /* This method of building a heap is O(n), rather than O(n lg n). */ + + for (i = size; i >= 1; --i) { + FloatDown(i); + } + initialized = true; + + return true; + } + +/* really __gl_pqHeapInsert */ +/* returns LONG_MAX iff out of memory */ + int pqInsert(Object keyNew) { + int curr; + int free; + + curr = ++size; + if ((curr * 2) > max) { + com.sun.opengl.impl.glu.tessellator.PriorityQ.PQnode[] saveNodes = nodes; + com.sun.opengl.impl.glu.tessellator.PriorityQ.PQhandleElem[] saveHandles = handles; + + /* If the heap overflows, double its size. */ + max <<= 1; +// pq->nodes = (PQnode *)memRealloc( pq->nodes, (size_t) ((pq->max + 1) * sizeof( pq->nodes[0] ))); + PriorityQ.PQnode[] pqNodes = new PriorityQ.PQnode[max + 1]; + System.arraycopy( nodes, 0, pqNodes, 0, nodes.length ); + for (int i = nodes.length; i < pqNodes.length; i++) { + pqNodes[i] = new PQnode(); + } + nodes = pqNodes; + if (nodes == null) { + nodes = saveNodes; /* restore ptr to free upon return */ + return Integer.MAX_VALUE; + } + +// pq->handles = (PQhandleElem *)memRealloc( pq->handles,(size_t)((pq->max + 1) * sizeof( pq->handles[0] ))); + PriorityQ.PQhandleElem[] pqHandles = new PriorityQ.PQhandleElem[max + 1]; + System.arraycopy( handles, 0, pqHandles, 0, handles.length ); + for (int i = handles.length; i < pqHandles.length; i++) { + pqHandles[i] = new PQhandleElem(); + } + handles = pqHandles; + if (handles == null) { + handles = saveHandles; /* restore ptr to free upon return */ + return Integer.MAX_VALUE; + } + } + + if (freeList == 0) { + free = curr; + } else { + free = freeList; + freeList = handles[free].node; + } + + nodes[curr].handle = free; + handles[free].node = curr; + handles[free].key = keyNew; + + if (initialized) { + FloatUp(curr); + } + assert (free != Integer.MAX_VALUE); + return free; + } + +/* really __gl_pqHeapExtractMin */ + Object pqExtractMin() { + com.sun.opengl.impl.glu.tessellator.PriorityQ.PQnode[] n = nodes; + com.sun.opengl.impl.glu.tessellator.PriorityQ.PQhandleElem[] h = handles; + int hMin = n[1].handle; + Object min = h[hMin].key; + + if (size > 0) { + n[1].handle = n[size].handle; + h[n[1].handle].node = 1; + + h[hMin].key = null; + h[hMin].node = freeList; + freeList = hMin; + + if (--size > 0) { + FloatDown(1); + } + } + return min; + } + +/* really __gl_pqHeapDelete */ + void pqDelete(int hCurr) { + com.sun.opengl.impl.glu.tessellator.PriorityQ.PQnode[] n = nodes; + com.sun.opengl.impl.glu.tessellator.PriorityQ.PQhandleElem[] h = handles; + int curr; + + assert (hCurr >= 1 && hCurr <= max && h[hCurr].key != null); + + curr = h[hCurr].node; + n[curr].handle = n[size].handle; + h[n[curr].handle].node = curr; + + if (curr <= --size) { + if (curr <= 1 || LEQ(leq, h[n[curr >> 1].handle].key, h[n[curr].handle].key)) { + FloatDown(curr); + } else { + FloatUp(curr); + } + } + h[hCurr].key = null; + h[hCurr].node = freeList; + freeList = hCurr; + } + + Object pqMinimum() { + return handles[nodes[1].handle].key; + } + + boolean pqIsEmpty() { + return size == 0; + } +} diff --git a/src/classes/com/sun/opengl/impl/glu/tessellator/PriorityQSort.java b/src/classes/com/sun/opengl/impl/glu/tessellator/PriorityQSort.java new file mode 100644 index 000000000..67924524d --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/tessellator/PriorityQSort.java @@ -0,0 +1,278 @@ +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 1.1 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.sun.opengl.impl.glu.tessellator; + +class PriorityQSort extends com.sun.opengl.impl.glu.tessellator.PriorityQ { + com.sun.opengl.impl.glu.tessellator.PriorityQHeap heap; + Object[] keys; + + // JAVA: 'order' contains indices into the keys array. + // This simulates the indirect pointers used in the original C code + // (from Frank Suykens, Luciad.com). + int[] order; + int size, max; + boolean initialized; + com.sun.opengl.impl.glu.tessellator.PriorityQ.Leq leq; + + public PriorityQSort(com.sun.opengl.impl.glu.tessellator.PriorityQ.Leq leq) { + heap = new com.sun.opengl.impl.glu.tessellator.PriorityQHeap(leq); + + keys = new Object[com.sun.opengl.impl.glu.tessellator.PriorityQ.INIT_SIZE]; + + size = 0; + max = com.sun.opengl.impl.glu.tessellator.PriorityQ.INIT_SIZE; + initialized = false; + this.leq = leq; + } + +/* really __gl_pqSortDeletePriorityQ */ + void pqDeletePriorityQ() { + if (heap != null) heap.pqDeletePriorityQ(); + order = null; + keys = null; + } + + private static boolean LT(com.sun.opengl.impl.glu.tessellator.PriorityQ.Leq leq, Object x, Object y) { + return (!com.sun.opengl.impl.glu.tessellator.PriorityQHeap.LEQ(leq, y, x)); + } + + private static boolean GT(com.sun.opengl.impl.glu.tessellator.PriorityQ.Leq leq, Object x, Object y) { + return (!com.sun.opengl.impl.glu.tessellator.PriorityQHeap.LEQ(leq, x, y)); + } + + private static void Swap(int[] array, int a, int b) { + if (true) { + int tmp = array[a]; + array[a] = array[b]; + array[b] = tmp; + } else { + + } + } + + private static class Stack { + int p, r; + } + +/* really __gl_pqSortInit */ + boolean pqInit() { + int p, r, i, j; + int piv; + Stack[] stack = new Stack[50]; + for (int k = 0; k < stack.length; k++) { + stack[k] = new Stack(); + } + int top = 0; + + int seed = 2016473283; + + /* Create an array of indirect pointers to the keys, so that we + * the handles we have returned are still valid. + */ + order = new int[size + 1]; +/* the previous line is a patch to compensate for the fact that IBM */ +/* machines return a null on a malloc of zero bytes (unlike SGI), */ +/* so we have to put in this defense to guard against a memory */ +/* fault four lines down. from [email protected]. */ + p = 0; + r = size - 1; + for (piv = 0, i = p; i <= r; ++piv, ++i) { + // indirect pointers: keep an index into the keys array, not a direct pointer to its contents + order[i] = piv; + } + + /* Sort the indirect pointers in descending order, + * using randomized Quicksort + */ + stack[top].p = p; + stack[top].r = r; + ++top; + while (--top >= 0) { + p = stack[top].p; + r = stack[top].r; + while (r > p + 10) { + seed = Math.abs( seed * 1539415821 + 1 ); + i = p + seed % (r - p + 1); + piv = order[i]; + order[i] = order[p]; + order[p] = piv; + i = p - 1; + j = r + 1; + do { + do { + ++i; + } while (GT(leq, keys[order[i]], keys[piv])); + do { + --j; + } while (LT(leq, keys[order[j]], keys[piv])); + Swap(order, i, j); + } while (i < j); + Swap(order, i, j); /* Undo last swap */ + if (i - p < r - j) { + stack[top].p = j + 1; + stack[top].r = r; + ++top; + r = i - 1; + } else { + stack[top].p = p; + stack[top].r = i - 1; + ++top; + p = j + 1; + } + } + /* Insertion sort small lists */ + for (i = p + 1; i <= r; ++i) { + piv = order[i]; + for (j = i; j > p && LT(leq, keys[order[j - 1]], keys[piv]); --j) { + order[j] = order[j - 1]; + } + order[j] = piv; + } + } + max = size; + initialized = true; + heap.pqInit(); /* always succeeds */ + +/* #ifndef NDEBUG + p = order; + r = p + size - 1; + for (i = p; i < r; ++i) { + Assertion.doAssert(LEQ( * * (i + 1), **i )); + } + #endif*/ + + return true; + } + +/* really __gl_pqSortInsert */ +/* returns LONG_MAX iff out of memory */ + int pqInsert(Object keyNew) { + int curr; + + if (initialized) { + return heap.pqInsert(keyNew); + } + curr = size; + if (++size >= max) { + Object[] saveKey = keys; + + /* If the heap overflows, double its size. */ + max <<= 1; +// pq->keys = (PQHeapKey *)memRealloc( pq->keys,(size_t)(pq->max * sizeof( pq->keys[0] ))); + Object[] pqKeys = new Object[max]; + System.arraycopy( keys, 0, pqKeys, 0, keys.length ); + keys = pqKeys; + if (keys == null) { + keys = saveKey; /* restore ptr to free upon return */ + return Integer.MAX_VALUE; + } + } + assert curr != Integer.MAX_VALUE; + keys[curr] = keyNew; + + /* Negative handles index the sorted array. */ + return -(curr + 1); + } + +/* really __gl_pqSortExtractMin */ + Object pqExtractMin() { + Object sortMin, heapMin; + + if (size == 0) { + return heap.pqExtractMin(); + } + sortMin = keys[order[size - 1]]; + if (!heap.pqIsEmpty()) { + heapMin = heap.pqMinimum(); + if (LEQ(leq, heapMin, sortMin)) { + return heap.pqExtractMin(); + } + } + do { + --size; + } while (size > 0 && keys[order[size - 1]] == null); + return sortMin; + } + +/* really __gl_pqSortMinimum */ + Object pqMinimum() { + Object sortMin, heapMin; + + if (size == 0) { + return heap.pqMinimum(); + } + sortMin = keys[order[size - 1]]; + if (!heap.pqIsEmpty()) { + heapMin = heap.pqMinimum(); + if (com.sun.opengl.impl.glu.tessellator.PriorityQHeap.LEQ(leq, heapMin, sortMin)) { + return heapMin; + } + } + return sortMin; + } + +/* really __gl_pqSortIsEmpty */ + boolean pqIsEmpty() { + return (size == 0) && heap.pqIsEmpty(); + } + +/* really __gl_pqSortDelete */ + void pqDelete(int curr) { + if (curr >= 0) { + heap.pqDelete(curr); + return; + } + curr = -(curr + 1); + assert curr < max && keys[curr] != null; + + keys[curr] = null; + while (size > 0 && keys[order[size - 1]] == null) { + --size; + } + } +} diff --git a/src/classes/com/sun/opengl/impl/glu/tessellator/Render.java b/src/classes/com/sun/opengl/impl/glu/tessellator/Render.java new file mode 100644 index 000000000..999656b82 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/tessellator/Render.java @@ -0,0 +1,557 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 1.1 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.sun.opengl.impl.glu.tessellator; + +import javax.media.opengl.*; +import javax.media.opengl.glu.*; + +class Render { + private static final boolean USE_OPTIMIZED_CODE_PATH = false; + + private Render() { + } + + private static final RenderFan renderFan = new RenderFan(); + private static final RenderStrip renderStrip = new RenderStrip(); + private static final RenderTriangle renderTriangle = new RenderTriangle(); + +/* This structure remembers the information we need about a primitive + * to be able to render it later, once we have determined which + * primitive is able to use the most triangles. + */ + private static class FaceCount { + public FaceCount() { + } + + public FaceCount(long size, com.sun.opengl.impl.glu.tessellator.GLUhalfEdge eStart, renderCallBack render) { + this.size = size; + this.eStart = eStart; + this.render = render; + } + + long size; /* number of triangles used */ + com.sun.opengl.impl.glu.tessellator.GLUhalfEdge eStart; /* edge where this primitive starts */ + renderCallBack render; + }; + + private static interface renderCallBack { + void render(GLUtessellatorImpl tess, com.sun.opengl.impl.glu.tessellator.GLUhalfEdge e, long size); + } + + /************************ Strips and Fans decomposition ******************/ + +/* __gl_renderMesh( tess, mesh ) takes a mesh and breaks it into triangle + * fans, strips, and separate triangles. A substantial effort is made + * to use as few rendering primitives as possible (ie. to make the fans + * and strips as large as possible). + * + * The rendering output is provided as callbacks (see the api). + */ + public static void __gl_renderMesh(GLUtessellatorImpl tess, com.sun.opengl.impl.glu.tessellator.GLUmesh mesh) { + com.sun.opengl.impl.glu.tessellator.GLUface f; + + /* Make a list of separate triangles so we can render them all at once */ + tess.lonelyTriList = null; + + for (f = mesh.fHead.next; f != mesh.fHead; f = f.next) { + f.marked = false; + } + for (f = mesh.fHead.next; f != mesh.fHead; f = f.next) { + + /* We examine all faces in an arbitrary order. Whenever we find + * an unprocessed face F, we output a group of faces including F + * whose size is maximum. + */ + if (f.inside && !f.marked) { + RenderMaximumFaceGroup(tess, f); + assert (f.marked); + } + } + if (tess.lonelyTriList != null) { + RenderLonelyTriangles(tess, tess.lonelyTriList); + tess.lonelyTriList = null; + } + } + + + static void RenderMaximumFaceGroup(GLUtessellatorImpl tess, com.sun.opengl.impl.glu.tessellator.GLUface fOrig) { + /* We want to find the largest triangle fan or strip of unmarked faces + * which includes the given face fOrig. There are 3 possible fans + * passing through fOrig (one centered at each vertex), and 3 possible + * strips (one for each CCW permutation of the vertices). Our strategy + * is to try all of these, and take the primitive which uses the most + * triangles (a greedy approach). + */ + com.sun.opengl.impl.glu.tessellator.GLUhalfEdge e = fOrig.anEdge; + FaceCount max = new FaceCount(); + FaceCount newFace = new FaceCount(); + + max.size = 1; + max.eStart = e; + max.render = renderTriangle; + + if (!tess.flagBoundary) { + newFace = MaximumFan(e); + if (newFace.size > max.size) { + max = newFace; + } + newFace = MaximumFan(e.Lnext); + if (newFace.size > max.size) { + max = newFace; + } + newFace = MaximumFan(e.Onext.Sym); + if (newFace.size > max.size) { + max = newFace; + } + + newFace = MaximumStrip(e); + if (newFace.size > max.size) { + max = newFace; + } + newFace = MaximumStrip(e.Lnext); + if (newFace.size > max.size) { + max = newFace; + } + newFace = MaximumStrip(e.Onext.Sym); + if (newFace.size > max.size) { + max = newFace; + } + } + max.render.render(tess, max.eStart, max.size); + } + + +/* Macros which keep track of faces we have marked temporarily, and allow + * us to backtrack when necessary. With triangle fans, this is not + * really necessary, since the only awkward case is a loop of triangles + * around a single origin vertex. However with strips the situation is + * more complicated, and we need a general tracking method like the + * one here. + */ + private static boolean Marked(com.sun.opengl.impl.glu.tessellator.GLUface f) { + return !f.inside || f.marked; + } + + private static GLUface AddToTrail(com.sun.opengl.impl.glu.tessellator.GLUface f, com.sun.opengl.impl.glu.tessellator.GLUface t) { + f.trail = t; + f.marked = true; + return f; + } + + private static void FreeTrail(com.sun.opengl.impl.glu.tessellator.GLUface t) { + if (true) { + while (t != null) { + t.marked = false; + t = t.trail; + } + } else { + /* absorb trailing semicolon */ + } + } + + static FaceCount MaximumFan(com.sun.opengl.impl.glu.tessellator.GLUhalfEdge eOrig) { + /* eOrig.Lface is the face we want to render. We want to find the size + * of a maximal fan around eOrig.Org. To do this we just walk around + * the origin vertex as far as possible in both directions. + */ + FaceCount newFace = new FaceCount(0, null, renderFan); + com.sun.opengl.impl.glu.tessellator.GLUface trail = null; + com.sun.opengl.impl.glu.tessellator.GLUhalfEdge e; + + for (e = eOrig; !Marked(e.Lface); e = e.Onext) { + trail = AddToTrail(e.Lface, trail); + ++newFace.size; + } + for (e = eOrig; !Marked(e.Sym.Lface); e = e.Sym.Lnext) { + trail = AddToTrail(e.Sym.Lface, trail); + ++newFace.size; + } + newFace.eStart = e; + /*LINTED*/ + FreeTrail(trail); + return newFace; + } + + + private static boolean IsEven(long n) { + return (n & 0x1L) == 0; + } + + static FaceCount MaximumStrip(com.sun.opengl.impl.glu.tessellator.GLUhalfEdge eOrig) { + /* Here we are looking for a maximal strip that contains the vertices + * eOrig.Org, eOrig.Dst, eOrig.Lnext.Dst (in that order or the + * reverse, such that all triangles are oriented CCW). + * + * Again we walk forward and backward as far as possible. However for + * strips there is a twist: to get CCW orientations, there must be + * an *even* number of triangles in the strip on one side of eOrig. + * We walk the strip starting on a side with an even number of triangles; + * if both side have an odd number, we are forced to shorten one side. + */ + FaceCount newFace = new FaceCount(0, null, renderStrip); + long headSize = 0, tailSize = 0; + com.sun.opengl.impl.glu.tessellator.GLUface trail = null; + com.sun.opengl.impl.glu.tessellator.GLUhalfEdge e, eTail, eHead; + + for (e = eOrig; !Marked(e.Lface); ++tailSize, e = e.Onext) { + trail = AddToTrail(e.Lface, trail); + ++tailSize; + e = e.Lnext.Sym; + if (Marked(e.Lface)) break; + trail = AddToTrail(e.Lface, trail); + } + eTail = e; + + for (e = eOrig; !Marked(e.Sym.Lface); ++headSize, e = e.Sym.Onext.Sym) { + trail = AddToTrail(e.Sym.Lface, trail); + ++headSize; + e = e.Sym.Lnext; + if (Marked(e.Sym.Lface)) break; + trail = AddToTrail(e.Sym.Lface, trail); + } + eHead = e; + + newFace.size = tailSize + headSize; + if (IsEven(tailSize)) { + newFace.eStart = eTail.Sym; + } else if (IsEven(headSize)) { + newFace.eStart = eHead; + } else { + /* Both sides have odd length, we must shorten one of them. In fact, + * we must start from eHead to guarantee inclusion of eOrig.Lface. + */ + --newFace.size; + newFace.eStart = eHead.Onext; + } + /*LINTED*/ + FreeTrail(trail); + return newFace; + } + + private static class RenderTriangle implements renderCallBack { + public void render(GLUtessellatorImpl tess, com.sun.opengl.impl.glu.tessellator.GLUhalfEdge e, long size) { + /* Just add the triangle to a triangle list, so we can render all + * the separate triangles at once. + */ + assert (size == 1); + tess.lonelyTriList = AddToTrail(e.Lface, tess.lonelyTriList); + } + } + + + static void RenderLonelyTriangles(GLUtessellatorImpl tess, com.sun.opengl.impl.glu.tessellator.GLUface f) { + /* Now we render all the separate triangles which could not be + * grouped into a triangle fan or strip. + */ + com.sun.opengl.impl.glu.tessellator.GLUhalfEdge e; + int newState; + int edgeState = -1; /* force edge state output for first vertex */ + + tess.callBeginOrBeginData(GL2ES1.GL_TRIANGLES); + + for (; f != null; f = f.trail) { + /* Loop once for each edge (there will always be 3 edges) */ + + e = f.anEdge; + do { + if (tess.flagBoundary) { + /* Set the "edge state" to true just before we output the + * first vertex of each edge on the polygon boundary. + */ + newState = (!e.Sym.Lface.inside) ? 1 : 0; + if (edgeState != newState) { + edgeState = newState; + tess.callEdgeFlagOrEdgeFlagData( edgeState != 0); + } + } + tess.callVertexOrVertexData( e.Org.data); + + e = e.Lnext; + } while (e != f.anEdge); + } + tess.callEndOrEndData(); + } + + private static class RenderFan implements renderCallBack { + public void render(GLUtessellatorImpl tess, com.sun.opengl.impl.glu.tessellator.GLUhalfEdge e, long size) { + /* Render as many CCW triangles as possible in a fan starting from + * edge "e". The fan *should* contain exactly "size" triangles + * (otherwise we've goofed up somewhere). + */ + tess.callBeginOrBeginData( GL2ES1.GL_TRIANGLE_FAN); + tess.callVertexOrVertexData( e.Org.data); + tess.callVertexOrVertexData( e.Sym.Org.data); + + while (!Marked(e.Lface)) { + e.Lface.marked = true; + --size; + e = e.Onext; + tess.callVertexOrVertexData( e.Sym.Org.data); + } + + assert (size == 0); + tess.callEndOrEndData(); + } + } + + private static class RenderStrip implements renderCallBack { + public void render(GLUtessellatorImpl tess, com.sun.opengl.impl.glu.tessellator.GLUhalfEdge e, long size) { + /* Render as many CCW triangles as possible in a strip starting from + * edge "e". The strip *should* contain exactly "size" triangles + * (otherwise we've goofed up somewhere). + */ + tess.callBeginOrBeginData( GL2ES1.GL_TRIANGLE_STRIP); + tess.callVertexOrVertexData( e.Org.data); + tess.callVertexOrVertexData( e.Sym.Org.data); + + while (!Marked(e.Lface)) { + e.Lface.marked = true; + --size; + e = e.Lnext.Sym; + tess.callVertexOrVertexData( e.Org.data); + if (Marked(e.Lface)) break; + + e.Lface.marked = true; + --size; + e = e.Onext; + tess.callVertexOrVertexData( e.Sym.Org.data); + } + + assert (size == 0); + tess.callEndOrEndData(); + } + } + + /************************ Boundary contour decomposition ******************/ + +/* __gl_renderBoundary( tess, mesh ) takes a mesh, and outputs one + * contour for each face marked "inside". The rendering output is + * provided as callbacks (see the api). + */ + public static void __gl_renderBoundary(GLUtessellatorImpl tess, com.sun.opengl.impl.glu.tessellator.GLUmesh mesh) { + com.sun.opengl.impl.glu.tessellator.GLUface f; + com.sun.opengl.impl.glu.tessellator.GLUhalfEdge e; + + for (f = mesh.fHead.next; f != mesh.fHead; f = f.next) { + if (f.inside) { + tess.callBeginOrBeginData( GL2ES1.GL_LINE_LOOP); + e = f.anEdge; + do { + tess.callVertexOrVertexData( e.Org.data); + e = e.Lnext; + } while (e != f.anEdge); + tess.callEndOrEndData(); + } + } + } + + + /************************ Quick-and-dirty decomposition ******************/ + + private static final int SIGN_INCONSISTENT = 2; + + static int ComputeNormal(GLUtessellatorImpl tess, double[] norm, boolean check) +/* + * If check==false, we compute the polygon normal and place it in norm[]. + * If check==true, we check that each triangle in the fan from v0 has a + * consistent orientation with respect to norm[]. If triangles are + * consistently oriented CCW, return 1; if CW, return -1; if all triangles + * are degenerate return 0; otherwise (no consistent orientation) return + * SIGN_INCONSISTENT. + */ { + com.sun.opengl.impl.glu.tessellator.CachedVertex[] v = tess.cache; +// CachedVertex vn = v0 + tess.cacheCount; + int vn = tess.cacheCount; +// CachedVertex vc; + int vc; + double dot, xc, yc, zc, xp, yp, zp; + double[] n = new double[3]; + int sign = 0; + + /* Find the polygon normal. It is important to get a reasonable + * normal even when the polygon is self-intersecting (eg. a bowtie). + * Otherwise, the computed normal could be very tiny, but perpendicular + * to the true plane of the polygon due to numerical noise. Then all + * the triangles would appear to be degenerate and we would incorrectly + * decompose the polygon as a fan (or simply not render it at all). + * + * We use a sum-of-triangles normal algorithm rather than the more + * efficient sum-of-trapezoids method (used in CheckOrientation() + * in normal.c). This lets us explicitly reverse the signed area + * of some triangles to get a reasonable normal in the self-intersecting + * case. + */ + if (!check) { + norm[0] = norm[1] = norm[2] = 0.0; + } + + vc = 1; + xc = v[vc].coords[0] - v[0].coords[0]; + yc = v[vc].coords[1] - v[0].coords[1]; + zc = v[vc].coords[2] - v[0].coords[2]; + while (++vc < vn) { + xp = xc; + yp = yc; + zp = zc; + xc = v[vc].coords[0] - v[0].coords[0]; + yc = v[vc].coords[1] - v[0].coords[1]; + zc = v[vc].coords[2] - v[0].coords[2]; + + /* Compute (vp - v0) cross (vc - v0) */ + n[0] = yp * zc - zp * yc; + n[1] = zp * xc - xp * zc; + n[2] = xp * yc - yp * xc; + + dot = n[0] * norm[0] + n[1] * norm[1] + n[2] * norm[2]; + if (!check) { + /* Reverse the contribution of back-facing triangles to get + * a reasonable normal for self-intersecting polygons (see above) + */ + if (dot >= 0) { + norm[0] += n[0]; + norm[1] += n[1]; + norm[2] += n[2]; + } else { + norm[0] -= n[0]; + norm[1] -= n[1]; + norm[2] -= n[2]; + } + } else if (dot != 0) { + /* Check the new orientation for consistency with previous triangles */ + if (dot > 0) { + if (sign < 0) return SIGN_INCONSISTENT; + sign = 1; + } else { + if (sign > 0) return SIGN_INCONSISTENT; + sign = -1; + } + } + } + return sign; + } + +/* __gl_renderCache( tess ) takes a single contour and tries to render it + * as a triangle fan. This handles convex polygons, as well as some + * non-convex polygons if we get lucky. + * + * Returns true if the polygon was successfully rendered. The rendering + * output is provided as callbacks (see the api). + */ + public static boolean __gl_renderCache(GLUtessellatorImpl tess) { + com.sun.opengl.impl.glu.tessellator.CachedVertex[] v = tess.cache; +// CachedVertex vn = v0 + tess.cacheCount; + int vn = tess.cacheCount; +// CachedVertex vc; + int vc; + double[] norm = new double[3]; + int sign; + + if (tess.cacheCount < 3) { + /* Degenerate contour -- no output */ + return true; + } + + norm[0] = tess.normal[0]; + norm[1] = tess.normal[1]; + norm[2] = tess.normal[2]; + if (norm[0] == 0 && norm[1] == 0 && norm[2] == 0) { + ComputeNormal( tess, norm, false); + } + + sign = ComputeNormal( tess, norm, true); + if (sign == SIGN_INCONSISTENT) { + /* Fan triangles did not have a consistent orientation */ + return false; + } + if (sign == 0) { + /* All triangles were degenerate */ + return true; + } + + if ( !USE_OPTIMIZED_CODE_PATH ) { + return false; + } else { + /* Make sure we do the right thing for each winding rule */ + switch (tess.windingRule) { + case GLU.GLU_TESS_WINDING_ODD: + case GLU.GLU_TESS_WINDING_NONZERO: + break; + case GLU.GLU_TESS_WINDING_POSITIVE: + if (sign < 0) return true; + break; + case GLU.GLU_TESS_WINDING_NEGATIVE: + if (sign > 0) return true; + break; + case GLU.GLU_TESS_WINDING_ABS_GEQ_TWO: + return true; + } + + tess.callBeginOrBeginData( tess.boundaryOnly ? GL2ES1.GL_LINE_LOOP + : (tess.cacheCount > 3) ? GL2ES1.GL_TRIANGLE_FAN + : GL2ES1.GL_TRIANGLES); + + tess.callVertexOrVertexData( v[0].data); + if (sign > 0) { + for (vc = 1; vc < vn; ++vc) { + tess.callVertexOrVertexData( v[vc].data); + } + } else { + for (vc = vn - 1; vc > 0; --vc) { + tess.callVertexOrVertexData( v[vc].data); + } + } + tess.callEndOrEndData(); + return true; + } + } +} diff --git a/src/classes/com/sun/opengl/impl/glu/tessellator/Sweep.java b/src/classes/com/sun/opengl/impl/glu/tessellator/Sweep.java new file mode 100644 index 000000000..105328d87 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/tessellator/Sweep.java @@ -0,0 +1,1353 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 1.1 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.sun.opengl.impl.glu.tessellator; + +import javax.media.opengl.*; +import javax.media.opengl.glu.*; + +class Sweep { + private Sweep() { + } + +// #ifdef FOR_TRITE_TEST_PROGRAM +// extern void DebugEvent( GLUtessellator *tess ); +// #else + private static void DebugEvent(GLUtessellatorImpl tess) { + + } +// #endif + +/* + * Invariants for the Edge Dictionary. + * - each pair of adjacent edges e2=Succ(e1) satisfies EdgeLeq(e1,e2) + * at any valid location of the sweep event + * - if EdgeLeq(e2,e1) as well (at any valid sweep event), then e1 and e2 + * share a common endpoint + * - for each e, e.Dst has been processed, but not e.Org + * - each edge e satisfies VertLeq(e.Dst,event) && VertLeq(event,e.Org) + * where "event" is the current sweep line event. + * - no edge e has zero length + * + * Invariants for the Mesh (the processed portion). + * - the portion of the mesh left of the sweep line is a planar graph, + * ie. there is *some* way to embed it in the plane + * - no processed edge has zero length + * - no two processed vertices have identical coordinates + * - each "inside" region is monotone, ie. can be broken into two chains + * of monotonically increasing vertices according to VertLeq(v1,v2) + * - a non-invariant: these chains may intersect (very slightly) + * + * Invariants for the Sweep. + * - if none of the edges incident to the event vertex have an activeRegion + * (ie. none of these edges are in the edge dictionary), then the vertex + * has only right-going edges. + * - if an edge is marked "fixUpperEdge" (it is a temporary edge introduced + * by ConnectRightVertex), then it is the only right-going edge from + * its associated vertex. (This says that these edges exist only + * when it is necessary.) + */ + +/* When we merge two edges into one, we need to compute the combined + * winding of the new edge. + */ + private static void AddWinding(GLUhalfEdge eDst, GLUhalfEdge eSrc) { + eDst.winding += eSrc.winding; + eDst.Sym.winding += eSrc.Sym.winding; + } + + + private static ActiveRegion RegionBelow(ActiveRegion r) { + return ((ActiveRegion) Dict.dictKey(Dict.dictPred(r.nodeUp))); + } + + private static ActiveRegion RegionAbove(ActiveRegion r) { + return ((ActiveRegion) Dict.dictKey(Dict.dictSucc(r.nodeUp))); + } + + static boolean EdgeLeq(GLUtessellatorImpl tess, ActiveRegion reg1, ActiveRegion reg2) +/* + * Both edges must be directed from right to left (this is the canonical + * direction for the upper edge of each region). + * + * The strategy is to evaluate a "t" value for each edge at the + * current sweep line position, given by tess.event. The calculations + * are designed to be very stable, but of course they are not perfect. + * + * Special case: if both edge destinations are at the sweep event, + * we sort the edges by slope (they would otherwise compare equally). + */ { + GLUvertex event = tess.event; + GLUhalfEdge e1, e2; + double t1, t2; + + e1 = reg1.eUp; + e2 = reg2.eUp; + + if (e1.Sym.Org == event) { + if (e2.Sym.Org == event) { + /* Two edges right of the sweep line which meet at the sweep event. + * Sort them by slope. + */ + if (Geom.VertLeq(e1.Org, e2.Org)) { + return Geom.EdgeSign(e2.Sym.Org, e1.Org, e2.Org) <= 0; + } + return Geom.EdgeSign(e1.Sym.Org, e2.Org, e1.Org) >= 0; + } + return Geom.EdgeSign(e2.Sym.Org, event, e2.Org) <= 0; + } + if (e2.Sym.Org == event) { + return Geom.EdgeSign(e1.Sym.Org, event, e1.Org) >= 0; + } + + /* General case - compute signed distance *from* e1, e2 to event */ + t1 = Geom.EdgeEval(e1.Sym.Org, event, e1.Org); + t2 = Geom.EdgeEval(e2.Sym.Org, event, e2.Org); + return (t1 >= t2); + } + + + static void DeleteRegion(GLUtessellatorImpl tess, ActiveRegion reg) { + if (reg.fixUpperEdge) { + /* It was created with zero winding number, so it better be + * deleted with zero winding number (ie. it better not get merged + * with a real edge). + */ + assert (reg.eUp.winding == 0); + } + reg.eUp.activeRegion = null; + Dict.dictDelete(tess.dict, reg.nodeUp); /* __gl_dictListDelete */ + } + + + static boolean FixUpperEdge(ActiveRegion reg, GLUhalfEdge newEdge) +/* + * Replace an upper edge which needs fixing (see ConnectRightVertex). + */ { + assert (reg.fixUpperEdge); + if (!Mesh.__gl_meshDelete(reg.eUp)) return false; + reg.fixUpperEdge = false; + reg.eUp = newEdge; + newEdge.activeRegion = reg; + + return true; + } + + static ActiveRegion TopLeftRegion(ActiveRegion reg) { + GLUvertex org = reg.eUp.Org; + GLUhalfEdge e; + + /* Find the region above the uppermost edge with the same origin */ + do { + reg = RegionAbove(reg); + } while (reg.eUp.Org == org); + + /* If the edge above was a temporary edge introduced by ConnectRightVertex, + * now is the time to fix it. + */ + if (reg.fixUpperEdge) { + e = Mesh.__gl_meshConnect(RegionBelow(reg).eUp.Sym, reg.eUp.Lnext); + if (e == null) return null; + if (!FixUpperEdge(reg, e)) return null; + reg = RegionAbove(reg); + } + return reg; + } + + static ActiveRegion TopRightRegion(ActiveRegion reg) { + GLUvertex dst = reg.eUp.Sym.Org; + + /* Find the region above the uppermost edge with the same destination */ + do { + reg = RegionAbove(reg); + } while (reg.eUp.Sym.Org == dst); + return reg; + } + + static ActiveRegion AddRegionBelow(GLUtessellatorImpl tess, + ActiveRegion regAbove, + GLUhalfEdge eNewUp) +/* + * Add a new active region to the sweep line, *somewhere* below "regAbove" + * (according to where the new edge belongs in the sweep-line dictionary). + * The upper edge of the new region will be "eNewUp". + * Winding number and "inside" flag are not updated. + */ { + ActiveRegion regNew = new ActiveRegion(); + if (regNew == null) throw new RuntimeException(); + + regNew.eUp = eNewUp; + /* __gl_dictListInsertBefore */ + regNew.nodeUp = Dict.dictInsertBefore(tess.dict, regAbove.nodeUp, regNew); + if (regNew.nodeUp == null) throw new RuntimeException(); + regNew.fixUpperEdge = false; + regNew.sentinel = false; + regNew.dirty = false; + + eNewUp.activeRegion = regNew; + return regNew; + } + + static boolean IsWindingInside(GLUtessellatorImpl tess, int n) { + switch (tess.windingRule) { + case GLU.GLU_TESS_WINDING_ODD: + return (n & 1) != 0; + case GLU.GLU_TESS_WINDING_NONZERO: + return (n != 0); + case GLU.GLU_TESS_WINDING_POSITIVE: + return (n > 0); + case GLU.GLU_TESS_WINDING_NEGATIVE: + return (n < 0); + case GLU.GLU_TESS_WINDING_ABS_GEQ_TWO: + return (n >= 2) || (n <= -2); + } + /*LINTED*/ +// assert (false); + throw new InternalError(); + /*NOTREACHED*/ + } + + + static void ComputeWinding(GLUtessellatorImpl tess, ActiveRegion reg) { + reg.windingNumber = RegionAbove(reg).windingNumber + reg.eUp.winding; + reg.inside = IsWindingInside(tess, reg.windingNumber); + } + + + static void FinishRegion(GLUtessellatorImpl tess, ActiveRegion reg) +/* + * Delete a region from the sweep line. This happens when the upper + * and lower chains of a region meet (at a vertex on the sweep line). + * The "inside" flag is copied to the appropriate mesh face (we could + * not do this before -- since the structure of the mesh is always + * changing, this face may not have even existed until now). + */ { + GLUhalfEdge e = reg.eUp; + GLUface f = e.Lface; + + f.inside = reg.inside; + f.anEdge = e; /* optimization for __gl_meshTessellateMonoRegion() */ + DeleteRegion(tess, reg); + } + + + static GLUhalfEdge FinishLeftRegions(GLUtessellatorImpl tess, + ActiveRegion regFirst, ActiveRegion regLast) +/* + * We are given a vertex with one or more left-going edges. All affected + * edges should be in the edge dictionary. Starting at regFirst.eUp, + * we walk down deleting all regions where both edges have the same + * origin vOrg. At the same time we copy the "inside" flag from the + * active region to the face, since at this point each face will belong + * to at most one region (this was not necessarily true until this point + * in the sweep). The walk stops at the region above regLast; if regLast + * is null we walk as far as possible. At the same time we relink the + * mesh if necessary, so that the ordering of edges around vOrg is the + * same as in the dictionary. + */ { + ActiveRegion reg, regPrev; + GLUhalfEdge e, ePrev; + + regPrev = regFirst; + ePrev = regFirst.eUp; + while (regPrev != regLast) { + regPrev.fixUpperEdge = false; /* placement was OK */ + reg = RegionBelow(regPrev); + e = reg.eUp; + if (e.Org != ePrev.Org) { + if (!reg.fixUpperEdge) { + /* Remove the last left-going edge. Even though there are no further + * edges in the dictionary with this origin, there may be further + * such edges in the mesh (if we are adding left edges to a vertex + * that has already been processed). Thus it is important to call + * FinishRegion rather than just DeleteRegion. + */ + FinishRegion(tess, regPrev); + break; + } + /* If the edge below was a temporary edge introduced by + * ConnectRightVertex, now is the time to fix it. + */ + e = Mesh.__gl_meshConnect(ePrev.Onext.Sym, e.Sym); + if (e == null) throw new RuntimeException(); + if (!FixUpperEdge(reg, e)) throw new RuntimeException(); + } + + /* Relink edges so that ePrev.Onext == e */ + if (ePrev.Onext != e) { + if (!Mesh.__gl_meshSplice(e.Sym.Lnext, e)) throw new RuntimeException(); + if (!Mesh.__gl_meshSplice(ePrev, e)) throw new RuntimeException(); + } + FinishRegion(tess, regPrev); /* may change reg.eUp */ + ePrev = reg.eUp; + regPrev = reg; + } + return ePrev; + } + + + static void AddRightEdges(GLUtessellatorImpl tess, ActiveRegion regUp, + GLUhalfEdge eFirst, GLUhalfEdge eLast, GLUhalfEdge eTopLeft, + boolean cleanUp) +/* + * Purpose: insert right-going edges into the edge dictionary, and update + * winding numbers and mesh connectivity appropriately. All right-going + * edges share a common origin vOrg. Edges are inserted CCW starting at + * eFirst; the last edge inserted is eLast.Sym.Lnext. If vOrg has any + * left-going edges already processed, then eTopLeft must be the edge + * such that an imaginary upward vertical segment from vOrg would be + * contained between eTopLeft.Sym.Lnext and eTopLeft; otherwise eTopLeft + * should be null. + */ { + ActiveRegion reg, regPrev; + GLUhalfEdge e, ePrev; + boolean firstTime = true; + + /* Insert the new right-going edges in the dictionary */ + e = eFirst; + do { + assert (Geom.VertLeq(e.Org, e.Sym.Org)); + AddRegionBelow(tess, regUp, e.Sym); + e = e.Onext; + } while (e != eLast); + + /* Walk *all* right-going edges from e.Org, in the dictionary order, + * updating the winding numbers of each region, and re-linking the mesh + * edges to match the dictionary ordering (if necessary). + */ + if (eTopLeft == null) { + eTopLeft = RegionBelow(regUp).eUp.Sym.Onext; + } + regPrev = regUp; + ePrev = eTopLeft; + for (; ;) { + reg = RegionBelow(regPrev); + e = reg.eUp.Sym; + if (e.Org != ePrev.Org) break; + + if (e.Onext != ePrev) { + /* Unlink e from its current position, and relink below ePrev */ + if (!Mesh.__gl_meshSplice(e.Sym.Lnext, e)) throw new RuntimeException(); + if (!Mesh.__gl_meshSplice(ePrev.Sym.Lnext, e)) throw new RuntimeException(); + } + /* Compute the winding number and "inside" flag for the new regions */ + reg.windingNumber = regPrev.windingNumber - e.winding; + reg.inside = IsWindingInside(tess, reg.windingNumber); + + /* Check for two outgoing edges with same slope -- process these + * before any intersection tests (see example in __gl_computeInterior). + */ + regPrev.dirty = true; + if (!firstTime && CheckForRightSplice(tess, regPrev)) { + AddWinding(e, ePrev); + DeleteRegion(tess, regPrev); + if (!Mesh.__gl_meshDelete(ePrev)) throw new RuntimeException(); + } + firstTime = false; + regPrev = reg; + ePrev = e; + } + regPrev.dirty = true; + assert (regPrev.windingNumber - e.winding == reg.windingNumber); + + if (cleanUp) { + /* Check for intersections between newly adjacent edges. */ + WalkDirtyRegions(tess, regPrev); + } + } + + + static void CallCombine(GLUtessellatorImpl tess, GLUvertex isect, + Object[] data, float[] weights, boolean needed) { + double[] coords = new double[3]; + + /* Copy coord data in case the callback changes it. */ + coords[0] = isect.coords[0]; + coords[1] = isect.coords[1]; + coords[2] = isect.coords[2]; + + Object[] outData = new Object[1]; + tess.callCombineOrCombineData(coords, data, weights, outData); + isect.data = outData[0]; + if (isect.data == null) { + if (!needed) { + isect.data = data[0]; + } else if (!tess.fatalError) { + /* The only way fatal error is when two edges are found to intersect, + * but the user has not provided the callback necessary to handle + * generated intersection points. + */ + tess.callErrorOrErrorData(GLU.GLU_TESS_NEED_COMBINE_CALLBACK); + tess.fatalError = true; + } + } + } + + static void SpliceMergeVertices(GLUtessellatorImpl tess, GLUhalfEdge e1, + GLUhalfEdge e2) +/* + * Two vertices with idential coordinates are combined into one. + * e1.Org is kept, while e2.Org is discarded. + */ { + Object[] data = new Object[4]; + float[] weights = new float[]{0.5f, 0.5f, 0.0f, 0.0f}; + + data[0] = e1.Org.data; + data[1] = e2.Org.data; + CallCombine(tess, e1.Org, data, weights, false); + if (!Mesh.__gl_meshSplice(e1, e2)) throw new RuntimeException(); + } + + static void VertexWeights(GLUvertex isect, GLUvertex org, GLUvertex dst, + float[] weights) +/* + * Find some weights which describe how the intersection vertex is + * a linear combination of "org" and "dest". Each of the two edges + * which generated "isect" is allocated 50% of the weight; each edge + * splits the weight between its org and dst according to the + * relative distance to "isect". + */ { + double t1 = Geom.VertL1dist(org, isect); + double t2 = Geom.VertL1dist(dst, isect); + + weights[0] = (float) (0.5 * t2 / (t1 + t2)); + weights[1] = (float) (0.5 * t1 / (t1 + t2)); + isect.coords[0] += weights[0] * org.coords[0] + weights[1] * dst.coords[0]; + isect.coords[1] += weights[0] * org.coords[1] + weights[1] * dst.coords[1]; + isect.coords[2] += weights[0] * org.coords[2] + weights[1] * dst.coords[2]; + } + + + static void GetIntersectData(GLUtessellatorImpl tess, GLUvertex isect, + GLUvertex orgUp, GLUvertex dstUp, + GLUvertex orgLo, GLUvertex dstLo) +/* + * We've computed a new intersection point, now we need a "data" pointer + * from the user so that we can refer to this new vertex in the + * rendering callbacks. + */ { + Object[] data = new Object[4]; + float[] weights = new float[4]; + float[] weights1 = new float[2]; + float[] weights2 = new float[2]; + + data[0] = orgUp.data; + data[1] = dstUp.data; + data[2] = orgLo.data; + data[3] = dstLo.data; + + isect.coords[0] = isect.coords[1] = isect.coords[2] = 0; + VertexWeights(isect, orgUp, dstUp, weights1); + VertexWeights(isect, orgLo, dstLo, weights2); + System.arraycopy(weights1, 0, weights, 0, 2); + System.arraycopy(weights2, 0, weights, 2, 2); + + CallCombine(tess, isect, data, weights, true); + } + + static boolean CheckForRightSplice(GLUtessellatorImpl tess, ActiveRegion regUp) +/* + * Check the upper and lower edge of "regUp", to make sure that the + * eUp.Org is above eLo, or eLo.Org is below eUp (depending on which + * origin is leftmost). + * + * The main purpose is to splice right-going edges with the same + * dest vertex and nearly identical slopes (ie. we can't distinguish + * the slopes numerically). However the splicing can also help us + * to recover from numerical errors. For example, suppose at one + * point we checked eUp and eLo, and decided that eUp.Org is barely + * above eLo. Then later, we split eLo into two edges (eg. from + * a splice operation like this one). This can change the result of + * our test so that now eUp.Org is incident to eLo, or barely below it. + * We must correct this condition to maintain the dictionary invariants. + * + * One possibility is to check these edges for intersection again + * (ie. CheckForIntersect). This is what we do if possible. However + * CheckForIntersect requires that tess.event lies between eUp and eLo, + * so that it has something to fall back on when the intersection + * calculation gives us an unusable answer. So, for those cases where + * we can't check for intersection, this routine fixes the problem + * by just splicing the offending vertex into the other edge. + * This is a guaranteed solution, no matter how degenerate things get. + * Basically this is a combinatorial solution to a numerical problem. + */ { + ActiveRegion regLo = RegionBelow(regUp); + GLUhalfEdge eUp = regUp.eUp; + GLUhalfEdge eLo = regLo.eUp; + + if (Geom.VertLeq(eUp.Org, eLo.Org)) { + if (Geom.EdgeSign(eLo.Sym.Org, eUp.Org, eLo.Org) > 0) return false; + + /* eUp.Org appears to be below eLo */ + if (!Geom.VertEq(eUp.Org, eLo.Org)) { + /* Splice eUp.Org into eLo */ + if (Mesh.__gl_meshSplitEdge(eLo.Sym) == null) throw new RuntimeException(); + if (!Mesh.__gl_meshSplice(eUp, eLo.Sym.Lnext)) throw new RuntimeException(); + regUp.dirty = regLo.dirty = true; + + } else if (eUp.Org != eLo.Org) { + /* merge the two vertices, discarding eUp.Org */ + tess.pq.pqDelete(eUp.Org.pqHandle); /* __gl_pqSortDelete */ + SpliceMergeVertices(tess, eLo.Sym.Lnext, eUp); + } + } else { + if (Geom.EdgeSign(eUp.Sym.Org, eLo.Org, eUp.Org) < 0) return false; + + /* eLo.Org appears to be above eUp, so splice eLo.Org into eUp */ + RegionAbove(regUp).dirty = regUp.dirty = true; + if (Mesh.__gl_meshSplitEdge(eUp.Sym) == null) throw new RuntimeException(); + if (!Mesh.__gl_meshSplice(eLo.Sym.Lnext, eUp)) throw new RuntimeException(); + } + return true; + } + + static boolean CheckForLeftSplice(GLUtessellatorImpl tess, ActiveRegion regUp) +/* + * Check the upper and lower edge of "regUp", to make sure that the + * eUp.Sym.Org is above eLo, or eLo.Sym.Org is below eUp (depending on which + * destination is rightmost). + * + * Theoretically, this should always be true. However, splitting an edge + * into two pieces can change the results of previous tests. For example, + * suppose at one point we checked eUp and eLo, and decided that eUp.Sym.Org + * is barely above eLo. Then later, we split eLo into two edges (eg. from + * a splice operation like this one). This can change the result of + * the test so that now eUp.Sym.Org is incident to eLo, or barely below it. + * We must correct this condition to maintain the dictionary invariants + * (otherwise new edges might get inserted in the wrong place in the + * dictionary, and bad stuff will happen). + * + * We fix the problem by just splicing the offending vertex into the + * other edge. + */ { + ActiveRegion regLo = RegionBelow(regUp); + GLUhalfEdge eUp = regUp.eUp; + GLUhalfEdge eLo = regLo.eUp; + GLUhalfEdge e; + + assert (!Geom.VertEq(eUp.Sym.Org, eLo.Sym.Org)); + + if (Geom.VertLeq(eUp.Sym.Org, eLo.Sym.Org)) { + if (Geom.EdgeSign(eUp.Sym.Org, eLo.Sym.Org, eUp.Org) < 0) return false; + + /* eLo.Sym.Org is above eUp, so splice eLo.Sym.Org into eUp */ + RegionAbove(regUp).dirty = regUp.dirty = true; + e = Mesh.__gl_meshSplitEdge(eUp); + if (e == null) throw new RuntimeException(); + if (!Mesh.__gl_meshSplice(eLo.Sym, e)) throw new RuntimeException(); + e.Lface.inside = regUp.inside; + } else { + if (Geom.EdgeSign(eLo.Sym.Org, eUp.Sym.Org, eLo.Org) > 0) return false; + + /* eUp.Sym.Org is below eLo, so splice eUp.Sym.Org into eLo */ + regUp.dirty = regLo.dirty = true; + e = Mesh.__gl_meshSplitEdge(eLo); + if (e == null) throw new RuntimeException(); + if (!Mesh.__gl_meshSplice(eUp.Lnext, eLo.Sym)) throw new RuntimeException(); + e.Sym.Lface.inside = regUp.inside; + } + return true; + } + + + static boolean CheckForIntersect(GLUtessellatorImpl tess, ActiveRegion regUp) +/* + * Check the upper and lower edges of the given region to see if + * they intersect. If so, create the intersection and add it + * to the data structures. + * + * Returns true if adding the new intersection resulted in a recursive + * call to AddRightEdges(); in this case all "dirty" regions have been + * checked for intersections, and possibly regUp has been deleted. + */ { + ActiveRegion regLo = RegionBelow(regUp); + GLUhalfEdge eUp = regUp.eUp; + GLUhalfEdge eLo = regLo.eUp; + GLUvertex orgUp = eUp.Org; + GLUvertex orgLo = eLo.Org; + GLUvertex dstUp = eUp.Sym.Org; + GLUvertex dstLo = eLo.Sym.Org; + double tMinUp, tMaxLo; + GLUvertex isect = new GLUvertex(); + GLUvertex orgMin; + GLUhalfEdge e; + + assert (!Geom.VertEq(dstLo, dstUp)); + assert (Geom.EdgeSign(dstUp, tess.event, orgUp) <= 0); + assert (Geom.EdgeSign(dstLo, tess.event, orgLo) >= 0); + assert (orgUp != tess.event && orgLo != tess.event); + assert (!regUp.fixUpperEdge && !regLo.fixUpperEdge); + + if (orgUp == orgLo) return false; /* right endpoints are the same */ + + tMinUp = Math.min(orgUp.t, dstUp.t); + tMaxLo = Math.max(orgLo.t, dstLo.t); + if (tMinUp > tMaxLo) return false; /* t ranges do not overlap */ + + if (Geom.VertLeq(orgUp, orgLo)) { + if (Geom.EdgeSign(dstLo, orgUp, orgLo) > 0) return false; + } else { + if (Geom.EdgeSign(dstUp, orgLo, orgUp) < 0) return false; + } + + /* At this point the edges intersect, at least marginally */ + DebugEvent(tess); + + Geom.EdgeIntersect(dstUp, orgUp, dstLo, orgLo, isect); + /* The following properties are guaranteed: */ + assert (Math.min(orgUp.t, dstUp.t) <= isect.t); + assert (isect.t <= Math.max(orgLo.t, dstLo.t)); + assert (Math.min(dstLo.s, dstUp.s) <= isect.s); + assert (isect.s <= Math.max(orgLo.s, orgUp.s)); + + if (Geom.VertLeq(isect, tess.event)) { + /* The intersection point lies slightly to the left of the sweep line, + * so move it until it''s slightly to the right of the sweep line. + * (If we had perfect numerical precision, this would never happen + * in the first place). The easiest and safest thing to do is + * replace the intersection by tess.event. + */ + isect.s = tess.event.s; + isect.t = tess.event.t; + } + /* Similarly, if the computed intersection lies to the right of the + * rightmost origin (which should rarely happen), it can cause + * unbelievable inefficiency on sufficiently degenerate inputs. + * (If you have the test program, try running test54.d with the + * "X zoom" option turned on). + */ + orgMin = Geom.VertLeq(orgUp, orgLo) ? orgUp : orgLo; + if (Geom.VertLeq(orgMin, isect)) { + isect.s = orgMin.s; + isect.t = orgMin.t; + } + + if (Geom.VertEq(isect, orgUp) || Geom.VertEq(isect, orgLo)) { + /* Easy case -- intersection at one of the right endpoints */ + CheckForRightSplice(tess, regUp); + return false; + } + + if ((!Geom.VertEq(dstUp, tess.event) + && Geom.EdgeSign(dstUp, tess.event, isect) >= 0) + || (!Geom.VertEq(dstLo, tess.event) + && Geom.EdgeSign(dstLo, tess.event, isect) <= 0)) { + /* Very unusual -- the new upper or lower edge would pass on the + * wrong side of the sweep event, or through it. This can happen + * due to very small numerical errors in the intersection calculation. + */ + if (dstLo == tess.event) { + /* Splice dstLo into eUp, and process the new region(s) */ + if (Mesh.__gl_meshSplitEdge(eUp.Sym) == null) throw new RuntimeException(); + if (!Mesh.__gl_meshSplice(eLo.Sym, eUp)) throw new RuntimeException(); + regUp = TopLeftRegion(regUp); + if (regUp == null) throw new RuntimeException(); + eUp = RegionBelow(regUp).eUp; + FinishLeftRegions(tess, RegionBelow(regUp), regLo); + AddRightEdges(tess, regUp, eUp.Sym.Lnext, eUp, eUp, true); + return true; + } + if (dstUp == tess.event) { + /* Splice dstUp into eLo, and process the new region(s) */ + if (Mesh.__gl_meshSplitEdge(eLo.Sym) == null) throw new RuntimeException(); + if (!Mesh.__gl_meshSplice(eUp.Lnext, eLo.Sym.Lnext)) throw new RuntimeException(); + regLo = regUp; + regUp = TopRightRegion(regUp); + e = RegionBelow(regUp).eUp.Sym.Onext; + regLo.eUp = eLo.Sym.Lnext; + eLo = FinishLeftRegions(tess, regLo, null); + AddRightEdges(tess, regUp, eLo.Onext, eUp.Sym.Onext, e, true); + return true; + } + /* Special case: called from ConnectRightVertex. If either + * edge passes on the wrong side of tess.event, split it + * (and wait for ConnectRightVertex to splice it appropriately). + */ + if (Geom.EdgeSign(dstUp, tess.event, isect) >= 0) { + RegionAbove(regUp).dirty = regUp.dirty = true; + if (Mesh.__gl_meshSplitEdge(eUp.Sym) == null) throw new RuntimeException(); + eUp.Org.s = tess.event.s; + eUp.Org.t = tess.event.t; + } + if (Geom.EdgeSign(dstLo, tess.event, isect) <= 0) { + regUp.dirty = regLo.dirty = true; + if (Mesh.__gl_meshSplitEdge(eLo.Sym) == null) throw new RuntimeException(); + eLo.Org.s = tess.event.s; + eLo.Org.t = tess.event.t; + } + /* leave the rest for ConnectRightVertex */ + return false; + } + + /* General case -- split both edges, splice into new vertex. + * When we do the splice operation, the order of the arguments is + * arbitrary as far as correctness goes. However, when the operation + * creates a new face, the work done is proportional to the size of + * the new face. We expect the faces in the processed part of + * the mesh (ie. eUp.Lface) to be smaller than the faces in the + * unprocessed original contours (which will be eLo.Sym.Lnext.Lface). + */ + if (Mesh.__gl_meshSplitEdge(eUp.Sym) == null) throw new RuntimeException(); + if (Mesh.__gl_meshSplitEdge(eLo.Sym) == null) throw new RuntimeException(); + if (!Mesh.__gl_meshSplice(eLo.Sym.Lnext, eUp)) throw new RuntimeException(); + eUp.Org.s = isect.s; + eUp.Org.t = isect.t; + eUp.Org.pqHandle = tess.pq.pqInsert(eUp.Org); /* __gl_pqSortInsert */ + if (eUp.Org.pqHandle == Long.MAX_VALUE) { + tess.pq.pqDeletePriorityQ(); /* __gl_pqSortDeletePriorityQ */ + tess.pq = null; + throw new RuntimeException(); + } + GetIntersectData(tess, eUp.Org, orgUp, dstUp, orgLo, dstLo); + RegionAbove(regUp).dirty = regUp.dirty = regLo.dirty = true; + return false; + } + + static void WalkDirtyRegions(GLUtessellatorImpl tess, ActiveRegion regUp) +/* + * When the upper or lower edge of any region changes, the region is + * marked "dirty". This routine walks through all the dirty regions + * and makes sure that the dictionary invariants are satisfied + * (see the comments at the beginning of this file). Of course + * new dirty regions can be created as we make changes to restore + * the invariants. + */ { + ActiveRegion regLo = RegionBelow(regUp); + GLUhalfEdge eUp, eLo; + + for (; ;) { + /* Find the lowest dirty region (we walk from the bottom up). */ + while (regLo.dirty) { + regUp = regLo; + regLo = RegionBelow(regLo); + } + if (!regUp.dirty) { + regLo = regUp; + regUp = RegionAbove(regUp); + if (regUp == null || !regUp.dirty) { + /* We've walked all the dirty regions */ + return; + } + } + regUp.dirty = false; + eUp = regUp.eUp; + eLo = regLo.eUp; + + if (eUp.Sym.Org != eLo.Sym.Org) { + /* Check that the edge ordering is obeyed at the Dst vertices. */ + if (CheckForLeftSplice(tess, regUp)) { + + /* If the upper or lower edge was marked fixUpperEdge, then + * we no longer need it (since these edges are needed only for + * vertices which otherwise have no right-going edges). + */ + if (regLo.fixUpperEdge) { + DeleteRegion(tess, regLo); + if (!Mesh.__gl_meshDelete(eLo)) throw new RuntimeException(); + regLo = RegionBelow(regUp); + eLo = regLo.eUp; + } else if (regUp.fixUpperEdge) { + DeleteRegion(tess, regUp); + if (!Mesh.__gl_meshDelete(eUp)) throw new RuntimeException(); + regUp = RegionAbove(regLo); + eUp = regUp.eUp; + } + } + } + if (eUp.Org != eLo.Org) { + if (eUp.Sym.Org != eLo.Sym.Org + && !regUp.fixUpperEdge && !regLo.fixUpperEdge + && (eUp.Sym.Org == tess.event || eLo.Sym.Org == tess.event)) { + /* When all else fails in CheckForIntersect(), it uses tess.event + * as the intersection location. To make this possible, it requires + * that tess.event lie between the upper and lower edges, and also + * that neither of these is marked fixUpperEdge (since in the worst + * case it might splice one of these edges into tess.event, and + * violate the invariant that fixable edges are the only right-going + * edge from their associated vertex). + */ + if (CheckForIntersect(tess, regUp)) { + /* WalkDirtyRegions() was called recursively; we're done */ + return; + } + } else { + /* Even though we can't use CheckForIntersect(), the Org vertices + * may violate the dictionary edge ordering. Check and correct this. + */ + CheckForRightSplice(tess, regUp); + } + } + if (eUp.Org == eLo.Org && eUp.Sym.Org == eLo.Sym.Org) { + /* A degenerate loop consisting of only two edges -- delete it. */ + AddWinding(eLo, eUp); + DeleteRegion(tess, regUp); + if (!Mesh.__gl_meshDelete(eUp)) throw new RuntimeException(); + regUp = RegionAbove(regLo); + } + } + } + + + static void ConnectRightVertex(GLUtessellatorImpl tess, ActiveRegion regUp, + GLUhalfEdge eBottomLeft) +/* + * Purpose: connect a "right" vertex vEvent (one where all edges go left) + * to the unprocessed portion of the mesh. Since there are no right-going + * edges, two regions (one above vEvent and one below) are being merged + * into one. "regUp" is the upper of these two regions. + * + * There are two reasons for doing this (adding a right-going edge): + * - if the two regions being merged are "inside", we must add an edge + * to keep them separated (the combined region would not be monotone). + * - in any case, we must leave some record of vEvent in the dictionary, + * so that we can merge vEvent with features that we have not seen yet. + * For example, maybe there is a vertical edge which passes just to + * the right of vEvent; we would like to splice vEvent into this edge. + * + * However, we don't want to connect vEvent to just any vertex. We don''t + * want the new edge to cross any other edges; otherwise we will create + * intersection vertices even when the input data had no self-intersections. + * (This is a bad thing; if the user's input data has no intersections, + * we don't want to generate any false intersections ourselves.) + * + * Our eventual goal is to connect vEvent to the leftmost unprocessed + * vertex of the combined region (the union of regUp and regLo). + * But because of unseen vertices with all right-going edges, and also + * new vertices which may be created by edge intersections, we don''t + * know where that leftmost unprocessed vertex is. In the meantime, we + * connect vEvent to the closest vertex of either chain, and mark the region + * as "fixUpperEdge". This flag says to delete and reconnect this edge + * to the next processed vertex on the boundary of the combined region. + * Quite possibly the vertex we connected to will turn out to be the + * closest one, in which case we won''t need to make any changes. + */ { + GLUhalfEdge eNew; + GLUhalfEdge eTopLeft = eBottomLeft.Onext; + ActiveRegion regLo = RegionBelow(regUp); + GLUhalfEdge eUp = regUp.eUp; + GLUhalfEdge eLo = regLo.eUp; + boolean degenerate = false; + + if (eUp.Sym.Org != eLo.Sym.Org) { + CheckForIntersect(tess, regUp); + } + + /* Possible new degeneracies: upper or lower edge of regUp may pass + * through vEvent, or may coincide with new intersection vertex + */ + if (Geom.VertEq(eUp.Org, tess.event)) { + if (!Mesh.__gl_meshSplice(eTopLeft.Sym.Lnext, eUp)) throw new RuntimeException(); + regUp = TopLeftRegion(regUp); + if (regUp == null) throw new RuntimeException(); + eTopLeft = RegionBelow(regUp).eUp; + FinishLeftRegions(tess, RegionBelow(regUp), regLo); + degenerate = true; + } + if (Geom.VertEq(eLo.Org, tess.event)) { + if (!Mesh.__gl_meshSplice(eBottomLeft, eLo.Sym.Lnext)) throw new RuntimeException(); + eBottomLeft = FinishLeftRegions(tess, regLo, null); + degenerate = true; + } + if (degenerate) { + AddRightEdges(tess, regUp, eBottomLeft.Onext, eTopLeft, eTopLeft, true); + return; + } + + /* Non-degenerate situation -- need to add a temporary, fixable edge. + * Connect to the closer of eLo.Org, eUp.Org. + */ + if (Geom.VertLeq(eLo.Org, eUp.Org)) { + eNew = eLo.Sym.Lnext; + } else { + eNew = eUp; + } + eNew = Mesh.__gl_meshConnect(eBottomLeft.Onext.Sym, eNew); + if (eNew == null) throw new RuntimeException(); + + /* Prevent cleanup, otherwise eNew might disappear before we've even + * had a chance to mark it as a temporary edge. + */ + AddRightEdges(tess, regUp, eNew, eNew.Onext, eNew.Onext, false); + eNew.Sym.activeRegion.fixUpperEdge = true; + WalkDirtyRegions(tess, regUp); + } + +/* Because vertices at exactly the same location are merged together + * before we process the sweep event, some degenerate cases can't occur. + * However if someone eventually makes the modifications required to + * merge features which are close together, the cases below marked + * TOLERANCE_NONZERO will be useful. They were debugged before the + * code to merge identical vertices in the main loop was added. + */ + private static final boolean TOLERANCE_NONZERO = false; + + static void ConnectLeftDegenerate(GLUtessellatorImpl tess, + ActiveRegion regUp, GLUvertex vEvent) +/* + * The event vertex lies exacty on an already-processed edge or vertex. + * Adding the new vertex involves splicing it into the already-processed + * part of the mesh. + */ { + GLUhalfEdge e, eTopLeft, eTopRight, eLast; + ActiveRegion reg; + + e = regUp.eUp; + if (Geom.VertEq(e.Org, vEvent)) { + /* e.Org is an unprocessed vertex - just combine them, and wait + * for e.Org to be pulled from the queue + */ + assert (TOLERANCE_NONZERO); + SpliceMergeVertices(tess, e, vEvent.anEdge); + return; + } + + if (!Geom.VertEq(e.Sym.Org, vEvent)) { + /* General case -- splice vEvent into edge e which passes through it */ + if (Mesh.__gl_meshSplitEdge(e.Sym) == null) throw new RuntimeException(); + if (regUp.fixUpperEdge) { + /* This edge was fixable -- delete unused portion of original edge */ + if (!Mesh.__gl_meshDelete(e.Onext)) throw new RuntimeException(); + regUp.fixUpperEdge = false; + } + if (!Mesh.__gl_meshSplice(vEvent.anEdge, e)) throw new RuntimeException(); + SweepEvent(tess, vEvent); /* recurse */ + return; + } + + /* vEvent coincides with e.Sym.Org, which has already been processed. + * Splice in the additional right-going edges. + */ + assert (TOLERANCE_NONZERO); + regUp = TopRightRegion(regUp); + reg = RegionBelow(regUp); + eTopRight = reg.eUp.Sym; + eTopLeft = eLast = eTopRight.Onext; + if (reg.fixUpperEdge) { + /* Here e.Sym.Org has only a single fixable edge going right. + * We can delete it since now we have some real right-going edges. + */ + assert (eTopLeft != eTopRight); /* there are some left edges too */ + DeleteRegion(tess, reg); + if (!Mesh.__gl_meshDelete(eTopRight)) throw new RuntimeException(); + eTopRight = eTopLeft.Sym.Lnext; + } + if (!Mesh.__gl_meshSplice(vEvent.anEdge, eTopRight)) throw new RuntimeException(); + if (!Geom.EdgeGoesLeft(eTopLeft)) { + /* e.Sym.Org had no left-going edges -- indicate this to AddRightEdges() */ + eTopLeft = null; + } + AddRightEdges(tess, regUp, eTopRight.Onext, eLast, eTopLeft, true); + } + + + static void ConnectLeftVertex(GLUtessellatorImpl tess, GLUvertex vEvent) +/* + * Purpose: connect a "left" vertex (one where both edges go right) + * to the processed portion of the mesh. Let R be the active region + * containing vEvent, and let U and L be the upper and lower edge + * chains of R. There are two possibilities: + * + * - the normal case: split R into two regions, by connecting vEvent to + * the rightmost vertex of U or L lying to the left of the sweep line + * + * - the degenerate case: if vEvent is close enough to U or L, we + * merge vEvent into that edge chain. The subcases are: + * - merging with the rightmost vertex of U or L + * - merging with the active edge of U or L + * - merging with an already-processed portion of U or L + */ { + ActiveRegion regUp, regLo, reg; + GLUhalfEdge eUp, eLo, eNew; + ActiveRegion tmp = new ActiveRegion(); + + /* assert ( vEvent.anEdge.Onext.Onext == vEvent.anEdge ); */ + + /* Get a pointer to the active region containing vEvent */ + tmp.eUp = vEvent.anEdge.Sym; + /* __GL_DICTLISTKEY */ /* __gl_dictListSearch */ + regUp = (ActiveRegion) Dict.dictKey(Dict.dictSearch(tess.dict, tmp)); + regLo = RegionBelow(regUp); + eUp = regUp.eUp; + eLo = regLo.eUp; + + /* Try merging with U or L first */ + if (Geom.EdgeSign(eUp.Sym.Org, vEvent, eUp.Org) == 0) { + ConnectLeftDegenerate(tess, regUp, vEvent); + return; + } + + /* Connect vEvent to rightmost processed vertex of either chain. + * e.Sym.Org is the vertex that we will connect to vEvent. + */ + reg = Geom.VertLeq(eLo.Sym.Org, eUp.Sym.Org) ? regUp : regLo; + + if (regUp.inside || reg.fixUpperEdge) { + if (reg == regUp) { + eNew = Mesh.__gl_meshConnect(vEvent.anEdge.Sym, eUp.Lnext); + if (eNew == null) throw new RuntimeException(); + } else { + GLUhalfEdge tempHalfEdge = Mesh.__gl_meshConnect(eLo.Sym.Onext.Sym, vEvent.anEdge); + if (tempHalfEdge == null) throw new RuntimeException(); + + eNew = tempHalfEdge.Sym; + } + if (reg.fixUpperEdge) { + if (!FixUpperEdge(reg, eNew)) throw new RuntimeException(); + } else { + ComputeWinding(tess, AddRegionBelow(tess, regUp, eNew)); + } + SweepEvent(tess, vEvent); + } else { + /* The new vertex is in a region which does not belong to the polygon. + * We don''t need to connect this vertex to the rest of the mesh. + */ + AddRightEdges(tess, regUp, vEvent.anEdge, vEvent.anEdge, null, true); + } + } + + + static void SweepEvent(GLUtessellatorImpl tess, GLUvertex vEvent) +/* + * Does everything necessary when the sweep line crosses a vertex. + * Updates the mesh and the edge dictionary. + */ { + ActiveRegion regUp, reg; + GLUhalfEdge e, eTopLeft, eBottomLeft; + + tess.event = vEvent; /* for access in EdgeLeq() */ + DebugEvent(tess); + + /* Check if this vertex is the right endpoint of an edge that is + * already in the dictionary. In this case we don't need to waste + * time searching for the location to insert new edges. + */ + e = vEvent.anEdge; + while (e.activeRegion == null) { + e = e.Onext; + if (e == vEvent.anEdge) { + /* All edges go right -- not incident to any processed edges */ + ConnectLeftVertex(tess, vEvent); + return; + } + } + + /* Processing consists of two phases: first we "finish" all the + * active regions where both the upper and lower edges terminate + * at vEvent (ie. vEvent is closing off these regions). + * We mark these faces "inside" or "outside" the polygon according + * to their winding number, and delete the edges from the dictionary. + * This takes care of all the left-going edges from vEvent. + */ + regUp = TopLeftRegion(e.activeRegion); + if (regUp == null) throw new RuntimeException(); + reg = RegionBelow(regUp); + eTopLeft = reg.eUp; + eBottomLeft = FinishLeftRegions(tess, reg, null); + + /* Next we process all the right-going edges from vEvent. This + * involves adding the edges to the dictionary, and creating the + * associated "active regions" which record information about the + * regions between adjacent dictionary edges. + */ + if (eBottomLeft.Onext == eTopLeft) { + /* No right-going edges -- add a temporary "fixable" edge */ + ConnectRightVertex(tess, regUp, eBottomLeft); + } else { + AddRightEdges(tess, regUp, eBottomLeft.Onext, eTopLeft, eTopLeft, true); + } + } + + +/* Make the sentinel coordinates big enough that they will never be + * merged with real input features. (Even with the largest possible + * input contour and the maximum tolerance of 1.0, no merging will be + * done with coordinates larger than 3 * GLU_TESS_MAX_COORD). + */ + private static final double SENTINEL_COORD = (4.0 * GLU.GLU_TESS_MAX_COORD); + + static void AddSentinel(GLUtessellatorImpl tess, double t) +/* + * We add two sentinel edges above and below all other edges, + * to avoid special cases at the top and bottom. + */ { + GLUhalfEdge e; + ActiveRegion reg = new ActiveRegion(); + if (reg == null) throw new RuntimeException(); + + e = Mesh.__gl_meshMakeEdge(tess.mesh); + if (e == null) throw new RuntimeException(); + + e.Org.s = SENTINEL_COORD; + e.Org.t = t; + e.Sym.Org.s = -SENTINEL_COORD; + e.Sym.Org.t = t; + tess.event = e.Sym.Org; /* initialize it */ + + reg.eUp = e; + reg.windingNumber = 0; + reg.inside = false; + reg.fixUpperEdge = false; + reg.sentinel = true; + reg.dirty = false; + reg.nodeUp = Dict.dictInsert(tess.dict, reg); /* __gl_dictListInsertBefore */ + if (reg.nodeUp == null) throw new RuntimeException(); + } + + + static void InitEdgeDict(final GLUtessellatorImpl tess) +/* + * We maintain an ordering of edge intersections with the sweep line. + * This order is maintained in a dynamic dictionary. + */ { + /* __gl_dictListNewDict */ + tess.dict = Dict.dictNewDict(tess, new Dict.DictLeq() { + public boolean leq(Object frame, Object key1, Object key2) { + return EdgeLeq(tess, (ActiveRegion) key1, (ActiveRegion) key2); + } + }); + if (tess.dict == null) throw new RuntimeException(); + + AddSentinel(tess, -SENTINEL_COORD); + AddSentinel(tess, SENTINEL_COORD); + } + + + static void DoneEdgeDict(GLUtessellatorImpl tess) { + ActiveRegion reg; + int fixedEdges = 0; + + /* __GL_DICTLISTKEY */ /* __GL_DICTLISTMIN */ + while ((reg = (ActiveRegion) Dict.dictKey(Dict.dictMin(tess.dict))) != null) { + /* + * At the end of all processing, the dictionary should contain + * only the two sentinel edges, plus at most one "fixable" edge + * created by ConnectRightVertex(). + */ + if (!reg.sentinel) { + assert (reg.fixUpperEdge); + assert (++fixedEdges == 1); + } + assert (reg.windingNumber == 0); + DeleteRegion(tess, reg); +/* __gl_meshDelete( reg.eUp );*/ + } + Dict.dictDeleteDict(tess.dict); /* __gl_dictListDeleteDict */ + } + + + static void RemoveDegenerateEdges(GLUtessellatorImpl tess) +/* + * Remove zero-length edges, and contours with fewer than 3 vertices. + */ { + GLUhalfEdge e, eNext, eLnext; + GLUhalfEdge eHead = tess.mesh.eHead; + + /*LINTED*/ + for (e = eHead.next; e != eHead; e = eNext) { + eNext = e.next; + eLnext = e.Lnext; + + if (Geom.VertEq(e.Org, e.Sym.Org) && e.Lnext.Lnext != e) { + /* Zero-length edge, contour has at least 3 edges */ + + SpliceMergeVertices(tess, eLnext, e); /* deletes e.Org */ + if (!Mesh.__gl_meshDelete(e)) throw new RuntimeException(); /* e is a self-loop */ + e = eLnext; + eLnext = e.Lnext; + } + if (eLnext.Lnext == e) { + /* Degenerate contour (one or two edges) */ + + if (eLnext != e) { + if (eLnext == eNext || eLnext == eNext.Sym) { + eNext = eNext.next; + } + if (!Mesh.__gl_meshDelete(eLnext)) throw new RuntimeException(); + } + if (e == eNext || e == eNext.Sym) { + eNext = eNext.next; + } + if (!Mesh.__gl_meshDelete(e)) throw new RuntimeException(); + } + } + } + + static boolean InitPriorityQ(GLUtessellatorImpl tess) +/* + * Insert all vertices into the priority queue which determines the + * order in which vertices cross the sweep line. + */ { + PriorityQ pq; + GLUvertex v, vHead; + + /* __gl_pqSortNewPriorityQ */ + pq = tess.pq = PriorityQ.pqNewPriorityQ(new PriorityQ.Leq() { + public boolean leq(Object key1, Object key2) { + return Geom.VertLeq(((GLUvertex) key1), (GLUvertex) key2); + } + }); + if (pq == null) return false; + + vHead = tess.mesh.vHead; + for (v = vHead.next; v != vHead; v = v.next) { + v.pqHandle = pq.pqInsert(v); /* __gl_pqSortInsert */ + if (v.pqHandle == Long.MAX_VALUE) break; + } + if (v != vHead || !pq.pqInit()) { /* __gl_pqSortInit */ + tess.pq.pqDeletePriorityQ(); /* __gl_pqSortDeletePriorityQ */ + tess.pq = null; + return false; + } + + return true; + } + + + static void DonePriorityQ(GLUtessellatorImpl tess) { + tess.pq.pqDeletePriorityQ(); /* __gl_pqSortDeletePriorityQ */ + } + + + static boolean RemoveDegenerateFaces(GLUmesh mesh) +/* + * Delete any degenerate faces with only two edges. WalkDirtyRegions() + * will catch almost all of these, but it won't catch degenerate faces + * produced by splice operations on already-processed edges. + * The two places this can happen are in FinishLeftRegions(), when + * we splice in a "temporary" edge produced by ConnectRightVertex(), + * and in CheckForLeftSplice(), where we splice already-processed + * edges to ensure that our dictionary invariants are not violated + * by numerical errors. + * + * In both these cases it is *very* dangerous to delete the offending + * edge at the time, since one of the routines further up the stack + * will sometimes be keeping a pointer to that edge. + */ { + GLUface f, fNext; + GLUhalfEdge e; + + /*LINTED*/ + for (f = mesh.fHead.next; f != mesh.fHead; f = fNext) { + fNext = f.next; + e = f.anEdge; + assert (e.Lnext != e); + + if (e.Lnext.Lnext == e) { + /* A face with only two edges */ + AddWinding(e.Onext, e); + if (!Mesh.__gl_meshDelete(e)) return false; + } + } + return true; + } + + public static boolean __gl_computeInterior(GLUtessellatorImpl tess) +/* + * __gl_computeInterior( tess ) computes the planar arrangement specified + * by the given contours, and further subdivides this arrangement + * into regions. Each region is marked "inside" if it belongs + * to the polygon, according to the rule given by tess.windingRule. + * Each interior region is guaranteed be monotone. + */ { + GLUvertex v, vNext; + + tess.fatalError = false; + + /* Each vertex defines an event for our sweep line. Start by inserting + * all the vertices in a priority queue. Events are processed in + * lexicographic order, ie. + * + * e1 < e2 iff e1.x < e2.x || (e1.x == e2.x && e1.y < e2.y) + */ + RemoveDegenerateEdges(tess); + if (!InitPriorityQ(tess)) return false; /* if error */ + InitEdgeDict(tess); + + /* __gl_pqSortExtractMin */ + while ((v = (GLUvertex) tess.pq.pqExtractMin()) != null) { + for (; ;) { + vNext = (GLUvertex) tess.pq.pqMinimum(); /* __gl_pqSortMinimum */ + if (vNext == null || !Geom.VertEq(vNext, v)) break; + + /* Merge together all vertices at exactly the same location. + * This is more efficient than processing them one at a time, + * simplifies the code (see ConnectLeftDegenerate), and is also + * important for correct handling of certain degenerate cases. + * For example, suppose there are two identical edges A and B + * that belong to different contours (so without this code they would + * be processed by separate sweep events). Suppose another edge C + * crosses A and B from above. When A is processed, we split it + * at its intersection point with C. However this also splits C, + * so when we insert B we may compute a slightly different + * intersection point. This might leave two edges with a small + * gap between them. This kind of error is especially obvious + * when using boundary extraction (GLU_TESS_BOUNDARY_ONLY). + */ + vNext = (GLUvertex) tess.pq.pqExtractMin(); /* __gl_pqSortExtractMin*/ + SpliceMergeVertices(tess, v.anEdge, vNext.anEdge); + } + SweepEvent(tess, v); + } + + /* Set tess.event for debugging purposes */ + /* __GL_DICTLISTKEY */ /* __GL_DICTLISTMIN */ + tess.event = ((ActiveRegion) Dict.dictKey(Dict.dictMin(tess.dict))).eUp.Org; + DebugEvent(tess); + DoneEdgeDict(tess); + DonePriorityQ(tess); + + if (!RemoveDegenerateFaces(tess.mesh)) return false; + Mesh.__gl_meshCheckMesh(tess.mesh); + + return true; + } +} diff --git a/src/classes/com/sun/opengl/impl/glu/tessellator/TessMono.java b/src/classes/com/sun/opengl/impl/glu/tessellator/TessMono.java new file mode 100644 index 000000000..62c653bfe --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/tessellator/TessMono.java @@ -0,0 +1,209 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 1.1 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.sun.opengl.impl.glu.tessellator; + +class TessMono { +/* __gl_meshTessellateMonoRegion( face ) tessellates a monotone region + * (what else would it do??) The region must consist of a single + * loop of half-edges (see mesh.h) oriented CCW. "Monotone" in this + * case means that any vertical line intersects the interior of the + * region in a single interval. + * + * Tessellation consists of adding interior edges (actually pairs of + * half-edges), to split the region into non-overlapping triangles. + * + * The basic idea is explained in Preparata and Shamos (which I don''t + * have handy right now), although their implementation is more + * complicated than this one. The are two edge chains, an upper chain + * and a lower chain. We process all vertices from both chains in order, + * from right to left. + * + * The algorithm ensures that the following invariant holds after each + * vertex is processed: the untessellated region consists of two + * chains, where one chain (say the upper) is a single edge, and + * the other chain is concave. The left vertex of the single edge + * is always to the left of all vertices in the concave chain. + * + * Each step consists of adding the rightmost unprocessed vertex to one + * of the two chains, and forming a fan of triangles from the rightmost + * of two chain endpoints. Determining whether we can add each triangle + * to the fan is a simple orientation test. By making the fan as large + * as possible, we restore the invariant (check it yourself). + */ + static boolean __gl_meshTessellateMonoRegion(GLUface face) { + GLUhalfEdge up, lo; + + /* All edges are oriented CCW around the boundary of the region. + * First, find the half-edge whose origin vertex is rightmost. + * Since the sweep goes from left to right, face->anEdge should + * be close to the edge we want. + */ + up = face.anEdge; + assert (up.Lnext != up && up.Lnext.Lnext != up); + + for (; Geom.VertLeq(up.Sym.Org, up.Org); up = up.Onext.Sym) + ; + for (; Geom.VertLeq(up.Org, up.Sym.Org); up = up.Lnext) + ; + lo = up.Onext.Sym; + + while (up.Lnext != lo) { + if (Geom.VertLeq(up.Sym.Org, lo.Org)) { + /* up.Sym.Org is on the left. It is safe to form triangles from lo.Org. + * The EdgeGoesLeft test guarantees progress even when some triangles + * are CW, given that the upper and lower chains are truly monotone. + */ + while (lo.Lnext != up && (Geom.EdgeGoesLeft(lo.Lnext) + || Geom.EdgeSign(lo.Org, lo.Sym.Org, lo.Lnext.Sym.Org) <= 0)) { + GLUhalfEdge tempHalfEdge = Mesh.__gl_meshConnect(lo.Lnext, lo); + if (tempHalfEdge == null) return false; + lo = tempHalfEdge.Sym; + } + lo = lo.Onext.Sym; + } else { + /* lo.Org is on the left. We can make CCW triangles from up.Sym.Org. */ + while (lo.Lnext != up && (Geom.EdgeGoesRight(up.Onext.Sym) + || Geom.EdgeSign(up.Sym.Org, up.Org, up.Onext.Sym.Org) >= 0)) { + GLUhalfEdge tempHalfEdge = Mesh.__gl_meshConnect(up, up.Onext.Sym); + if (tempHalfEdge == null) return false; + up = tempHalfEdge.Sym; + } + up = up.Lnext; + } + } + + /* Now lo.Org == up.Sym.Org == the leftmost vertex. The remaining region + * can be tessellated in a fan from this leftmost vertex. + */ + assert (lo.Lnext != up); + while (lo.Lnext.Lnext != up) { + GLUhalfEdge tempHalfEdge = Mesh.__gl_meshConnect(lo.Lnext, lo); + if (tempHalfEdge == null) return false; + lo = tempHalfEdge.Sym; + } + + return true; + } + + +/* __gl_meshTessellateInterior( mesh ) tessellates each region of + * the mesh which is marked "inside" the polygon. Each such region + * must be monotone. + */ + public static boolean __gl_meshTessellateInterior(GLUmesh mesh) { + GLUface f, next; + + /*LINTED*/ + for (f = mesh.fHead.next; f != mesh.fHead; f = next) { + /* Make sure we don''t try to tessellate the new triangles. */ + next = f.next; + if (f.inside) { + if (!__gl_meshTessellateMonoRegion(f)) return false; + } + } + + return true; + } + + +/* __gl_meshDiscardExterior( mesh ) zaps (ie. sets to NULL) all faces + * which are not marked "inside" the polygon. Since further mesh operations + * on NULL faces are not allowed, the main purpose is to clean up the + * mesh so that exterior loops are not represented in the data structure. + */ + public static void __gl_meshDiscardExterior(GLUmesh mesh) { + GLUface f, next; + + /*LINTED*/ + for (f = mesh.fHead.next; f != mesh.fHead; f = next) { + /* Since f will be destroyed, save its next pointer. */ + next = f.next; + if (!f.inside) { + Mesh.__gl_meshZapFace(f); + } + } + } + + private static final int MARKED_FOR_DELETION = 0x7fffffff; + +/* __gl_meshSetWindingNumber( mesh, value, keepOnlyBoundary ) resets the + * winding numbers on all edges so that regions marked "inside" the + * polygon have a winding number of "value", and regions outside + * have a winding number of 0. + * + * If keepOnlyBoundary is TRUE, it also deletes all edges which do not + * separate an interior region from an exterior one. + */ + public static boolean __gl_meshSetWindingNumber(GLUmesh mesh, int value, boolean keepOnlyBoundary) { + GLUhalfEdge e, eNext; + + for (e = mesh.eHead.next; e != mesh.eHead; e = eNext) { + eNext = e.next; + if (e.Sym.Lface.inside != e.Lface.inside) { + + /* This is a boundary edge (one side is interior, one is exterior). */ + e.winding = (e.Lface.inside) ? value : -value; + } else { + + /* Both regions are interior, or both are exterior. */ + if (!keepOnlyBoundary) { + e.winding = 0; + } else { + if (!Mesh.__gl_meshDelete(e)) return false; + } + } + } + return true; + } + +} diff --git a/src/classes/com/sun/opengl/impl/glu/tessellator/TessState.java b/src/classes/com/sun/opengl/impl/glu/tessellator/TessState.java new file mode 100644 index 000000000..9cf192529 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/glu/tessellator/TessState.java @@ -0,0 +1,59 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 1.1 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.sun.opengl.impl.glu.tessellator; + +class TessState { + public static final int T_DORMANT = 0; + public static final int T_IN_POLYGON = 1; + public static final int T_IN_CONTOUR = 2; +} |