Ok - I grabbed nicoptere's Delaunay library and hacked the Plane class
to accept a GraphicsPath, grab the vertices from it, create Delaunay
triangles and render them.

There are two problems here.

1) nicopteres library doesn't have the concept of a bounding path, so
this solution won't handle convex shapes
2) It is creating too many faces and impacting fairly heavily on
performance

If it wasn't for 2, I might try my hand at fixing 1 - but I think I'm
going to have to use a basic Plane as my floor.  It won't follow the
edges of the building nicely, but at least it'll be fast.

Anyway,  since I hacked this thing together I thought I'd share.
createFaces() is where it all happens:

package
{
        import __AS3__.vec.Vector;

        import away3d.arcane;
        import away3d.core.base.*;
        import away3d.materials.*;
        import away3d.primitives.AbstractPrimitive;

        import flash.display.GraphicsPath;
        import flash.geom.Point;

        import net.nicoptere.delaunay.Delaunay;
        import net.nicoptere.delaunay.DelaunayTriangle;

        use namespace arcane;

    /**
    * Creates a 3d irregular plane within a GraphicsPath.
    */

        public class IrregularPlane extends AbstractPrimitive
        {

                private var grid:Array;
        private var _width:Number;
        private var _height:Number;
        private var _segmentsW:int;
        private var _segmentsH:int;
        private var _yUp:Boolean;
        private var _path:GraphicsPath;

                /**
                 * @inheritDoc
                 */
        protected override function buildPrimitive():void
        {
                super.buildPrimitive();

                createFaces();
        }

        /**
         * Defines the width of the plane. Defaults to 100, or the width
of the uv material (if one is applied).
         */
        public function get width():Number
        {
                return _width;
        }

        public function set width(val:Number):void
        {
                if (_width == val)
                        return;

                _width = val;
                _primitiveDirty = true;
        }

        /**
         * Defines the height of the plane. Defaults to 100, or the
height of the uv material (if one is applied).
         */
        public function get height():Number
        {
                return _height;
        }

        public function set height(val:Number):void
        {
                if (_height == val)
                        return;

                _height = val;
                _primitiveDirty = true;
        }

        /**
         * Defines the number of horizontal segments that make up the
plane. Defaults to 1.
         */
        public function get segmentsW():Number
        {
                return _segmentsW;
        }

        public function set segmentsW(val:Number):void
        {
                if (_segmentsW == val)
                        return;

                _segmentsW = val;
                _primitiveDirty = true;
        }

        /**
         * Defines the number of vertical segments that make up the
plane. Defaults to 1.
         */
        public function get segmentsH():Number
        {
                return _segmentsH;
        }

        public function set segmentsH(val:Number):void
        {
                if (_segmentsH == val)
                        return;

                _segmentsH = val;
                _primitiveDirty = true;
        }

        /**
         * Defines whether the coordinates of the plane points use a yUp
orientation (true) or a zUp orientation (false). Defaults to true.
         */
        public function get yUp():Boolean
        {
                return _yUp;
        }

        public function set yUp(val:Boolean):void
        {
                if (_yUp == val)
                        return;

                _yUp = val;
                _primitiveDirty = true;
        }

                /**
                 * Creates a new <code>Plane</code> object.
                 *
                 * @param       init                    [optional]      An 
initialisation object for specifying
default instance properties.
                 */

        public function IrregularPlane(path:GraphicsPath, init:Object
= null)
        {
            super(init);

                        _path = path;
            _width = ini.getNumber("width", 100, {min:0});
            _height = ini.getNumber("height", 100, {min:0});
            var segments:int = ini.getInt("segments", 1, {min:1});
            _segmentsW = ini.getInt("segmentsW", segments, {min:1});
            _segmentsH = ini.getInt("segmentsH", segments, {min:1});
                _yUp = ini.getBoolean("yUp", true);

            if (width*height == 0)
            {
                if (material is BitmapMaterial)
                {
                    var uvm:BitmapMaterial = material as
BitmapMaterial;
                    if (width == 0)
                        width = uvm.width;
                    if (height == 0)
                        height = uvm.height;
                }
                else
                {
                    width = 100;
                    height = 100;
                }
            }

                        type = "IrregularPlane";
                url = "primitive";
        }

                /**
                 * Returns the vertex object specified by the grid position of 
the
mesh.
                 *
                 * @param       w       The horizontal position on the 
primitive mesh.
                 * @param       h       The vertical position on the primitive 
mesh.
                 */
        public function vertex(w:int, h:int):Vertex
        {
                        if (_primitiveDirty)
                        updatePrimitive();

            return grid[h][w];
        }

                private function createFaces():void
                {
                        var points:Vector.<Point> = new Vector.<Point>;
                        var profile:Array = [];
                        //convert GraphicsPath to Points
                        for (var i:int = 0; i < _path.commands.length; i++)
                        {
                                points.push(new Point(_path.data.shift(), 
_path.data.shift()));
                        }
                        //Get triangles
                        var triangle:Vector.<DelaunayTriangle> =
Delaunay.Triangulate(points);
                        //Add triangles to mesh
                        for each (var tri:DelaunayTriangle in triangle)
                        {
                                        var p1: Vertex = new Vertex(tri.p1.x, 
0, tri.p1.y);
                                        var p2: Vertex = new Vertex(tri.p2.x, 
0, tri.p2.y);
                                        var p3: Vertex = new Vertex(tri.p3.x, 
0, tri.p3.y);
                                        trace(p1, p2, p3);
                                        addFace(createFace(p1, p2, p3));
                        }
                }

        }
}



