Cylinder radial segment primitive object for Papervision3D

Monday, May 19th, 2008
Cylinder radial segment primitive object for Papervision3D

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:

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;
}
}
}
tagged under:

ABOUT THIS AUTHOR

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

8 Comments


  1. marcel weber
    Visit Site
    August 28th, 2009

    Sounds nice! I would like to see the demo, but the links are broken.


  2. admin
    Visit Site
    October 13th, 2009

    Sorry Marcel, problem fixed. It was caused by changing my hosting to another provider and I have some issues with Wordpress. But now you can see example and download source code


  3. Giedrius
    Visit Site
    January 5th, 2010

    It seems this class doesn’t work with papervision library 2.0…
    Could You upload Your papervision library some how?


  4. Giedrius
    Visit Site
    January 5th, 2010

    Sorry…
    It works. Made some corrections. Just rendering isn’t well enough. While rotating camera there appears white spot on stage…


  5. Daniel Sedlacek
    Visit Site
    January 5th, 2010

    Sorry, it is bit out of date now. Hope you can use it at least as a concept.


  6. Achim
    Visit Site
    June 30th, 2010

    Hi,
    is there an update of this nice primitive working with PV3D 2.0?
    That would be really useful to create Pie Charts!


  7. Daniel Sedlacek
    Visit Site
    July 6th, 2010

    @Achim: This should help, it’s PV3D 2.0 and it provides more control over texturing. Enjoy. http://franto.com/uploads/examples/pie/Cylinder3D.as


  8. Daniel Sedlacek
    Visit Site
    July 7th, 2010

    @Achim: this should help, it’s Pv3D 2.0 version with enhanced texturing and fixed UV mapping bug. Get the new class here.

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="" escaped="">

CommentLuv Enabled

Images is enhanced with WordPress Lightbox JS by Zeo