From 19f6d4e4531c6e0531ee50abac3b737cdf68fe07 Mon Sep 17 00:00:00 2001 From: nathan lachenmyer Date: Thu, 14 Jul 2022 14:48:43 -0700 Subject: [PATCH] GeomIO changes --- include/cinder/GeomIo.h | 224 +++++++++++++++++++++++++------------ src/cinder/GeomIo.cpp | 238 ++++++++++++++++++++-------------------- 2 files changed, 269 insertions(+), 193 deletions(-) diff --git a/include/cinder/GeomIo.h b/include/cinder/GeomIo.h index b9190d33df..43d1115605 100644 --- a/include/cinder/GeomIo.h +++ b/include/cinder/GeomIo.h @@ -55,7 +55,7 @@ typedef std::shared_ptr SourceRef; // keep this incrementing by 1 only; some code relies on that for iterating; add corresponding entry to sAttribNames enum Attrib { POSITION, COLOR, TEX_COORD_0, TEX_COORD_1, TEX_COORD_2, TEX_COORD_3, - NORMAL, TANGENT, BITANGENT, BONE_INDEX, BONE_WEIGHT, + NORMAL, TANGENT, BITANGENT, BONE_INDEX, BONE_WEIGHT, CUSTOM_0, CUSTOM_1, CUSTOM_2, CUSTOM_3, CUSTOM_4, CUSTOM_5, CUSTOM_6, CUSTOM_7, CUSTOM_8, CUSTOM_9, NUM_ATTRIBS, USER_DEFINED = NUM_ATTRIBS }; typedef std::set AttribSet; @@ -144,7 +144,7 @@ class CI_API Source { virtual Primitive getPrimitive() const = 0; virtual uint8_t getAttribDims( Attrib attr ) const = 0; virtual AttribSet getAvailableAttribs() const = 0; - + virtual void loadInto( Target *target, const AttribSet &requestedAttribs ) const = 0; virtual Source* clone() const = 0; @@ -159,7 +159,7 @@ class CI_API Source { class CI_API Target { public: - virtual uint8_t getAttribDims( Attrib attr ) const = 0; + virtual uint8_t getAttribDims( Attrib attr ) const = 0; virtual void copyAttrib( Attrib attr, uint8_t dims, size_t strideBytes, const float *srcData, size_t count ) = 0; virtual void copyIndices( Primitive primitive, const uint32_t *source, size_t numIndices, uint8_t requiredBytesPerIndex ) = 0; @@ -170,7 +170,7 @@ class CI_API Target { static void copyIndexDataForceTriangles( Primitive primitive, const uint32_t *source, size_t numIndices, uint32_t indexOffset, uint32_t *target ); static void copyIndexDataForceTriangles( Primitive primitive, const uint32_t *source, size_t numIndices, uint16_t indexOffset, uint16_t *target ); static void copyIndexDataForceLines( Primitive primitive, const uint32_t *source, size_t numIndices, uint32_t indexOffset, uint32_t *target ); - + static void generateIndicesForceTriangles( Primitive primitive, size_t numInputIndices, uint32_t indexOffset, uint32_t *target ); static void generateIndicesForceLines( Primitive primitive, size_t numInputIndices, uint32_t indexOffset, uint32_t *target ); @@ -191,24 +191,24 @@ class CI_API Modifier { size_t getNumIndices() const { return mNumIndices; } Primitive getPrimitive() const { return mPrimitive; } AttribSet getAvailableAttribs() const { return mAvaliableAttribs; } - + size_t mNumVertices, mNumIndices; Primitive mPrimitive; AttribSet mAvaliableAttribs; - + friend class SourceMods; }; - + virtual ~Modifier() {} - + virtual Modifier* clone() const = 0; - + virtual size_t getNumVertices( const Modifier::Params &upstreamParams ) const; virtual size_t getNumIndices( const Modifier::Params &upstreamParams ) const; virtual Primitive getPrimitive( const Modifier::Params &upstreamParams ) const; virtual uint8_t getAttribDims( Attrib attr, uint8_t upstreamDims ) const; virtual AttribSet getAvailableAttribs( const Modifier::Params &upstreamParams ) const; - + virtual void process( SourceModsContext *ctx, const AttribSet &requestedAttribs ) const = 0; }; @@ -226,6 +226,7 @@ class CI_API Rect : public Source { //! Enables TEX_COORD_0 attrib and specifies corner values in clockwise order starting with the upper-left Rect& texCoords( const vec2 &upperLeft, const vec2 &upperRight, const vec2 &lowerRight, const vec2 &lowerLeft ); + Rectf getRect() const { return Rectf(mPositions[0], mPositions[3]); }; size_t getNumVertices() const override { return 4; } size_t getNumIndices() const override { return 0; } Primitive getPrimitive() const override { return Primitive::TRIANGLE_STRIP; } @@ -241,19 +242,22 @@ class CI_API Rect : public Source { std::array mColors; bool mHasColors; }; - + class CI_API RoundedRect : public Source { public: RoundedRect(); RoundedRect( const Rectf &r, float cornerRadius = 1.0f ); - + RoundedRect& rect( const Rectf &r ) { mRectPositions = r; return *this; } RoundedRect& colors( bool enable = true ) { mHasColors = enable; return *this; } RoundedRect& cornerSubdivisions( int cornerSubdivisions ); RoundedRect& cornerRadius( float cornerRadius ); RoundedRect& texCoords( const vec2 &upperLeft, const vec2 &lowerRight ); RoundedRect& colors( const ColorAf &upperLeft, const ColorAf &upperRight, const ColorAf &lowerRight, const ColorAf &lowerLeft ); - + + Rectf getRect() const { return mRectPositions; } + int getCornerSubdivisions() const { return mSubdivisions; } + float getCornerRadius() const { return mCornerRadius; } size_t getNumVertices() const override { return mNumVertices; } size_t getNumIndices() const override { return 0; } Primitive getPrimitive() const override { return Primitive::TRIANGLE_FAN; } @@ -261,12 +265,12 @@ class CI_API RoundedRect : public Source { AttribSet getAvailableAttribs() const override; void loadInto( Target *target, const AttribSet &requestedAttribs ) const override; RoundedRect* clone() const override { return new RoundedRect( *this ); } - + protected: void updateVertexCount(); void setDefaultColors(); void setDefaultTexCoords(); - + Rectf mRectPositions, mRectTexCoords; std::array mColors; bool mHasColors; @@ -290,7 +294,9 @@ class CI_API Cube : public Source { Cube& size( const vec3 &sz ) { mSize = sz; return *this; } Cube& size( float x, float y, float z ) { mSize = vec3( x, y, z ); return *this; } - size_t getNumVertices() const override; + vec3 getSize() const { return mSize; } + vec3 getSubdivisions() const { return mSubdivisions; } + size_t getNumVertices() const override; size_t getNumIndices() const override; Primitive getPrimitive() const override { return Primitive::TRIANGLES; } uint8_t getAttribDims( Attrib attr ) const override; @@ -322,7 +328,9 @@ class CI_API CubeSphere : public Source { CubeSphere& size( float x, float y, float z ) { mSize = vec3( x, y, z ); return *this; } CubeSphere& equalSpacing( bool enabled = true ) { mEqualSpacing = enabled; return *this; } - size_t getNumVertices() const override; + vec3 getSize() const { return mSize; } + vec3 getSubdivisions() const { return mSubdivisions; } + size_t getNumVertices() const override; size_t getNumIndices() const override; Primitive getPrimitive() const override { return Primitive::TRIANGLES; } uint8_t getAttribDims( Attrib attr ) const override; @@ -344,7 +352,7 @@ class CI_API Icosahedron : public Source { // Enables colors. Disabled by default. Icosahedron& colors( bool enable = true ) { mHasColors = enable; return *this; } - + size_t getNumVertices() const override; size_t getNumIndices() const override; Primitive getPrimitive() const override { return Primitive::TRIANGLES; } @@ -360,7 +368,7 @@ class CI_API Icosahedron : public Source { static float sPositions[12*3]; static float sTexCoords[60*2]; static uint32_t sIndices[60]; - + friend class Icosphere; friend class WireIcosahedron; }; @@ -374,6 +382,7 @@ class CI_API Icosphere : public Source { Icosphere& subdivisions( int sub ) { mSubdivision = (sub > 0) ? (sub + 1) : 1; mCalculationsCached = false; return *this; } + int getSubdivisions() const { return mSubdivision; } size_t getNumVertices() const override { calculate(); return mPositions.size(); } size_t getNumIndices() const override { calculate(); return mIndices.size(); } Primitive getPrimitive() const override { return Primitive::TRIANGLES; } @@ -401,6 +410,7 @@ class CI_API Teapot : public Source { Teapot& subdivisions( int sub ); + int getSubdivisions() const { return mSubdivision; } size_t getNumVertices() const override { return mNumVertices; } size_t getNumIndices() const override { return mNumIndices; } Primitive getPrimitive() const override { return Primitive::TRIANGLES; } @@ -416,7 +426,7 @@ class CI_API Teapot : public Source { static void generatePatches( float *v, float *n, float *tc, uint32_t *el, int grid ); static void buildPatchReflect( int patchNum, float *B, float *dB, float *v, float *n, float *tc, unsigned int *el, int &index, int &elIndex, int &tcIndex, int grid, bool reflectX, bool reflectY ); - static void buildPatch( vec3 patch[][4], float *B, float *dB, float *v, float *n, float *tc, + static void buildPatch( vec3 patch[][4], float *B, float *dB, float *v, float *n, float *tc, unsigned int *el, int &index, int &elIndex, int &tcIndex, int grid, const mat3 reflect, bool invertNormal ); static void getPatch( int patchNum, vec3 patch[][4], bool reverseV ); static void computeBasisFunctions( float *B, float *dB, int grid ); @@ -438,6 +448,9 @@ class CI_API Circle : public Source { Circle& radius( float radius ); Circle& subdivisions( int subdivs ); + vec2 getCenter() const { return mCenter; } + float getRadius() const { return mRadius; } + int getSubdivisions() const { return mNumSubdivisions; } size_t getNumVertices() const override; size_t getNumIndices() const override { return 0; } Primitive getPrimitive() const override { return Primitive::TRIANGLE_FAN; } @@ -464,6 +477,10 @@ class CI_API Ring : public Source { Ring& width( float width ); Ring& subdivisions( int subdivs ); + vec2 getCenter() const { return mCenter; } + float getRadius() const { return mRadius; } + float getWidth() const { return mWidth; } + int getSubdivisions() const { return mNumSubdivisions; } size_t getNumVertices() const override; size_t getNumIndices() const override { return 0; } Primitive getPrimitive() const override { return Primitive::TRIANGLE_STRIP; } @@ -493,6 +510,9 @@ class CI_API Sphere : public Source { //! Specifies the number of segments, which determines the roundness of the sphere. Sphere& subdivisions( int subdiv ) { mSubdivisions = subdiv; return *this; } + vec3 getCenter() const { return mCenter; } + float getRadius() const { return mRadius; } + int getSubdivisions() const { return mSubdivisions; } size_t getNumVertices() const override; size_t getNumIndices() const override; Primitive getPrimitive() const override { return Primitive::TRIANGLES; } @@ -527,6 +547,12 @@ class CI_API Capsule : public Source { //! Conveniently sets center, length and direction Capsule& set( const vec3 &from, const vec3 &to ); + vec3 getCenter() const { return mCenter; } + int getSubdivisionsAxis() const { return mSubdivisionsAxis; } + int getSubdivisionsHeight() const { return mSubdivisionsHeight; } + float getRadius() const { return mRadius; } + float getLength() const { return mLength; } + vec3 getDirection() const { return mDirection; } size_t getNumVertices() const override; size_t getNumIndices() const override; Primitive getPrimitive() const override { return Primitive::TRIANGLES; } @@ -565,6 +591,14 @@ class CI_API Torus : public Source { //! Specifies the major and minor radius separately. Torus& radius( float major, float minor ) { mRadiusMajor = math::max(0, major); mRadiusMinor = math::max(0, minor); return *this; } + vec3 getCenter() const { return mCenter; } + int getSubdivisionsAxis() const { return mSubdivisionsAxis; } + int getSubdivisionsHeight() const { return mSubdivisionsHeight; } + float getMajorRadius() const { return mRadiusMajor; } + float getMinorRadius() const { return mRadiusMinor; } + float getHeight() const { return mHeight; } + unsigned getTwist() const { return mTwist; } + float getTwistOffset() const { return mTwistOffset; } size_t getNumVertices() const override; size_t getNumIndices() const override; Primitive getPrimitive() const override { return Primitive::TRIANGLES; } @@ -606,7 +640,13 @@ class CI_API TorusKnot : public Source { TorusKnot& scale( const vec3 &scale ) { mScale = scale; return *this; } //! Allows you to scale the generated curve. TorusKnot& scale( float x, float y, float z ) { mScale = vec3( x, y, z ); return *this; } - + + int getSubdivisionsAxis() const { return mSubdivisionsAxis; } + int getSubdivisionsHeight() const { return mSubdivisionsHeight; } + int getParameterP() const { return mP; } + int getParameterQ() const { return mQ; } + float getRadius() const { return mRadius; } + vec3 getScale() const { return mScale; } size_t getNumVertices() const override; size_t getNumIndices() const override; Primitive getPrimitive() const override { return Primitive::TRIANGLES; } @@ -666,6 +706,16 @@ class CI_API Helix : public Torus { Helix& ratio( float ratio ) { Torus::ratio( ratio ); return *this; } //! Specifies the major and minor radius separately. Helix& radius( float major, float minor ) { Torus::radius( major, minor ); return *this; } + + vec3 getCenter() const { return mCenter; } + int getSubdivisionsAxis() const { return mSubdivisionsAxis; } + int getSubdivisionsHeight() const { return mSubdivisionsHeight; } + float getMajorRadius() const { return mRadiusMajor; } + float getMinorRadius() const { return mRadiusMinor; } + float getHeight() const { return mHeight; } + unsigned getTwist() const { return mTwist; } + float getTwistOffset() const { return mTwistOffset; } + float getNumberOfCoils() const { return mCoils; } }; class CI_API Cylinder : public Source { @@ -692,6 +742,13 @@ class CI_API Cylinder : public Source { //! Conveniently sets origin, height and direction so that the center of the base is \a from and the center of the apex is \a to. Cylinder& set( const vec3 &from, const vec3 &to ); + vec3 getOrigin() const { return mOrigin; } + int getSubdivisionsAxis() const { return mSubdivisionsAxis; } + int getSubdivisionsHeight() const { return mSubdivisionsHeight; } + int getSubdivisionsCap() const { return mSubdivisionsCap; } + float getRadius() const { return mRadiusBase; } + float getHeight() const { return mHeight; } + vec3 getDirection() const { return mDirection; } size_t getNumVertices() const override; size_t getNumIndices() const override; Primitive getPrimitive() const override { return Primitive::TRIANGLES; } @@ -744,6 +801,14 @@ class CI_API Cone : public Cylinder { Cone& direction( const vec3 &direction ) { Cylinder::direction( direction ); return *this; } //! Conveniently sets origin, height and direction. Cone& set( const vec3 &from, const vec3 &to ) { Cylinder::set( from, to ); return *this; } + + vec3 getOrigin() const { return mOrigin; } + int getSubdivisionsAxis() const { return mSubdivisionsAxis; } + int getSubdivisionsHeight() const { return mSubdivisionsHeight; } + float getBaseRadius() const { return mRadiusBase; } + float getApexRadius() const { return mRadiusApex; } + float getHeight() const { return mHeight; } + vec3 getDirection() const { return mDirection; } }; //! Defaults to a plane on the z axis, origin = [0, 0, 0], normal = [0, 1, 0] @@ -760,6 +825,10 @@ class CI_API Plane : public Source { Plane& origin( const vec3 &origin ) { mOrigin = origin; return *this; } Plane& normal( const vec3 &normal ); + vec2 getSubdivisions() const { return mSubdivisions; } + vec3 getOrigin() const { return mOrigin; } + vec3 getNormal() const { return glm::cross(mAxisU, mAxisV); } + vec2 getSize() const { return mSize; } size_t getNumVertices() const override { return ( mSubdivisions.x + 1 ) * ( mSubdivisions.y + 1 ); } size_t getNumIndices() const override { return mSubdivisions.x * mSubdivisions.y * 6; } Primitive getPrimitive() const override { return Primitive::TRIANGLES; } @@ -777,7 +846,7 @@ class CI_API Plane : public Source { class CI_API Extrude : public Source { public: Extrude( const Shape2d &shape, float distance, float approximationScale = 1.0f ); - + //! Sets the distance of extrusion along the axis. Extrude& distance( float dist ) { mDistance = dist; return *this; } //! Enables or disables front and back caps. Enabled by default. @@ -789,6 +858,8 @@ class CI_API Extrude : public Source { //! Sets the number of subdivisions along the axis of extrusion Extrude& subdivisions( int sub ) { mSubdivisions = std::max( 1, sub ); updatePathSubdivision(); return *this; } + float getDistance() const { return mDistance; } + int getSubdivisions() const { return mSubdivisions; } size_t getNumVertices() const override; size_t getNumIndices() const override; Primitive getPrimitive() const override { return Primitive::TRIANGLES; } @@ -796,11 +867,11 @@ class CI_API Extrude : public Source { AttribSet getAvailableAttribs() const override; void loadInto( Target *target, const AttribSet &requestedAttribs ) const override; Extrude* clone() const override { return new Extrude( *this ); } - + protected: void updatePathSubdivision(); void calculate( std::vector *positions, std::vector *normals, std::vector *texCoords, std::vector *indices ) const; - + std::vector mPaths; float mApproximationScale; float mDistance; @@ -808,14 +879,14 @@ class CI_API Extrude : public Source { int mSubdivisions; std::shared_ptr mCap; Rectf mCapBounds; - + std::vector> mPathSubdivisionPositions, mPathSubdivisionTangents; }; class CI_API ExtrudeSpline : public Source { public: ExtrudeSpline( const Shape2d &shape, const ci::BSpline<3,float> &spline, int splineSubdivisions = 10, float approximationScale = 1.0f ); - + //! Enables or disables front and back caps. Enabled by default. ExtrudeSpline& caps( bool caps ) { mFrontCap = mBackCap = caps; return *this; } //! Enables or disables front cap. Enabled by default. @@ -827,6 +898,7 @@ class CI_API ExtrudeSpline : public Source { //! Sets the function used to calculate the width of the Shape2d at each subdivision ExtrudeSpline& thickness( const std::function &fn ) { mThicknessFn = fn; return *this; } + int getSubdivisions() const { return mSubdivisions; } size_t getNumVertices() const override; size_t getNumIndices() const override; Primitive getPrimitive() const override { return Primitive::TRIANGLES; } @@ -834,11 +906,11 @@ class CI_API ExtrudeSpline : public Source { AttribSet getAvailableAttribs() const override; void loadInto( Target *target, const AttribSet &requestedAttribs ) const override; ExtrudeSpline* clone() const override { return new ExtrudeSpline( *this ); } - + protected: void updatePathSubdivision(); void calculate( std::vector *positions, std::vector *normals, std::vector *texCoords, std::vector *indices ) const; - + std::vector mPaths; std::vector mSplineFrames; std::vector mSplineTimes; @@ -848,7 +920,7 @@ class CI_API ExtrudeSpline : public Source { std::shared_ptr mCap; Rectf mCapBounds; std::function mThicknessFn; - + std::vector> mPathSubdivisionPositions, mPathSubdivisionTangents; std::vector mPathSubdivisionLengths; }; @@ -866,7 +938,7 @@ class CI_API BSpline : public Source { AttribSet getAvailableAttribs() const override; void loadInto( Target *target, const AttribSet &requestedAttribs ) const override; BSpline* clone() const override { return new BSpline( *this ); } - + protected: template void init( const ci::BSpline<2,T> &spline, int subdivisions ); @@ -892,7 +964,7 @@ class CI_API WireSource : public Source { protected: WireSource() {} - virtual ~WireSource() {} + virtual ~WireSource() {} }; @@ -913,6 +985,12 @@ class CI_API WireCapsule : public WireSource { //! Conveniently sets center, length and direction WireCapsule& set( const vec3 &from, const vec3 &to ); + vec3 getCenter() const { return mCenter; } + int getSubdivisionsAxis() const { return mSubdivisionsAxis; } + int getSubdivisionsHeight() const { return mSubdivisionsHeight; } + float getRadius() const { return mRadius; } + float getLength() const { return mLength; } + vec3 getDirection() const { return mDirection; } size_t getNumVertices() const override; void loadInto( Target *target, const AttribSet &requestedAttribs ) const override; WireCapsule* clone() const override { return new WireCapsule( *this ); } @@ -954,23 +1032,23 @@ class CI_API WireCircle : public Source { int mNumSegments; size_t mNumVertices; }; - + class CI_API WireRoundedRect : public WireSource { public: WireRoundedRect(); WireRoundedRect( const Rectf &r, float cornerRadius = 1.0f ); - + WireRoundedRect& rect( const Rectf &r ) { mRectPositions = r; return *this; } WireRoundedRect& cornerSubdivisions( int cornerSubdivisions ); WireRoundedRect& cornerRadius( float cornerRadius ); - + size_t getNumVertices() const override { return mNumVertices; } void loadInto( Target *target, const AttribSet &requestedAttribs ) const override; WireRoundedRect* clone() const override { return new WireRoundedRect( *this ); } - + protected: void updateVertexCount(); - + Rectf mRectPositions; int mCornerSubdivisions, mNumVertices; float mCornerRadius; @@ -1000,7 +1078,7 @@ class CI_API WireCube : public WireSource { { mSubdivisions = glm::max( ivec3( 1 ), subdivisions ); } - + WireCube& subdivisions( int sub ) { mSubdivisions = ivec3( std::max( 1, sub ) ); return *this; } WireCube& subdivisionsX( int sub ) { mSubdivisions.x = std::max( 1, sub ); return *this; } WireCube& subdivisionsY( int sub ) { mSubdivisions.y = std::max( 1, sub ); return *this; } @@ -1011,7 +1089,7 @@ class CI_API WireCube : public WireSource { size_t getNumVertices() const override { return ( mSubdivisions.x - 1 ) * 8 + ( mSubdivisions.y - 1 ) * 8 + ( mSubdivisions.z - 1 ) * 8 + 24; } void loadInto( Target *target, const AttribSet &requestedAttribs ) const override; WireCube* clone() const override { return new WireCube( *this ); } - + protected: ivec3 mSubdivisions; vec3 mSize; @@ -1217,7 +1295,7 @@ class CI_API Transform : public Modifier { const mat4& getMatrix() const { return mTransform; } //! Sets the mat4 used to transform positions, normals and tangents. void setMatrix( const mat4 &transform ) { mTransform = transform; } - + // Inherited from Modifier Modifier* clone() const override { return new Transform( mTransform ); } uint8_t getAttribDims( Attrib attr, uint8_t upstreamDims ) const override; @@ -1268,7 +1346,7 @@ class CI_API Twist : public Modifier { Modifier* clone() const override { return new Twist( *this ); } void process( SourceModsContext *ctx, const AttribSet &requestedAttribs ) const override; - + protected: vec3 mAxisStart, mAxisEnd; float mStartAngle, mEndAngle; @@ -1296,16 +1374,16 @@ class CI_API ColorFromAttrib : public Modifier { ColorFromAttrib( Attrib attrib, const std::function &fn ) : mAttrib( attrib ), mFnColor3( fn ) {} - + Attrib getAttrib() const { return mAttrib; } ColorFromAttrib& attrib( Attrib attrib ) { mAttrib = attrib; return *this; } Modifier* clone() const override { return new ColorFromAttrib( mAttrib, mFnColor2, mFnColor3 ); } uint8_t getAttribDims( Attrib attr, uint8_t upstreamDims ) const override; AttribSet getAvailableAttribs( const Modifier::Params &upstreamParams ) const override; - + void process( SourceModsContext *ctx, const AttribSet &requestedAttribs ) const override; - + protected: ColorFromAttrib( Attrib attrib, const std::function &fn2, const std::function &fn3 ) : mAttrib( attrib ), mFnColor2( fn2 ), mFnColor3( fn3 ) @@ -1347,7 +1425,7 @@ class AttribFn : public Modifier { typedef typename std::function FN; static const int SRCDIM = sizeof(S)/ sizeof(float); static const int DSTDIM = sizeof(D)/ sizeof(float); - + AttribFn( Attrib src, Attrib dst, const FN &fn ) : mSrcAttrib( src ), mDstAttrib( dst ), mFn( fn ) {} @@ -1355,13 +1433,13 @@ class AttribFn : public Modifier { AttribFn( Attrib attrib, const FN &fn ) : mSrcAttrib( attrib ), mDstAttrib( attrib ), mFn( fn ) {} - + Modifier* clone() const override { return new AttribFn( mSrcAttrib, mDstAttrib, mFn ); } uint8_t getAttribDims( Attrib attr, uint8_t upstreamDims ) const override; AttribSet getAvailableAttribs( const Modifier::Params &upstreamParams ) const override; - + void process( SourceModsContext *ctx, const AttribSet &requestedAttribs ) const override; - + protected: geom::Attrib mSrcAttrib, mDstAttrib; FN mFn; @@ -1395,7 +1473,7 @@ class CI_API Tangents : public Modifier { uint8_t getAttribDims( Attrib attr, uint8_t upstreamDims ) const override; AttribSet getAvailableAttribs( const Modifier::Params &upstreamParams ) const override; - + Modifier* clone() const override { return new Tangents; } void process( SourceModsContext *ctx, const AttribSet &requestedAttribs ) const override; }; @@ -1420,13 +1498,13 @@ class CI_API Remove : public Modifier { Remove( Attrib attrib ) : mAttrib( attrib ) {} - + uint8_t getAttribDims( Attrib attr, uint8_t upstreamDims ) const override; - AttribSet getAvailableAttribs( const Modifier::Params &upstreamParams ) const override; - + AttribSet getAvailableAttribs( const Modifier::Params &upstreamParams ) const override; + Modifier* clone() const override { return new Remove( mAttrib ); } void process( SourceModsContext *ctx, const AttribSet &requestedAttribs ) const override; - + protected: Attrib mAttrib; }; @@ -1437,11 +1515,11 @@ class CI_API Bounds : public Modifier { Bounds( AxisAlignedBox *result, Attrib attrib = POSITION ) : mResult( result ), mAttrib( attrib ) {} - - + + Modifier* clone() const override { return new Bounds( mResult, mAttrib ); } void process( SourceModsContext *ctx, const AttribSet &requestedAttribs ) const override; - + protected: AxisAlignedBox *mResult; Attrib mAttrib; @@ -1453,10 +1531,10 @@ class CI_API Subdivide : public Modifier { public: Subdivide() {} - + size_t getNumVertices( const Modifier::Params &upstreamParams ) const override; size_t getNumIndices( const Modifier::Params &upstreamParams ) const override; - + Modifier* clone() const override { return new Subdivide(); } void process( SourceModsContext *ctx, const AttribSet &requestedAttribs ) const override; }; @@ -1473,12 +1551,12 @@ class CI_API SourceModsContext : public Target { // called by SourceMods::loadInto() void loadInto( Target *target, const AttribSet &requestedAttribs ); - + // Target virtuals; also used by Modifiers uint8_t getAttribDims( Attrib attr ) const override; void copyAttrib( Attrib attr, uint8_t dims, size_t strideBytes, const float *srcData, size_t count ) override; void copyIndices( Primitive primitive, const uint32_t *source, size_t numIndices, uint8_t requiredBytesPerIndex ) override; - + //! Appends vertex data to existing data for \a attr. \a dims must match existing data. void appendAttrib( Attrib attr, uint8_t dims, const float *srcData, size_t count ); void clearAttrib( Attrib attr ); @@ -1490,29 +1568,29 @@ class CI_API SourceModsContext : public Target { size_t getNumIndices() const; Primitive getPrimitive() const; AttribSet getAvailableAttribs() const; - + void processUpstream( const AttribSet &requestedAttribs ); float* getAttribData( Attrib attr ); const float* getAttribData( Attrib attr ) const { return const_cast( this )->getAttribData( attr ); } uint32_t* getIndicesData(); const uint32_t* getIndicesData() const { return const_cast( this )->getIndicesData(); } - + void preload( const AttribSet &requestedAttribs ); void combine( const SourceModsContext &rhs ); void complete( Target *target, const AttribSet &requestedAttribs ); - + private: const Source *mSource; std::vector mModiferStack; - + const AttribSet *mAttribMask; - + size_t mNumVertices; std::map mAttribInfo; std::map> mAttribData; std::map mAttribCount; - + std::unique_ptr mIndices; size_t mNumIndices; uint8_t mIndicesRequiredBytes; @@ -1561,15 +1639,15 @@ class CI_API SourceMods : public Source { else mSourcePtr = source; } - + void append( const Modifier &modifier ); void append( const Source &source ); void append( const SourceMods &sourceMods ); - SourceMods& operator=( const SourceMods &rhs ) { copyImpl( rhs ); return *this; } + SourceMods& operator=( const SourceMods &rhs ) { copyImpl( rhs ); return *this; } SourceMods& operator&=( const SourceMods &sourceMods ) { append( sourceMods ); return *this; } - SourceMods& operator&=( const Source &source ) { append( source ); return *this; } - + SourceMods& operator&=( const Source &source ) { append( source ); return *this; } + const std::vector>& getModifiers() const { return mModifiers; } const Source* getSource() const { return mSourcePtr; } //! Not generally useful. Use getSource() instead. Maps to nullptr when the SourceMods is not responsible for ownership. @@ -1587,16 +1665,16 @@ class CI_API SourceMods : public Source { protected: void copyImpl( const SourceMods &rhs ); void cacheVariables() const; - + const Source* mSourcePtr; // null if we have children std::unique_ptr mSourceStorage; // null if we don't have ownership std::vector> mModifiers; - + mutable bool mVariablesCached; mutable std::vector mParamsStack; - + std::vector> mChildren; - + friend class SourceModsContext; }; diff --git a/src/cinder/GeomIo.cpp b/src/cinder/GeomIo.cpp index 8a48f60586..582b21ed9c 100644 --- a/src/cinder/GeomIo.cpp +++ b/src/cinder/GeomIo.cpp @@ -131,7 +131,7 @@ size_t BufferLayout::calcRequiredStorage( size_t numVertices ) const { if( numVertices == 0 ) return 0; - + size_t result = 0; for( auto &attrib : mAttribs ) { size_t stride = attrib.getStride(); @@ -139,7 +139,7 @@ size_t BufferLayout::calcRequiredStorage( size_t numVertices ) const stride = attrib.getByteSize(); result = std::max( result, attrib.getOffset() + (numVertices-1) * stride + attrib.getByteSize() ); } - + return result; } @@ -206,7 +206,7 @@ void copyData( uint8_t srcDimensions, size_t srcStrideBytes, const float *srcDat for( size_t v = 0; v < numElements; ++v ) { for( uint8_t d = 0; d < dstDimensions; ++d ) dstData[d] = 0; - dstData = (float*)((uint8_t*)dstData + dstStrideBytes); + dstData = (float*)((uint8_t*)dstData + dstStrideBytes); } } else if( srcStrideBytes == srcDimensions * sizeof(float) ) // call equivalent method that doesn't support srcStrideBytes @@ -269,9 +269,9 @@ void copyData( uint8_t srcDimensions, const float *srcData, size_t numElements, for( size_t v = 0; v < numElements; ++v ) { for( uint8_t d = 0; d < dstDimensions; ++d ) dstData[d] = 0; - dstData = (float*)((uint8_t*)dstData + dstStrideBytes); + dstData = (float*)((uint8_t*)dstData + dstStrideBytes); } - } + } else if( (srcDimensions == dstDimensions) && (dstStrideBytes == dstDimensions * sizeof(float)) ) { memcpy( dstData, srcData, numElements * srcDimensions * sizeof(float) ); } @@ -320,7 +320,7 @@ void copyData( uint8_t srcDimensions, const float *srcData, size_t numElements, } -namespace { +namespace { template bool indicesInRange( const uint32_t *indices, size_t numIndices, T indexOffset ) { @@ -374,7 +374,7 @@ void copyIndexDataForceTrianglesImpl( Primitive primitive, const uint32_t *sourc } break; case Primitive::TRIANGLE_FAN: { // ABC, ACD, ADE, etc - CI_ASSERT( indexOffset == 0 ); // unsupported with TRIANGLE_FAN + CI_ASSERT( indexOffset == 0 ); // unsupported with TRIANGLE_FAN if( numIndices < 3 ) return; size_t outIdx = 0; @@ -390,7 +390,7 @@ void copyIndexDataForceTrianglesImpl( Primitive primitive, const uint32_t *sourc } } -// Lengyel, Eric. "Computing Tangent Space Basis Vectors for an Arbitrary Mesh". +// Lengyel, Eric. "Computing Tangent Space Basis Vectors for an Arbitrary Mesh". // Terathon Software 3D Graphics Library, 2001. // http://www.terathon.com/code/tangent.html template @@ -722,7 +722,7 @@ RoundedRect::RoundedRect() setDefaultColors(); setDefaultTexCoords(); } - + RoundedRect::RoundedRect( const Rectf &r, float cornerRadius ) : mSubdivisions( -1 ), mCornerRadius( cornerRadius ), mHasColors( false ), mNumVertices( 0 ) { @@ -731,7 +731,7 @@ RoundedRect::RoundedRect( const Rectf &r, float cornerRadius ) setDefaultColors(); setDefaultTexCoords(); } - + RoundedRect& RoundedRect::cornerSubdivisions( int cornerSubdivisions ) { mSubdivisions = cornerSubdivisions; @@ -755,23 +755,23 @@ RoundedRect& RoundedRect::texCoords( const vec2 &upperLeft, const vec2 &lowerRig RoundedRect& RoundedRect::colors( const ColorAf &upperLeft, const ColorAf &upperRight, const ColorAf &lowerRight, const ColorAf &lowerLeft ) { mHasColors = true; - mColors[0] = lowerLeft; - mColors[1] = lowerRight; - mColors[2] = upperRight; + mColors[0] = lowerLeft; + mColors[1] = lowerRight; + mColors[2] = upperRight; mColors[3] = upperLeft; return *this; } - + void RoundedRect::updateVertexCount() { if( mSubdivisions <= 0 ) { mSubdivisions = (int)math::floor( mCornerRadius * M_PI * 2 / 4 ); } if( mSubdivisions < 2 ) mSubdivisions = 2; - + mNumVertices = ( mSubdivisions + 1 ) * 4 + 2; } - + uint8_t RoundedRect::getAttribDims( Attrib attr ) const { switch( attr ) { @@ -789,7 +789,7 @@ AttribSet RoundedRect::getAvailableAttribs() const { return { Attrib::POSITION, Attrib::NORMAL, Attrib::TEX_COORD_0, Attrib::COLOR, Attrib::TANGENT }; } - + void RoundedRect::loadInto( cinder::geom::Target *target, const AttribSet &requestedAttribs ) const { std::vector positions; @@ -807,16 +807,16 @@ void RoundedRect::loadInto( cinder::geom::Target *target, const AttribSet &reque std::vector tangents; if( requestedAttribs.count( geom::Attrib::TANGENT ) ) tangents.resize( mNumVertices ); - + auto posCenter = mRectPositions.getCenter(); auto texCenter = mRectTexCoords.getCenter(); - + auto bufferPositions = ! positions.empty(); auto bufferTexCoords = ! texCoords.empty(); auto bufferNormals = ! normals.empty(); auto bufferTangents = ! tangents.empty(); auto bufferColors = ! colors.empty(); - + if( bufferPositions ) positions[0] = posCenter; if( bufferTexCoords ) @@ -889,7 +889,7 @@ void RoundedRect::loadInto( cinder::geom::Target *target, const AttribSet &reque auto colorU1 = lerp( mColors[0], mColors[1], currentTexCoord.x / mRectTexCoords.getWidth() ); colors[tri] = lerp( colorU0, colorU1, currentTexCoord.y / mRectTexCoords.getHeight() ); } - + if( bufferPositions ) target->copyAttrib( geom::Attrib::POSITION, 2, 0, value_ptr( *positions.data() ), positions.size() ); if( bufferTexCoords ) @@ -901,7 +901,7 @@ void RoundedRect::loadInto( cinder::geom::Target *target, const AttribSet &reque if( bufferColors ) target->copyAttrib( geom::Attrib::COLOR, 4, 0, value_ptr( *colors.data() ), colors.size() ); } - + void RoundedRect::setDefaultColors() { mColors[0] = ColorAf( 1.0f, 0.0f, 0.0f, 1.0f ); // lower-left @@ -940,8 +940,7 @@ Cube& Cube::colors( const ColorAf &posX, const ColorAf &negX, const ColorAf &pos return *this; } -size_t Cube::getNumVertices() const -{ +size_t Cube::getNumVertices() const { return 2 * ( (mSubdivisions.x+1) * (mSubdivisions.y+1) ) // +-Z + 2 * ( (mSubdivisions.y+1) * (mSubdivisions.z+1) ) // +-X + 2 * ( (mSubdivisions.x+1) * (mSubdivisions.z+1) ); // +-Y @@ -964,7 +963,7 @@ uint8_t Cube::getAttribDims( Attrib attr ) const case Attrib::TANGENT: return 3; default: return 0; - } + } } AttribSet Cube::getAvailableAttribs() const @@ -1026,9 +1025,9 @@ void Cube::loadInto( Target *target, const AttribSet &requestedAttribs ) const vector *normalsPtr = nullptr; vector *colorsPtr = nullptr; vector *texCoordsPtr = nullptr; - + const size_t numVertices = getNumVertices(); - + // reserve room in vectors and set pointers to non-null for normals, texcoords and colors as appropriate positions.reserve( numVertices ); indices.reserve( getNumIndices() ); @@ -1046,7 +1045,7 @@ void Cube::loadInto( Target *target, const AttribSet &requestedAttribs ) const } vec3 sz = 0.5f * mSize; - + // +X generateFace( vec3(sz.x,0,0), vec3(0,0,sz.z), vec3(0,sz.y,0), mSubdivisions.z, mSubdivisions.y, &positions, normalsPtr, mColors[0], colorsPtr, texCoordsPtr, &indices ); @@ -1078,7 +1077,7 @@ void Cube::loadInto( Target *target, const AttribSet &requestedAttribs ) const if( requestedAttribs.count( geom::TANGENT ) ) { vector tangents; calculateTangents( getNumIndices(), indices.data(), numVertices, positions.data(), normals.data(), texCoords.data(), &tangents, nullptr ); - + if( requestedAttribs.count( geom::TANGENT ) ) target->copyAttrib( Attrib::TANGENT, 3, 0, (const float*)tangents.data(), numVertices ); } @@ -1111,8 +1110,7 @@ CubeSphere& CubeSphere::colors( const ColorAf &posX, const ColorAf &negX, const return *this; } -size_t CubeSphere::getNumVertices() const -{ +size_t CubeSphere::getNumVertices() const { return 2 * ( (mSubdivisions.x+1) * (mSubdivisions.y+1) ) // +-Z + 2 * ( (mSubdivisions.y+1) * (mSubdivisions.z+1) ) // +-X + 2 * ( (mSubdivisions.x+1) * (mSubdivisions.z+1) ); // +-Y @@ -1135,7 +1133,7 @@ uint8_t CubeSphere::getAttribDims( Attrib attr ) const case Attrib::TANGENT: return 3; default: return 0; - } + } } AttribSet CubeSphere::getAvailableAttribs() const @@ -1153,9 +1151,9 @@ void CubeSphere::loadInto( Target *target, const AttribSet &requestedAttribs ) c vector *normalsPtr = nullptr; vector *colorsPtr = nullptr; vector *texCoordsPtr = nullptr; - + const size_t numVertices = getNumVertices(); - + // reserve room in vectors and set pointers to non-null for normals, texcoords and colors as appropriate positions.reserve( numVertices ); indices.reserve( getNumIndices() ); @@ -1171,7 +1169,7 @@ void CubeSphere::loadInto( Target *target, const AttribSet &requestedAttribs ) c texCoords.reserve( numVertices ); texCoordsPtr = &texCoords; } - + // +X generateFace( vec3(1,0,0), vec3(0,0,1), vec3(0,1,0), mSubdivisions.z, mSubdivisions.y, &positions, normalsPtr, mColors[0], colorsPtr, texCoordsPtr, &indices ); @@ -1222,7 +1220,7 @@ void CubeSphere::loadInto( Target *target, const AttribSet &requestedAttribs ) c if( requestedAttribs.count( geom::TANGENT ) ) { vector tangents; calculateTangents( getNumIndices(), indices.data(), numVertices, positions.data(), normals.data(), texCoords.data(), &tangents, nullptr ); - + if( requestedAttribs.count( geom::TANGENT ) ) target->copyAttrib( Attrib::TANGENT, 3, 0, (const float*)tangents.data(), numVertices ); } @@ -1236,7 +1234,7 @@ void CubeSphere::loadInto( Target *target, const AttribSet &requestedAttribs ) c #undef PHI // take the reciprocal of phi, to obtain an icosahedron that fits a unit cube #define PHI (1.0f / ((1.0f + math::sqrt(5.0f)) / 2.0f)) -float Icosahedron::sPositions[12*3] = { +float Icosahedron::sPositions[12*3] = { -PHI, 1.0f, 0.0f, PHI, 1.0f, 0.0f, -PHI,-1.0f, 0.0f, PHI,-1.0f, 0.0f, 0.0f, -PHI, 1.0f, 0.0f, PHI, 1.0f, 0.0f, -PHI,-1.0f, 0.0f, PHI,-1.0f, 1.0f, 0.0f, -PHI, 1.0f, 0.0f, PHI, -1.0f, 0.0f, -PHI, -1.0f, 0.0f, PHI }; @@ -1346,7 +1344,7 @@ void Icosahedron::loadInto( Target *target, const AttribSet & /*requestedAttribs vector positions, normals, colors; vector texcoords; vector indices; - + calculate( &positions, &normals, &colors, &texcoords, &indices ); target->copyAttrib( Attrib::POSITION, 3, 0, value_ptr( *positions.data() ), positions.size() ); @@ -1798,7 +1796,7 @@ void Teapot::loadInto( Target *target, const AttribSet &requestedAttribs ) const { vector positions, normals, texCoords; vector indices; - + calculate( &positions, &normals, &texCoords, &indices ); target->copyAttrib( Attrib::POSITION, 3, 0, positions.data(), mNumVertices ); @@ -2099,7 +2097,7 @@ void Sphere::loadInto( Target *target, const AttribSet &requestedAttribs ) const *indexIt++ = (uint32_t)(r * numSegments + s); } } - + target->copyAttrib( Attrib::POSITION, 3, 0, value_ptr( *positions.data() ), positions.size() ); target->copyAttrib( Attrib::NORMAL, 3, 0, value_ptr( *normals.data() ), normals.size() ); target->copyAttrib( Attrib::TEX_COORD_0, 2, 0, value_ptr( *texCoords.data() ), texCoords.size() ); @@ -2108,7 +2106,7 @@ void Sphere::loadInto( Target *target, const AttribSet &requestedAttribs ) const if( requestedAttribs.count( geom::TANGENT ) ) { vector tangents; calculateTangents( indices.size(), indices.data(), positions.size(), positions.data(), normals.data(), texCoords.data(), &tangents, nullptr ); - + if( requestedAttribs.count( geom::TANGENT ) ) target->copyAttrib( Attrib::TANGENT, 3, 0, (const float*)tangents.data(), tangents.size() ); } @@ -2201,7 +2199,7 @@ void Capsule::calculateRing( size_t segments, float radius, float y, float dy, float v = 0.5f - ((mRadius * y + mLength * dy) / (2.0f * mRadius + mLength)); texCoords->emplace_back( u, v ); } - + if( colors ) { float g = 0.5f + ((mRadius * y + mLength * dy) / (2.0f * mRadius + mLength)); colors->emplace_back( x * 0.5f + 0.5f, g, z * 0.5f + 0.5f ); @@ -2261,7 +2259,7 @@ void Capsule::loadInto( Target *target, const AttribSet &requestedAttribs ) cons if( requestedAttribs.count( geom::TANGENT ) ) { vector tangents; calculateTangents( indices.size(), indices.data(), positions.size(), positions.data(), normals.data(), texCoords.data(), &tangents, nullptr ); - + if( requestedAttribs.count( geom::TANGENT ) ) target->copyAttrib( Attrib::TANGENT, 3, 0, (const float*)tangents.data(), tangents.size() ); } @@ -2395,7 +2393,7 @@ void Torus::loadInto( Target *target, const AttribSet &requestedAttribs ) const if( requestedAttribs.count( geom::TANGENT ) ) { vector tangents; calculateTangents( indices.size(), indices.data(), positions.size(), positions.data(), normals.data(), texCoords.data(), &tangents, nullptr ); - + if( requestedAttribs.count( geom::TANGENT ) ) target->copyAttrib( Attrib::TANGENT, 3, 0, (const float*)tangents.data(), tangents.size() ); } @@ -2503,8 +2501,8 @@ void TorusKnot::calculate( std::vector *positions, std::vector *norm ( *texCoords )[idx].x = float( i ) / mSubdivisionsHeight; if( tangents ) - ( *tangents )[idx] = T; - + ( *tangents )[idx] = T; + if( colors ) ( *colors )[idx] = ( *normals )[idx] * 0.5f + 0.5f; } @@ -2721,7 +2719,7 @@ void Cylinder::loadInto( Target *target, const AttribSet &requestedAttribs ) con if( requestedAttribs.count( geom::TANGENT ) ) { vector tangents; calculateTangents( indices.size(), indices.data(), positions.size(), positions.data(), normals.data(), texCoords.data(), &tangents, nullptr ); - + if( requestedAttribs.count( geom::TANGENT ) ) target->copyAttrib( Attrib::TANGENT, 3, 0, (const float*)tangents.data(), tangents.size() ); } @@ -2834,11 +2832,11 @@ void Plane::loadInto( Target *target, const AttribSet &requestedAttribs ) const if( requestedAttribs.count( geom::TANGENT ) ) { vector tangents; calculateTangents( getNumIndices(), indices.data(), positions.size(), positions.data(), normals.data(), texCoords.data(), &tangents, nullptr ); - + if( requestedAttribs.count( geom::TANGENT ) ) target->copyAttrib( Attrib::TANGENT, 3, 0, (const float*)tangents.data(), tangents.size() ); } - + target->copyIndices( Primitive::TRIANGLES, indices.data(), indices.size(), 4 ); } @@ -2855,7 +2853,7 @@ uint8_t Transform::getAttribDims( Attrib attr, uint8_t upstreamDims ) const void Transform::process( SourceModsContext *ctx, const AttribSet &requestedAttribs ) const { ctx->processUpstream( requestedAttribs ); - + const size_t numVertices = ctx->getNumVertices(); if( ctx->getAttribDims( POSITION ) == 2 ) { @@ -2878,7 +2876,7 @@ void Transform::process( SourceModsContext *ctx, const AttribSet &requestedAttri } else if( ctx->getAttribDims( POSITION ) != 0 ) CI_LOG_W( "Unsupported dimension for geom::POSITION passed to geom::Transform" ); - + // we'll make the sort of modification to our normals (if they're present) // using the inverse transpose of 'mTransform' if( ctx->getAttribDims( NORMAL ) == 3 ) { @@ -2907,7 +2905,7 @@ void Transform::process( SourceModsContext *ctx, const AttribSet &requestedAttri void Twist::process( SourceModsContext *ctx, const AttribSet &requestedAttribs ) const { ctx->processUpstream( requestedAttribs ); - + const size_t numVertices = ctx->getNumVertices(); const float invAxisLength = 1.0f / distance( mAxisStart, mAxisEnd ); const vec3 axisDir = ( mAxisEnd - mAxisStart ) * vec3( invAxisLength ); @@ -2919,7 +2917,7 @@ void Twist::process( SourceModsContext *ctx, const AttribSet &requestedAttribs ) normals = reinterpret_cast( ctx->getAttribData( NORMAL ) ); if( ctx->getAttribDims( TANGENT ) == 3 ) tangents = reinterpret_cast( ctx->getAttribData( TANGENT ) ); - + for( size_t v = 0; v < numVertices; ++v ) { // find the 't' value of the point on the axis that inPosition is closest to float closestDist = dot( positions[v] - mAxisStart, axisDir ); @@ -2979,7 +2977,7 @@ size_t Lines::calcNumIndices( Primitive primitive, size_t upstreamNumIndices, si void Lines::process( SourceModsContext *ctx, const AttribSet &requestedAttribs ) const { ctx->processUpstream( requestedAttribs ); - + const size_t numInIndices = ctx->getNumIndices(); const size_t numInVertices = ctx->getNumVertices(); const size_t numOutIndices = calcNumIndices( ctx->getPrimitive(), numInIndices, numInVertices ); @@ -3004,7 +3002,7 @@ void Lines::process( SourceModsContext *ctx, const AttribSet &requestedAttribs ) outIndices.push_back( (uint32_t)i ); outIndices.push_back( (uint32_t)(i + 1) ); } } - + ctx->copyIndices( geom::LINES, outIndices.data(), outIndices.size(), 4 ); } break; @@ -3028,7 +3026,7 @@ void Lines::process( SourceModsContext *ctx, const AttribSet &requestedAttribs ) outIndices.push_back( (uint32_t)j ); outIndices.push_back( (uint32_t)i ); } } - + ctx->copyIndices( geom::LINES, outIndices.data(), outIndices.size(), 4 ); } break; @@ -3050,7 +3048,7 @@ void Lines::process( SourceModsContext *ctx, const AttribSet &requestedAttribs ) outIndices.push_back( i + 2 ); outIndices.push_back( i + 0 ); } } - + ctx->copyIndices( geom::LINES, outIndices.data(), outIndices.size(), 4 ); } break; @@ -3072,7 +3070,7 @@ void Lines::process( SourceModsContext *ctx, const AttribSet &requestedAttribs ) outIndices.push_back( i + 2 ); outIndices.push_back( i + 0 ); } } - + ctx->copyIndices( geom::LINES, outIndices.data(), outIndices.size(), 4 ); } break; @@ -3139,7 +3137,7 @@ void ColorFromAttrib::process( SourceModsContext *ctx, const AttribSet &requeste unique_ptr mColorData( new float[numVertices * 3] ); uint8_t inputAttribDims = ctx->getAttribDims( mAttrib ); const float* inputAttribData = ctx->getAttribData( mAttrib ); - + if( mFnColor2 ) { if( inputAttribDims == 2 ) processColorAttrib( reinterpret_cast( inputAttribData ), reinterpret_cast( mColorData.get() ), mFnColor2, numVertices ); @@ -3182,7 +3180,7 @@ void Constant::process( SourceModsContext *ctx, const AttribSet &requestedAttrib ctx->processUpstream( requestedAttribs ); const size_t numVertices = ctx->getNumVertices(); - + switch( mDims ) { case 1: { unique_ptr mColorData( new float[numVertices] ); @@ -3275,7 +3273,7 @@ void geom::AttribFn::process( SourceModsContext *ctx, const AttribSet &requ } else inputAttribData = ctx->getAttribData( mSrcAttrib ); - + processAttrib( inputAttribData, outData.get(), mFn, numVertices ); ctx->copyAttrib( mDstAttrib, DSTDIM, 0, outData.get(), numVertices ); } @@ -3318,7 +3316,7 @@ void Extrude::updatePathSubdivision() Triangulator triangulator; for( const auto &subdivision : mPathSubdivisionPositions ) triangulator.addPolyLine( subdivision ); - + mCap = triangulator.createMesh(); } @@ -3360,7 +3358,7 @@ void Extrude::calculate( vector *positions, vector *normals, vector< indices->push_back( capIndices[i+0] + numCapVertices ); } } - + // EXTRUSION // we don't make use of the caps' vertices because their normals are wrong, // so we'll need to create verts unique to the extrusion @@ -3394,7 +3392,7 @@ void Extrude::calculate( vector *positions, vector *normals, vector< } } } - + size_t Extrude::getNumVertices() const { size_t result = 0; @@ -3451,7 +3449,7 @@ void Extrude::loadInto( Target *target, const AttribSet &requestedAttribs ) cons if( requestedAttribs.count( geom::TANGENT ) ) { vector tangents; calculateTangents( getNumIndices(), indices.data(), positions.size(), positions.data(), normals.data(), texCoords.data(), &tangents, nullptr ); - + if( requestedAttribs.count( geom::TANGENT ) ) target->copyAttrib( Attrib::TANGENT, 3, 0, (const float*)tangents.data(), tangents.size() ); } @@ -3466,7 +3464,7 @@ ExtrudeSpline::ExtrudeSpline( const Shape2d &shape, const ci::BSpline<3,float> & { for( const auto &contour : shape.getContours() ) mPaths.push_back( contour ); - + const vec3 firstFrameEps = vec3( 0.0000001f ); mSplineLength = spline.getLength( 0, 1 ); vec3 prevPos = spline.getPosition( 0 ); @@ -3482,14 +3480,14 @@ ExtrudeSpline::ExtrudeSpline( const Shape2d &shape, const ci::BSpline<3,float> & prevPos = curPos; prevTangent = curTangent; } - + updatePathSubdivision(); } void ExtrudeSpline::updatePathSubdivision() { bool capBoundsEmpty = true; - + // iterate all the paths of the shape and subdivide, calculating both positions and tangents for( const auto &path : mPaths ) { if( capBoundsEmpty ) { @@ -3501,10 +3499,10 @@ void ExtrudeSpline::updatePathSubdivision() mPathSubdivisionPositions.emplace_back( vector() ); mPathSubdivisionTangents.emplace_back( vector() ); path.subdivide( &mPathSubdivisionPositions.back(), &mPathSubdivisionTangents.back(), mApproximationScale ); - + // Path2d::subdivide might returns duplicates - mPathSubdivisionPositions.back().erase( std::unique( mPathSubdivisionPositions.back().begin(), mPathSubdivisionPositions.back().end() ), mPathSubdivisionPositions.back().end() ); - mPathSubdivisionTangents.back().erase( std::unique( mPathSubdivisionTangents.back().begin(), mPathSubdivisionTangents.back().end() ), mPathSubdivisionTangents.back().end() ); + mPathSubdivisionPositions.back().erase( std::unique( mPathSubdivisionPositions.back().begin(), mPathSubdivisionPositions.back().end() ), mPathSubdivisionPositions.back().end() ); + mPathSubdivisionTangents.back().erase( std::unique( mPathSubdivisionTangents.back().begin(), mPathSubdivisionTangents.back().end() ), mPathSubdivisionTangents.back().end() ); // normalize the tangents for( auto& tan : mPathSubdivisionTangents.back() ) @@ -3522,14 +3520,14 @@ void ExtrudeSpline::updatePathSubdivision() Triangulator triangulator; for( const auto &subdivision : mPathSubdivisionPositions ) triangulator.addPolyLine( subdivision ); - + mCap = triangulator.createMesh(); } void ExtrudeSpline::calculate( vector *positions, vector *normals, vector *texCoords, vector *indices ) const { auto capNumVertices = mCap->getNumVertices(); - + // CAP VERTICES const vec2* capPositions = mCap->getPositions<2>(); // front cap @@ -3554,7 +3552,7 @@ void ExtrudeSpline::calculate( vector *positions, vector *normals, v 0 ) ); // the uv z-component allows to differentiate caps and extrusion } } - + // CAP INDICES auto capIndices = mCap->getIndices(); // front cap @@ -3600,7 +3598,7 @@ void ExtrudeSpline::calculate( vector *positions, vector *normals, v } } } - + size_t ExtrudeSpline::getNumVertices() const { size_t result = 0; @@ -3657,7 +3655,7 @@ void ExtrudeSpline::loadInto( Target *target, const AttribSet &requestedAttribs if( requestedAttribs.count( geom::TANGENT ) ) { vector tangents; calculateTangents( getNumIndices(), indices.data(), positions.size(), positions.data(), normals.data(), texCoords.data(), &tangents, nullptr ); - + if( requestedAttribs.count( geom::TANGENT ) ) target->copyAttrib( Attrib::TANGENT, 3, 0, (const float*)tangents.data(), tangents.size() ); } @@ -3875,7 +3873,7 @@ void WireCircle::loadInto( Target *target, const AttribSet &/*requestedAttribs*/ target->copyAttrib( Attrib::POSITION, 3, 0, (const float*) positions.data(), numVertices ); } - + /////////////////////////////////////////////////////////////////////////////////////// // WireRoundedRect WireRoundedRect::WireRoundedRect() @@ -3884,14 +3882,14 @@ WireRoundedRect::WireRoundedRect() rect( Rectf( -0.5f, -0.5f, 0.5f, 0.5f ) ); updateVertexCount(); } - + WireRoundedRect::WireRoundedRect( const Rectf &r, float cornerRadius ) : mCornerSubdivisions( -1 ), mCornerRadius( cornerRadius ), mNumVertices( 0 ) { rect( r ); updateVertexCount(); } - + WireRoundedRect& WireRoundedRect::cornerSubdivisions( int cornerSubdivisions ) { mCornerSubdivisions = cornerSubdivisions; @@ -4104,7 +4102,7 @@ void WireCylinder::loadInto( Target *target, const AttribSet & /*requestedAttrib *ptr++ = mOrigin + m * vec3( mRadiusApex * c, mHeight, mRadiusApex * s ); } } - + float angle = float( 2.0 * M_PI / mNumSegments ); for( int i = 0; i <= mSubdivisionsHeight; ++i ) { float height = i * mHeight / mSubdivisionsHeight; @@ -4468,7 +4466,7 @@ void VertexNormalLines::process( SourceModsContext *ctx, const AttribSet &reques } } } - + ctx->copyAttrib( Attrib::POSITION, 3, 0, (const float*)outPositions.data(), numVertices ); ctx->copyAttrib( Attrib::CUSTOM_0, 1, 0, (const float*)outCustom0.data(), numVertices ); if( texCoords ) @@ -4531,12 +4529,12 @@ void Tangents::process( SourceModsContext *ctx, const AttribSet &requestedAttrib const vec3 *positions = (const vec3*)ctx->getAttribData( geom::POSITION ); const vec3 *normals = (const vec3*)ctx->getAttribData( geom::NORMAL ); const vec2 *texCoords = (const vec2*)ctx->getAttribData( geom::TEX_COORD_0 ); - + if( requestedAttribs.count( geom::TANGENT ) || requestedAttribs.count( geom::BITANGENT ) ) { vector tangents, bitangents; vector *bitangentPtr = ( requestedAttribs.count( geom::BITANGENT ) ) ? &bitangents : nullptr; calculateTangents( numIndices, ctx->getIndicesData(), numVertices, positions, normals, texCoords, &tangents, bitangentPtr ); - + if( requestedAttribs.count( geom::TANGENT ) ) ctx->copyAttrib( Attrib::TANGENT, 3, 0, (const float*)tangents.data(), numVertices ); if( bitangentPtr ) @@ -4554,12 +4552,12 @@ void Invert::process( SourceModsContext *ctx, const AttribSet &requestedAttribs CI_LOG_W( "geom::Invert missing attrib: " << attribToString( mAttrib ) ); return; } - + float *d = ctx->getAttribData( mAttrib ); size_t maxIdx = ctx->getAttribDims( mAttrib ) * ctx->getNumVertices(); for( size_t i = 0; i < maxIdx; ++i ) d[i] = -d[i]; - + // we don't need to copyAttrib() because we processed in place } @@ -4633,13 +4631,13 @@ void Bounds::process( SourceModsContext *ctx, const AttribSet &requestedAttribs AttribSet request = requestedAttribs; request.insert( mAttrib ); ctx->processUpstream( request ); - + uint8_t dims = ctx->getAttribDims( mAttrib ); if( dims == 0 ) { CI_LOG_W( "geom::Bounds requested attribute " << attribToString( mAttrib ) << " missing." ); return; } - + size_t numVertices = ctx->getNumVertices(); const float *data = ctx->getAttribData( mAttrib ); vec3 minResult( FLT_MAX ), maxResult( FLT_MIN ); @@ -4664,7 +4662,7 @@ void Bounds::process( SourceModsContext *ctx, const AttribSet &requestedAttribs } data += dims; } - + if( mResult ) *mResult = AxisAlignedBox( minResult, maxResult ); } @@ -4698,7 +4696,7 @@ void Subdivide::process( SourceModsContext *ctx, const AttribSet &requestedAttri AttribSet request = requestedAttribs; request.insert( POSITION ); ctx->processUpstream( request ); - + if( ctx->getPrimitive() != Primitive::TRIANGLES ) { CI_LOG_E( "geom::Subdivide only supports TRIANGLES primitive." ); return; @@ -4708,21 +4706,21 @@ void Subdivide::process( SourceModsContext *ctx, const AttribSet &requestedAttri CI_LOG_E( "geom::Subdivide requires 3D POSITION." ); return; } - + const size_t numInVertices = ctx->getNumVertices(); const size_t numInIndices = ctx->getNumIndices(); - + const uint32_t *inIndices = ctx->getIndicesData(); const vec3 *inPositions = reinterpret_cast( ctx->getAttribData( POSITION ) ); - + vector outPositions; vector outIndices; - + for( size_t idx = 0; idx < numInIndices; idx += 3 ) { vec3 sumPos = inPositions[inIndices[idx+0]] + inPositions[inIndices[idx+1]] + inPositions[inIndices[idx+2]]; outPositions.push_back( sumPos / 3.0f ); - + uint32_t newIdx = (uint32_t)(outPositions.size() + numInVertices - 1); // 0-new-2 outIndices.push_back( inIndices[idx+0] ); outIndices.push_back( newIdx ); outIndices.push_back( inIndices[idx+2] ); @@ -4731,13 +4729,13 @@ void Subdivide::process( SourceModsContext *ctx, const AttribSet &requestedAttri // new-1-2 outIndices.push_back( newIdx ); outIndices.push_back( inIndices[idx+1] ); outIndices.push_back( inIndices[idx+2] ); } - + // iterate the attributes and lerp for( const auto &attr : ctx->getAvailableAttribs() ) { // we processed POSITION in the previous loop if( attr == POSITION ) continue; - + vector outData; const float *inData = ctx->getAttribData( attr ); uint8_t dims = ctx->getAttribDims( attr ); @@ -4748,7 +4746,7 @@ void Subdivide::process( SourceModsContext *ctx, const AttribSet &requestedAttri inData[inIndices[idx+1]*dims + dim] + inData[inIndices[idx+2]*dims + dim]) / 3.0f ); } - + // normalize 3D NORMAL, TANGENT or BITANGENT if( ( (attr == NORMAL) || (attr == TANGENT) || (attr == BITANGENT) ) && ( dims == 3 ) ) { size_t numVerts = outData.size() / 3; @@ -4760,7 +4758,7 @@ void Subdivide::process( SourceModsContext *ctx, const AttribSet &requestedAttri ctx->appendAttrib( attr, dims, outData.data(), outData.size() / dims ); } - + ctx->appendAttrib( POSITION, 3, (const float*)outPositions.data(), outPositions.size() ); ctx->copyIndices( ctx->getPrimitive(), outIndices.data(), outIndices.size(), 4 ); } @@ -4836,12 +4834,12 @@ Primitive SourceMods::getPrimitive() const uint8_t SourceMods::getAttribDims( Attrib attr ) const { cacheVariables(); - + if( mSourcePtr ) { uint8_t result = mSourcePtr->getAttribDims( attr ); for( auto &mod : mModifiers ) result = mod->getAttribDims( attr, result ); - + return result; } else { @@ -4878,7 +4876,7 @@ void SourceMods::cacheVariables() const // this is important to set first; modifiers' get*() methods might call into one of our get*() methods // in which case we need cacheVariables() to return immediately mVariablesCached = true; - + mParamsStack.push_back( Modifier::Params() ); mParamsStack.back().mNumVertices = mSourcePtr->getNumVertices(); mParamsStack.back().mNumIndices = mSourcePtr->getNumIndices(); @@ -4908,7 +4906,7 @@ void SourceMods::loadInto( Target *target, const AttribSet &requestedAttribs ) c else { SourceModsContext context( this ); context.loadInto( target, requestedAttribs ); - } + } } else if( ! mChildren.empty() ) { // children SourceModsContext context( this ); @@ -4917,8 +4915,8 @@ void SourceMods::loadInto( Target *target, const AttribSet &requestedAttribs ) c siblingContext.preload( requestedAttribs ); context.combine( siblingContext ); } - - context.complete( target, requestedAttribs ); + + context.complete( target, requestedAttribs ); } } @@ -4957,10 +4955,10 @@ SourceModsContext::SourceModsContext( const SourceMods *sourceMods ) : mNumIndices( 0 ), mNumVertices( 0 ), mAttribMask( nullptr ), mPrimitive( NUM_PRIMITIVES ) { mSource = sourceMods->getSource(); - + if( ! sourceMods->mParamsStack.empty() ) // this allows for a non-indexed Source to have never specified the primitive via copyIndices() mPrimitive = sourceMods->mParamsStack.front().mPrimitive; - + for( auto &modifier : sourceMods->mModifiers ) mModiferStack.push_back( modifier.get() ); } @@ -5002,7 +5000,7 @@ void SourceModsContext::combine( const SourceModsContext &rhs ) const auto &count = rhs.mAttribCount.find( attribInfo.first )->second; this->copyAttrib( attribInfo.first, attribInfo.second.getDims(), attribInfo.second.getStride(), data.get(), count ); } - + return; } @@ -5019,14 +5017,14 @@ void SourceModsContext::combine( const SourceModsContext &rhs ) size_t rhsNumIndices = rhs.getNumIndices(); // rhs indices size_t numVertices = getNumVertices(); // upstream vertices size_t rhsNumVertices = rhs.getNumVertices(); // rhs vertices - + size_t numOutIndices = determineRequiredIndices( getPrimitive(), combinedPrimitive, numIndices ? numIndices : numVertices ); size_t rhsNumOutIndices = determineRequiredIndices( rhsPrimitive, combinedPrimitive, rhsNumIndices ? rhsNumIndices : rhsNumVertices ); size_t totalOutIndices = numOutIndices + rhsNumOutIndices; - + std::vector outIndices; outIndices.resize( totalOutIndices ); - + if( combinedPrimitive == Primitive::TRIANGLES ) { if( getNumIndices() ) // 'this is indexed Target::copyIndexDataForceTriangles( getPrimitive(), getIndicesData(), numIndices, 0, outIndices.data() ); @@ -5055,7 +5053,7 @@ void SourceModsContext::combine( const SourceModsContext &rhs ) } this->copyIndices( combinedPrimitive, outIndices.data(), outIndices.size(), 4 ); - + // Handle Attributes for( const auto &attribInfo : mAttribInfo ) { uint8_t dims = getAttribDims( attribInfo.first ); @@ -5084,14 +5082,14 @@ void SourceModsContext::complete( Target *target, const AttribSet &requestedAttr for( const auto &attribCount : mAttribCount ) if( attribCount.second != mNumVertices && ( requestedAttribs.count( attribCount.first ) > 0 ) ) CI_LOG_E( "Attribute " << attribToString( attribCount.first ) << " count is " << attribCount.first << " instead of " << mNumVertices ); - + for( const auto &attribInfoPair : mAttribInfo ) { Attrib attrib = attribInfoPair.first; const AttribInfo &attribInfo = attribInfoPair.second; target->copyAttrib( attrib, attribInfo.getDims(), attribInfo.getStride(), mAttribData[attrib].get(), mAttribCount[attrib] ); } - target->copyIndices( mPrimitive, mIndices.get(), mNumIndices, calcIndicesRequiredBytes( mNumIndices ) ); + target->copyIndices( mPrimitive, mIndices.get(), mNumIndices, calcIndicesRequiredBytes( mNumIndices ) ); } void SourceModsContext::loadInto( Target *target, const AttribSet &requestedAttribs ) @@ -5111,12 +5109,12 @@ void SourceModsContext::loadInto( Target *target, const AttribSet &requestedAttr // We've finished processing all Modifiers and the Source. Now iterate all the attribute data and the indices // and copy them to the target. - + // first let's verify that all counts on our requested attributes are the same. If not, we'll continue to process but with an error for( const auto &attribCount : mAttribCount ) if( attribCount.second != mNumVertices && ( requestedAttribs.count( attribCount.first ) > 0 ) ) CI_LOG_E( "Attribute " << attribToString( attribCount.first ) << " count is " << attribCount.first << " instead of " << mNumVertices ); - + for( const auto &attribInfoPair : mAttribInfo ) { Attrib attrib = attribInfoPair.first; const AttribInfo &attribInfo = attribInfoPair.second; @@ -5147,7 +5145,7 @@ void SourceModsContext::processUpstream( const AttribSet &requestedAttribs ) modifier->process( this, requestedAttribs ); } } - + uint8_t SourceModsContext::getAttribDims( Attrib attr ) const { auto attrInfoIt = mAttribInfo.find( attr ); @@ -5214,7 +5212,7 @@ void SourceModsContext::copyAttrib( Attrib attr, uint8_t dims, size_t strideByte const AttribInfo &attribInfo = mAttribInfo.at( attr ); needsAllocation = ( attribInfo.getStride() != strideBytes ) || ( attribInfo.getDims() != dims ) || ( count != mAttribCount[attr] ); } - + if( needsAllocation ) { mAttribData[attr] = unique_ptr( new float[dims * count] ); mAttribCount[attr] = count; @@ -5223,7 +5221,7 @@ void SourceModsContext::copyAttrib( Attrib attr, uint8_t dims, size_t strideByte auto it = mAttribInfo.insert( make_pair( attr, AttribInfo( attr, dims, dims * sizeof(float), (size_t)0 ) ) ).first; it->second = AttribInfo( attr, dims, dims * sizeof(float), (size_t)0 ); // only necessary if the key already exists } - + copyData( dims, strideBytes, srcData, count, dims, 0, mAttribData.at( attr ).get() ); } @@ -5267,7 +5265,7 @@ void SourceModsContext::appendIndices( Primitive primitive, const uint32_t *sour { if( mPrimitive != primitive ) CI_LOG_E( "Primitive types don't match" ); - + auto newIndices = unique_ptr( new uint32_t[numIndices + mNumIndices] ); mIndicesRequiredBytes = std::max( mIndicesRequiredBytes, requiredBytes ); @@ -5278,7 +5276,7 @@ void SourceModsContext::appendIndices( Primitive primitive, const uint32_t *sour memcpy( newIndices.get() + mNumIndices, source, sizeof(uint32_t) * numIndices ); // total indices += new number of indices mNumIndices = mNumIndices + numIndices; - + mIndices = std::move( newIndices ); }