On Mar 26, 7:46 pm, wagster <[email protected]> wrote:
> Looks very much like someone else has already done the heavy lifting:
>
> http://en.nicoptere.net/?p=10
>
> I'll grab that and have a play.
>
> On Mar 25, 1:54 pm, Fabrice3D <[email protected]> wrote:
>
> > ah well, once you have the earclipping done, and you need help for the 
> > build, just drop me a line.
> > Fabrice
>
> > On Mar 25, 2011, at 1:52 PM, wagster wrote:
>
> > > Thanks Fabrice -
>
> > > There's a fair amount of info out there on Delaunay triangulation
> > > algorithms - I could probably put together a class in AS3 - I'm just
> > > not sure how I'd translate it to a mesh after calculating it.  I'll
> > > let you know if I get anywhere with that, but I might just keep
> > > plugging away with SkinExtrude for now and see if I can't make it play
> > > nice!
>
> > > On Mar 25, 11:33 am, Fabrice3D <[email protected]> wrote:
> > >>> ) using SkinExtrude by passing in the path
> > >>> as two halves and joining them up.
>
> > >> until we do not have a delaunay mesh generator (high on my list)
> > >> you simply have to pass your angles for a L and use SkinExtrude
> > >> next issue: Projector class is not ported yet, expect distorts in 
> > >> texture.
>
> > >> I'm deep in LatheExtrude atm, which is the most complex extrude tool 
> > >> class.
> > >> after that others will follow faster...
>
> > >> Fabrice
>
> > >> On Mar 25, 2011, at 11:01 AM, wagster wrote:
>
> > >>> Ok, I've been looking into this a bit deeper and it seems to be a
> > >>> problem that a few people have come up against before, without a good
> > >>> solution yet.  I'm sure there is a solution but I may not understand
> > >>> enough about how 3D rendering works to hit upon it yet.
>
> > >>> Background: I'm working on a 3D floorplan system that allows you to
> > >>> draw the walls as paths and the floors as fills from within Flash and
> > >>> save it as a swf that gets loaded at runtime.  The walls are no
> > >>> problem: parse the swf, pull the paths out of a MovieClip called
> > >>> "Walls" and pass them to LinearExtrude to build them vertically.
> > >>> Surprisingly, the floor is more difficult.
>
> > >>> Problem: I get one closed path from a fill in Flash, but I can't
> > >>> figure out how to turn it into a mesh.
>
> > >>> Fabrice suggested (I think) using SkinExtrude by passing in the path
> > >>> as two halves and joining them up.  The problem here is that if you
> > >>> have an L-shaped room, the inside corner of the "L" gets filled in as
> > >>> well.  This has to work for all types of irregular floor layouts.
> > >>> I've been thinking that essentially what I need is some form of flood-
> > >>> fill algorithm that produces triangles, but I haven't figured out a
> > >>> reliable one myself and traditional flood-fill algorithms are all
> > >>> pixel based.
>
> > >>> Is there a way I could convert all the vertices from the path into the
> > >>> outside edges of a mesh, or rather create mesh by defining the outside
> > >>> edges?
>
> > >>> On Mar 22, 9:18 am, wagster <[email protected]> wrote:
> > >>>> Great.  I can just check the number of vertices in the path and double
> > >>>> up the end point if necessary.
>
> > >>>> On Mar 21, 11:37 pm, Fabrice3D <[email protected]> wrote:
>
> > >>>>> I've just uploaded SkinExtrude, if you have an even amount of 
> > >>>>> vertices, you should be ok...
> > >>>>> More are coming, but as usual, it happends 1 by 1 :)
> > >>>>> In meanhwile, thats all we can offer...
>
> > >>>>> Fabrice
>
> > >>>>> On Mar 21, 2011, at 11:59 PM, wagster wrote:
>
> > >>>>>> I have a 2D closed path describing a flat shape, like a fill in Flash
> > >>>>>> (that's because that's exactly what it was until I yanked it out of a
> > >>>>>> swf).  I need to pass all the vertices into a class that will 
> > >>>>>> recreate
> > >>>>>> this fill as a flat 3D object.  Could you please tell me which class 
> > >>>>>> I
> > >>>>>> should be going for?  I thought SkinExtrude was the one, but that
> > >>>>>> seems to require more than one path...
>
> > >>>>>> Oh, and thanks for your previous answer Fabrice - most helpful.

Reply via email to