Cylinder radial segment primitive object for Papervision3D

Monday, May 19th, 2008

For my latest project I needed to display 3D cylinder slices - Papervision was an obvious choice. Unfortunately the primitive cylinder class does not work this way, the cylinder is built as a square mesh with no option for segment slices. So I had to help myself, I started to play with the almost undocumented PV3D primitives, step by step modifying the original cylinder class and after couple hours I dig out what is what and derived my RadialSegment class. It follows the original concept with one material for whole object, supports UV mapping and inherit all other properties. Here it is, use it as you wish.

papervision3d cylinder radial segment

Code and live example in full article

Here is live example and source code follows:

[as]
package {
import org.papervision3d.core.geom.*;
import org.papervision3d.core.geom.renderables.Triangle3D;
import org.papervision3d.core.geom.renderables.Vertex3D;
import org.papervision3d.core.math.NumberUV;
import org.papervision3d.core.proto.*;

/**
* The RadialSegment class lets you create and display cylinders radial segments.
*

* The RadialSegment is divided in horizontal mesh segments and vertical ragial segments.
* * Derivated from original Cylinder class by Daniel Sedlacek (sedlacek.daniel@gmail.com).
* * Please follow the original Papervision3D license.
*/
public class RadialSegment extends TriangleMesh3D {
/**
* Number of segments horizontally. Defaults to 8.
*/
public var segmentsW : Number; /**
* Number of segments vertically. Defaults to 6.
*/
public var segmentsH : Number;

/**
* Default radius of Segment3D if not defined.
*/
static public var DEFAULT_RADIUS : Number = 100;

/**
* Default height if not defined.
*/
static public var DEFAULT_HEIGHT : Number = 50;

/**
* Default value of gridX if not defined.
*/
static public var DEFAULT_SEGMENTSW : Number = 8;

/**
* Default value of gridY if not defined.
*/
static public var DEFAULT_SEGMENTSH : Number = 2;

/**
* Minimum value of gridX.
*/
static public var MIN_SEGMENTSW : Number = 3;

/**
* Minimum value of gridY.
*/
static public var MIN_SEGMENTSH : Number = 1;

/**
* Create a new Cylinder object.
*

* @param material [optional] - A MaterialObject3D object that contains the material properties of the object.
* * @param angle [optional] - Desired segment angle <0,1>.
* * @param radius [optional] - Desired radius.
* * @param segmentsW [optional] - Number of segments horizontally. Defaults to 8.
* * @param segmentsH [optional] - Number of segments vertically. Defaults to 6.
* * @param topRadius [optional] - An optional parameter for con- or diverging cylinders
* * @param initObject [optional] - An object that contains user defined properties with which to populate the newly created GeometryObject3D.
* * It includes x, y, z, rotationX, rotationY, rotationZ, scaleX, scaleY scaleZ and a user defined extra object.
* * If extra is not an object, it is ignored. All properties of the extra field are copied into the new instance. The properties specified with extra are publicly available.
*/
public function RadialSegment( material : MaterialObject3D = null, angle : Number = 0.25, radius : Number = 100, height : Number = 100, segmentsW : int = 8, segmentsH : int = 2, topRadius : Number = -1, initObject : Object = null ) {
super(material, new Array(), new Array(), null, initObject); this.segmentsW = Math.max(MIN_SEGMENTSW, segmentsW || DEFAULT_SEGMENTSW);
// Defaults to 8
this.segmentsH = Math.max(MIN_SEGMENTSH, segmentsH || DEFAULT_SEGMENTSH);
// Defaults to 6
if (radius == 0) radius = DEFAULT_RADIUS;
// Defaults to 100
if (height == 0) height = DEFAULT_HEIGHT;
// Defaults to 100
if (topRadius == -1) topRadius = radius;
// segment
angle = angle > 1 ? 1 : angle < 0 ? 0 : angle;

buildSegment(angle, radius, height, topRadius);
}

private function buildSegment( fAngle : Number, fRadius : Number, fHeight : Number, fTopRadius : Number ) : void {
var matInstance : MaterialObject3D = material;

var i : Number, j : Number;

var iHor : Number = this.segmentsW + 1;
var iVer : Number = this.segmentsH;
var aVertice : Array = this.geometry.vertices;
var aFace : Array = this.geometry.faces;
var aVtc : Array = new Array();

for (j = 0;j < (iVer + 1);j++) {
// vertical
var fZ : Number = fHeight * (j / (iVer + 0)) - fHeight / 2;
//-fRadius*Math.cos(fRad1*Math.PI);
var fRds : Number = fTopRadius + (fRadius - fTopRadius) * (1 - j / (iVer));
//*Math.sin(fRad1*Math.PI);
var aRow : Array = new Array();
var oVtx : Vertex3D;

for (i = 0;i < iHor;i++) {
// horizontal
var fRad2 : Number = Number(2 * i / (iHor - 1));
var fX : Number = fRds * Math.sin(fRad2 * Math.PI * fAngle);
var fY : Number = fRds * Math.cos(fRad2 * Math.PI * fAngle);
oVtx = new Vertex3D(fY, fZ, fX);

aVertice.push(oVtx);
aRow.push(oVtx);
}

// special middle vertex
oVtx = new Vertex3D(0, fZ, 0);
aVertice.push(oVtx);
aRow.push(oVtx);

aVtc.push(aRow);
}
var iVerNum : int = aVtc.length;

var aP4uv : NumberUV, aP1uv : NumberUV, aP2uv : NumberUV, aP3uv : NumberUV;
var aP1 : Vertex3D, aP2 : Vertex3D, aP3 : Vertex3D, aP4 : Vertex3D;

for (j = 0;j < iVerNum;j++) {
var iHorNum : int = aVtc[j].length;
for (i = 0;i < iHorNum;i++) {
if (j > 0 && i >= 0) {
// select vertices
var bEnd : Boolean = i == (iHorNum - 0);
aP1 = aVtc[j][bEnd ? 0 : i];
aP2 = aVtc[j][(i == 0 ? iHorNum : i) - 1];
aP3 = aVtc[j - 1][(i == 0 ? iHorNum : i) - 1];
aP4 = aVtc[j - 1][bEnd ? 0 : i];
// uv
var fJ0 : Number = j / iVerNum;
var fJ1 : Number = (j - 1) / iVerNum;
var fI0 : Number = (i + 1) / iHorNum;
var fI1 : Number = i / iHorNum;
aP4uv = new NumberUV(fI0, fJ1);
aP1uv = new NumberUV(fI0, fJ0);
aP2uv = new NumberUV(fI1, fJ0);
aP3uv = new NumberUV(fI1, fJ1);

aFace.push(new Triangle3D(this, [aP1,aP2,aP3], matInstance, [aP1uv,aP2uv,aP3uv]));
aFace.push(new Triangle3D(this, [aP1,aP3,aP4], matInstance, [aP1uv,aP3uv,aP4uv]));
}
}
if (j == 0 || j == (iVerNum - 1)) {
for (i = 0;i < (iHorNum - 2);i++) {
// uv

aP1 = aVtc[j][iHorNum - 1];
aP2 = aVtc[j][i];
aP3 = aVtc[j][i + 1];

var bTop : Boolean = j == 0;
aP1uv = new NumberUV((bTop ? 1 : 0) + (bTop ? -1 : 1) * (aP1.x / fRadius / 2 + .5), aP1.z / fRadius / 2 + .5);
aP2uv = new NumberUV((bTop ? 1 : 0) + (bTop ? -1 : 1) * (aP2.x / fRadius / 2 + .5), aP2.z / fRadius / 2 + .5);
aP3uv = new NumberUV((bTop ? 1 : 0) + (bTop ? -1 : 1) * (aP3.x / fRadius / 2 + .5), aP3.z / fRadius / 2 + .5);

// face
if (j == 0) aFace.push(new Triangle3D(this, [aP1,aP3,aP2], matInstance, [aP1uv,aP3uv,aP2uv]));
else aFace.push(new Triangle3D(this, [aP1,aP2,aP3], matInstance, [aP1uv,aP2uv,aP3uv]));
}
}
}
this.geometry.ready = true;
}
}
}
[/as]

AddThis Feed Button

This is some text prior to the author information. You can change this text from the admin section of WP-Gravatar  Flash / Flex developer, London UK, Bratislava SK Read more from this author


tagged under:

ABOUT THIS AUTHOR

Flash / Flex developer, London UK, Bratislava SK

Get a Trackback link

3 Trackbacks/Pingbacks

  1. Pingback: Cylinder radial segment primitive object for Papervision3D on May 19, 2008
  2. Pingback: flash your on May 19, 2008
  3. Pingback: Pages tagged "the primitives" on May 21, 2008

Live Preview

Leave a comment

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="">

This site is using OpenAvatar based on
Images is enhanced with WordPress Lightbox JS by Zeo
Clicky Web Analytics