jogamp.opengl.glu.nurbs.Knotspec Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jogl-all Show documentation
Show all versions of jogl-all Show documentation
Java™ Binding for the OpenGL® API
package jogamp.opengl.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 2.0 (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;
}
}
}