Initializing SplineData CustomGUI
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 27/11/2002 at 14:45, xxxxxxxx wrote:
I cannot get the ATOM object to work without the "Not Enough Memory" error. Can you forward an example to me of your complete ATOM object example that works? That way I can see if it might be a conflict or something?
Best Regards, darf - bhodiNUT -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 27/11/2002 at 22:12, xxxxxxxx wrote:
Well, this is just the standard Atom.cpp with the above changes:
///////////////////////////////////////////////////////////// // CINEMA SDK : OBJECT PLUGINS // ///////////////////////////////////////////////////////////// // VERSION : CINEMA 4D // ///////////////////////////////////////////////////////////// // (c) 1989-2002 MAXON Computer GmbH, all rights reserved // ///////////////////////////////////////////////////////////// // this example demonstrates how to implement a generator // with input objects. the first sub-object (including childs) // of the atom is taken as polygonized input. The atom places // a sphere at input points and cylinders at input edges. // depending on the user options one single mesh or several // single objects (hierarchically grouped) are built. #include "c4d.h" #include "c4d_symbols.h" #include "Oatom.h" class AtomObject : public ObjectData { INSTANCEOF(AtomObject, ObjectData); public: virtual Bool Init(GeListNode *node); virtual BaseObject* GetVirtualObjects(PluginObject *op, HierarchyHelp *hh); virtual Bool Message(GeListNode *node, LONG type, void *t_data); Bool GetDParameter(GeListNode *node, const DescID &id,GeData &t_data,LONG &flags) { switch(id[0].id) { case ATOMOBJECT_PREVIEW: { PluginMaterial *mat = (PluginMaterial* )node; LONG dirty = 0; BitmapButtonStruct bbs(static_cast<PluginObject*>(node), id, dirty); t_data = GeData(CUSTOMDATATYPE_BITMAPBUTTON,bbs); flags |= DESCFLAGS_PARAM_GET; break; } } return SUPER::GetDParameter(node, id, t_data, flags); } Bool SetDParameter(GeListNode *node, const DescID &id, const GeData &t_data, LONG &flags) { switch(id[0].id) { case ATOMOBJECT_PREVIEW: flags |= DESCFLAGS_PARAM_SET; break; } return SUPER::SetDParameter(node, id, t_data, flags); } static NodeData *Alloc(void) { return gNew AtomObject; } }; // initialize settings Bool AtomObject::Init(GeListNode *node) { BaseObject *op = (BaseObject* )node; BaseContainer *data = op->GetDataInstance(); AutoAlloc<SplineData> falloffspline; if ( !falloffspline ) return FALSE; falloffspline->InsertKnot( 0.0, 0.0 ); falloffspline->InsertKnot( 1.0, 1.0 ); data->SetData(ATOMOBJECT_SINGLE + 42, GeData(CUSTOMDATATYPE_SPLINE, falloffspline) ); data->SetReal(ATOMOBJECT_SRAD,5.0); data->SetReal(ATOMOBJECT_CRAD,2.0); data->SetLong(ATOMOBJECT_SUB,8); data->SetBool(ATOMOBJECT_SINGLE,FALSE); return TRUE; } Bool AtomObject::Message(GeListNode *node, LONG type, void *t_data) { if (type==MSG_DESCRIPTION_VALIDATE) { BaseContainer *data = ((BaseObject* )node)->GetDataInstance(); CutReal(*data,ATOMOBJECT_CRAD,0.0,data->GetReal(ATOMOBJECT_SRAD)); } if (type == MSG_DESCRIPTION_GETBITMAP) { DescriptionGetBitmap* dgb = static_cast<DescriptionGetBitmap*>(t_data); if (dgb->id[0] == ATOMOBJECT_PREVIEW) { AutoAlloc<BaseBitmap> bm; bm->Init(50, 50); bm->SetPen(12, 34, 56); bm->Line(0, 0, 49, 49); dgb->bmp = bm.Release(); } } return TRUE; } // build a rectangular matrix system with a given normal static void RectangularSystem(const Vector &n, Vector *v1, Vector *v2) { *v2 = Vector(n.y,n.z,n.x); *v1 = !((*v2)%n); *v2 = !(n%(*v1)); } // build a single polygonal atom object static PolygonObject *BuildPolyHull(PolygonObject *op, const Matrix &ml, Real srad, Real crad, LONG sub, Real lod, Neighbor *n, BaseThread *bt) { BaseContainer bc,cc; LONG spcnt,svcnt,cpcnt,cvcnt,poff,voff,i,j,a,b,side; Vector *spadr=NULL,*cpadr=NULL,*rpadr=NULL,off,pa,pb; Polygon *svadr=NULL,*cvadr=NULL,*rvadr=NULL; UVWTag *suvw =NULL,*cuvw =NULL,*ruvw =NULL; Vector *padr = op->GetPoint(); Polygon *vadr = op->GetPolygon(); LONG pcnt = op->GetPointCount(); LONG vcnt = op->GetPolygonCount(); PolyInfo *pli = NULL; Bool ok=FALSE; Matrix m; // set sphere default values bc.SetReal(PRIM_SPHERE_RAD,srad); bc.SetReal(PRIM_SPHERE_SUB,sub); // set cylinder default values (cylinders are a special case of cone objects) cc.SetReal(PRIM_CYLINDER_RADIUS,crad); cc.SetReal(PRIM_CYLINDER_HEIGHT,1.0); cc.SetLong(PRIM_CYLINDER_CAPS,FALSE); cc.SetLong(PRIM_CYLINDER_HSUB,1); cc.SetLong(PRIM_CYLINDER_SEG,sub); cc.SetReal(PRIM_AXIS,4); // generate both primitives PolygonObject *sphere=(PolygonObject* )GeneratePrimitive(NULL,Osphere,bc,lod,FALSE,bt),*pp=NULL; PolygonObject *cyl=(PolygonObject* )GeneratePrimitive(NULL,Ocylinder,cc,lod,FALSE,bt); if (!sphere || !cyl) goto Error; spcnt = sphere->GetPointCount(); svcnt = sphere->GetPolygonCount(); spadr = sphere->GetPoint(); svadr = sphere->GetPolygon(); suvw = (UVWTag* )sphere->GetTag(Tuvw); cpcnt = cyl->GetPointCount(); cvcnt = cyl->GetPolygonCount(); cpadr = cyl->GetPoint(); cvadr = cyl->GetPolygon(); cuvw = (UVWTag* )cyl->GetTag(Tuvw); // allocate main object pp=PolygonObject::Alloc(spcnt*pcnt+cpcnt*n->GetEdgeCount(),svcnt*pcnt+cvcnt*n->GetEdgeCount()); if (!pp) goto Error; // add phong tag if (!pp->MakeTag(Tphong)) goto Error; // add UVW tag ruvw=(UVWTag* )pp->MakeVariableTag(Tuvw,pp->GetPolygonCount()); if (!ruvw) goto Error; // copy sphere geometry for each point rpadr = pp->GetPoint(); rvadr = pp->GetPolygon(); poff = 0; voff = 0; for (i=0; i<pcnt; i++) { // test every 256th time if there has been a user break, delete object in this case if (!(i&255) && bt && bt->TestBreak()) goto Error; off=padr[i]*ml; for (j=0; j<spcnt; j++) rpadr[poff+j] = off + spadr[j]; for (j=0; j<svcnt; j++) { rvadr[voff+j] = Polygon(svadr[j].a+poff,svadr[j].b+poff,svadr[j].c+poff,svadr[j].d+poff); ruvw->Cpy(voff+j,suvw,j); } poff+=spcnt; voff+=svcnt; } // copy cylinder geometry for each edge for (i=0; i<vcnt; i++) { pli = n->GetPolyInfo(i); // test every 256th time if there has been a user break, delete object in this case if (!(i&255) && bt && bt->TestBreak()) goto Error; for (side=0; side<4; side++) { // only proceed if edge has not already been processed // and edge really exists (for triangles side 2 from c..d does not exist as c==d) if (pli->mark[side] || side==2 && vadr[i].c==vadr[i].d) continue; switch (side) { case 0: a=vadr[i].a; b=vadr[i].b; break; case 1: a=vadr[i].b; b=vadr[i].c; break; case 2: a=vadr[i].c; b=vadr[i].d; break; case 3: a=vadr[i].d; b=vadr[i].a; break; } // build edge matrix pa = padr[a]*ml; pb = padr[b]*ml; m.off=(pa+pb)*0.5; RectangularSystem(!(pb-pa),&m.v1,&m.v2); m.v3=pb-pa; for (j=0; j<cpcnt; j++) rpadr[poff+j] = cpadr[j]*m; for (j=0; j<cvcnt; j++) { rvadr[voff+j] = Polygon(cvadr[j].a+poff,cvadr[j].b+poff,cvadr[j].c+poff,cvadr[j].d+poff); ruvw->Cpy(voff+j,cuvw,j); } poff+=cpcnt; voff+=cvcnt; } } // update object as point geometry has changed pp->Message(MSG_UPDATE); ok=TRUE; Error: blDelete(sphere); blDelete(cyl); if (!ok) blDelete(pp); return pp; } // build a single isoparm atom object static LineObject *BuildIsoHull(PolygonObject *op, const Matrix &ml, Real srad, Real crad, LONG sub, Real lod, Neighbor *n, BaseThread *bt) { LONG poff,soff,i,j,a,b,side; Vector *rpadr=NULL,off,pa,pb; Segment *rsadr=NULL; Vector *padr = op->GetPoint(); Polygon *vadr = op->GetPolygon(); LONG vcnt = op->GetPolygonCount(); PolyInfo *pli = NULL; Matrix m; Vector p[8]; // allocate isoparm object LineObject *pp=LineObject::Alloc(8*n->GetEdgeCount(),4*n->GetEdgeCount()); if (!pp) return NULL; rpadr = pp->GetPoint(); rsadr = pp->GetSegment(); poff = 0; soff = 0; p[0]=Vector(-crad, 0.0,-0.5); p[1]=Vector(-crad, 0.0, 0.5); p[2]=Vector( crad, 0.0,-0.5); p[3]=Vector( crad, 0.0, 0.5); p[4]=Vector( 0.0,-crad,-0.5); p[5]=Vector( 0.0,-crad, 0.5); p[6]=Vector( 0.0, crad,-0.5); p[7]=Vector( 0.0, crad, 0.5); for (i=0; i<vcnt; i++) { // test every 256th time if there has been a user break, delete object in this case if (!(i&255) && bt && bt->TestBreak()) { blDelete(pp); return NULL; } pli = n->GetPolyInfo(i); for (side=0; side<4; side++) { // only proceed if edge has not already been processed // and edge really exists (for triangles side 2 from c..d does not exist as c==d) if (pli->mark[side] || side==2 && vadr[i].c==vadr[i].d) continue; switch (side) { case 0: a=vadr[i].a; b=vadr[i].b; break; case 1: a=vadr[i].b; b=vadr[i].c; break; case 2: a=vadr[i].c; b=vadr[i].d; break; case 3: a=vadr[i].d; b=vadr[i].a; break; } // build edge matrix pa = padr[a]*ml; pb = padr[b]*ml; m.off=(pa+pb)*0.5; RectangularSystem(!(pb-pa),&m.v1,&m.v2); m.v3=pb-pa; for (j=0; j<8; j++) rpadr[poff+j] = p[j]*m; for (j=0; j<4; j++) { rsadr[soff+j].closed = FALSE; rsadr[soff+j].cnt = 2; } poff+=8; soff+=4; } } // update object as point geometry has changed pp->Message(MSG_UPDATE); return pp; } // go through every (child) object static Bool Recurse(HierarchyHelp *hh, BaseThread *bt, BaseObject *main, BaseObject *op, const Matrix &ml, Real srad, Real crad, LONG sub, Bool single) { // test if input object if polygonal if (op->GetType()==Opolygon) { BaseObject *tp = NULL; PolyInfo *pli = NULL; Vector *padr = ToPoly(op)->GetPoint(),pa,pb; LONG pcnt = ToPoly(op)->GetPointCount(),i,side,a,b; Polygon *vadr = ToPoly(op)->GetPolygon(); LONG vcnt = ToPoly(op)->GetPolygonCount(); Matrix m; Neighbor n; // load names from resource String pstr = GeLoadString(IDS_ATOM_POINT); String estr = GeLoadString(IDS_ATOM_EDGE); // initialize neighbor class if (!n.Init(pcnt,vadr,vcnt,NULL)) return FALSE; // create separate objects // if this option is enabled no polygonal geometry is build - more parametric objects // are returned instead if (single) { for (i=0; i<pcnt; i++) { // alloc sphere primitive tp=BaseObject::Alloc(Osphere); if (!tp) return FALSE; // add phong tag if (!tp->MakeTag(Tphong)) return FALSE; tp->SetName(pstr+" "+LongToString(i)); // set object parameters BaseContainer *bc = tp->GetDataInstance(); bc->SetReal(PRIM_SPHERE_RAD,srad); bc->SetReal(PRIM_SPHERE_SUB,sub); // insert as last object under main tp->InsertUnderLast(main); // set position in local coordinates tp->SetPos(padr[i]*ml); } for (i=0; i<vcnt; i++) { // get polygon info for i-th polygon pli = n.GetPolyInfo(i); for (side=0; side<4; side++) { // only proceed if edge has not already been processed // and edge really exists (for triangles side 2 from c..d does not exist as c==d) if (pli->mark[side] || side==2 && vadr[i].c==vadr[i].d) continue; // alloc cylinder primitive tp=BaseObject::Alloc(Ocylinder); if (!tp) return FALSE; // add phong tag if (!tp->MakeTag(Tphong)) return FALSE; switch (side) { case 0: a=vadr[i].a; b=vadr[i].b; break; case 1: a=vadr[i].b; b=vadr[i].c; break; case 2: a=vadr[i].c; b=vadr[i].d; break; case 3: a=vadr[i].d; b=vadr[i].a; break; } tp->SetName(estr+" "+LongToString(pli->edge[side])); pa = padr[a]*ml; pb = padr[b]*ml; // set object parameters BaseContainer *bc = tp->GetDataInstance(); bc->SetReal(PRIM_CYLINDER_RADIUS,crad); bc->SetReal(PRIM_CYLINDER_HEIGHT,Len(pb-pa)); bc->SetReal(PRIM_AXIS,4); bc->SetLong(PRIM_CYLINDER_CAPS,FALSE); bc->SetLong(PRIM_CYLINDER_HSUB,1); bc->SetLong(PRIM_CYLINDER_SEG,sub); // place cylinder at edge center tp->SetPos((pa+pb)*0.5); // build edge matrix m.v3=!(pb-pa); RectangularSystem(m.v3,&m.v1,&m.v2); tp->SetRot(MatrixToHPB(m)); // insert as last object under main tp->InsertUnderLast(main); } } } else { // check if polygonal geometry has to be built if (hh->GetVFlags()&VFLAG_POLYGONAL) tp = BuildPolyHull(ToPoly(op),ml,srad,crad,sub,hh->GetLOD(),&n,bt); else tp = PolygonObject::Alloc(0,0); if (tp) { tp->SetName(op->GetName()); tp->InsertUnderLast(main); // check if isoparm geometry has to be built if (hh->GetVFlags()&VFLAG_ISOPARM) { LineObject *ip = BuildIsoHull(ToPoly(op),ml,srad,crad,sub,hh->GetLOD(),&n,bt); // isoparm always needs to be set into a polygon object if (ip) tp->SetIsoparm(ip); } } } } for (op=op->GetDown(); op; op=op->GetNext()) if (!Recurse(hh,bt,main,op,ml*op->GetMl(),srad,crad,sub,single)) return FALSE; // check for user break return !bt || !bt->TestBreak(); } // main routine: build virtual atom objects BaseObject *AtomObject::GetVirtualObjects(PluginObject *op, HierarchyHelp *hh) { BaseObject *orig = op->GetDown(); // return if no input object is available if (!orig) return NULL; // request polygonized input hh->AddVFlags(VFLAG_POLYGONAL); Bool dirty = FALSE; // generate polygonalized clone of input object BaseObject *main=NULL,*res=op->GetAndCheckHierarchyClone(hh,orig,HCLONE_ASPOLY,&dirty,FALSE,NULL); // if !dirty object is already cached and doesn't need to be rebuilt if (!dirty) return res; if (!res) return NULL; LONG sub; Bool single; Real srad,crad; // get object container BaseContainer *bc=op->GetDataInstance(); BaseThread *bt=hh->GetThread(); // group all further objects with this null object main = BaseObject::Alloc(Onull); if (!main) goto Error; // get object settings srad = bc->GetReal(ATOMOBJECT_SRAD); crad = bc->GetReal(ATOMOBJECT_CRAD); sub = bc->GetLong(ATOMOBJECT_SUB); single = bc->GetBool(ATOMOBJECT_SINGLE); // go through all child hierarchies if (!Recurse(hh,bt,main,res,orig->GetMl(),srad,crad,sub,single)) goto Error; blDelete(res); return main; Error: blDelete(res); blDelete(main); return NULL; } // be sure to use a unique ID obtained from [www.plugincafe.com](http://www.plugincafe.com) #define ID_ATOMOBJECT 1001153 Bool RegisterAtomObject(void) { // decide by name if the plugin shall be registered - just for user convenience String name=GeLoadString(IDS_ATOM); if (!name.Content()) return TRUE; return RegisterObjectPlugin(ID_ATOMOBJECT,name,OBJECT_GENERATOR|OBJECT_INPUT,AtomObject::Alloc,"Oatom","atom.tif","atom_small.tif",0); }
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 28/11/2002 at 08:43, xxxxxxxx wrote:
I cannot find ATOMOBJECT_PREVIEW in any of the downloadable SDK atom object source or description files. While I would be very interested in that, the obejct still returns a memory error. I am on a Win2000 box with 512mg ram. Can you possibly send the SDK files you created this source for? Still really interested in the ATOMOBJECT_PREVIEW!
darf - bhodiNUT -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 28/11/2002 at 09:26, xxxxxxxx wrote:
Hey, it's you guys forcing me to always mess up my SDK folder with stupid tests...
Please forget ATOMOBJECT_PREVIEW (it's from another forum post showing how to use the bitmap button for previews). Here's a pristine version of RoundedTube.cpp with the spline code in Init() :///////////////////////////////////////////////////////////// // CINEMA SDK : OBJECT PLUGINS // ///////////////////////////////////////////////////////////// // VERSION : CINEMA 4D // ///////////////////////////////////////////////////////////// // (c) 1989-2002 MAXON Computer GmbH, all rights reserved // ///////////////////////////////////////////////////////////// // generator object example (with no input objects) #include "c4d.h" #include "c4d_symbols.h" #include "Oroundedtube.h" class RoundedTube : public ObjectData { public: String test; virtual Bool Init (GeListNode *node); virtual Bool Read (GeListNode *node, HyperFile *hf, LONG level); virtual Bool Write (GeListNode *node, HyperFile *hf); virtual void GetDimension (PluginObject *op, Vector *mp, Vector *rad); virtual Bool Draw (PluginObject *op, LONG type, BaseDraw *bd, BaseDrawHelp *bh); virtual LONG DetectHandle (PluginObject *op, BaseDraw *bd, LONG x, LONG y, LONG qualifier); virtual Bool MoveHandle (PluginObject *op, PluginObject *undo, const Matrix &tm, LONG hit_id, LONG qualifier); virtual BaseObject* GetVirtualObjects(PluginObject *op, HierarchyHelp *hh); virtual Bool Message(GeListNode *node, LONG type, void *t_data); static NodeData *Alloc(void) { return gNew RoundedTube; } }; Bool RoundedTube::Message(GeListNode *node, LONG type, void *t_data) { if (type==MSG_DESCRIPTION_VALIDATE) { BaseContainer *data = ((BaseObject* )node)->GetDataInstance(); CutReal(*data,TUBEOBJECT_IRADX,0.0,data->GetReal(TUBEOBJECT_RAD)); CutReal(*data,TUBEOBJECT_ROUNDRAD,0.0,data->GetReal(TUBEOBJECT_IRADX)); } else if (type==MSG_MENUPREPARE) { ((BaseObject* )node)->SetPhong(TRUE,FALSE,0.0); } return TRUE; } void RoundedTube::GetDimension(PluginObject *op, Vector *mp, Vector *rad) { BaseContainer *data = op->GetDataInstance(); Real rado,radx,rady; rado = data->GetReal(TUBEOBJECT_RAD); radx = data->GetReal(TUBEOBJECT_IRADX); rady = data->GetReal(TUBEOBJECT_IRADY); *mp =0.0; switch (data->GetLong(PRIM_AXIS)) { case 0: case 1: *rad=Vector(rady,rado+radx,rado+radx); break; case 2: case 3: *rad=Vector(rado+radx,rady,rado+radx); break; case 4: case 5: *rad=Vector(rado+radx,rado+radx,rady); break; } } static BaseObject *GenerateLathe(Vector *cpadr, LONG cpcnt, LONG sub, BaseThread *bt) { PolygonObject *op=NULL; UVWStruct us; UVWTag *tag =NULL; Vector *padr=NULL; Polygon *vadr=NULL; LONG i,j,pcnt,vcnt,a,b,c,d; Real len=0.0,sn,cs,v1,v2,*uvadr=NULL; pcnt = cpcnt*sub; vcnt = cpcnt*sub; op=PolygonObject::Alloc(pcnt,vcnt); if (!op) goto Error; tag = (UVWTag* )op->MakeVariableTag(Tuvw,vcnt); if (!tag) goto Error; padr=op->GetPoint(); vadr=op->GetPolygon(); uvadr = (Real* ) GeAlloc(sizeof(Real)*(cpcnt+1)); if (!uvadr) goto Error; uvadr[0]=0.0; for (i=0; i<cpcnt; i++) { uvadr[i] = len; len+=Len(cpadr[(i+1)%cpcnt]-cpadr[i]); } if (len>0.0) len=1.0/len; for (i=0; i<cpcnt; i++) uvadr[i]*=len; uvadr[cpcnt]=1.0; vcnt=0; for (i=0; i<sub; i++) { SinCos(pi2*Real(i)/Real(sub),sn,cs); v1=Real(i )/Real(sub); v2=Real(i+1)/Real(sub); if (bt && bt->TestBreak()) goto Error; for (j=0; j<cpcnt; j++) { a = cpcnt*i+j; padr[a] = Vector(cpadr[j].x*cs,cpadr[j].y,cpadr[j].x*sn); if (i<sub) { b = cpcnt*i +((j+1)%cpcnt); c = cpcnt*((i+1)%sub)+((j+1)%cpcnt); d = cpcnt*((i+1)%sub)+j; us = UVWStruct(Vector(v1,1.0-uvadr[j],0.0),Vector(v1,1.0-uvadr[j+1],0.0),Vector(v2,1.0-uvadr[j+1],0.0),Vector(v2,1.0-uvadr[j],0.0)); tag->Set(vcnt,us); vadr[vcnt++] = Polygon(a,b,c,d); } } } GeFree(uvadr); op->Message(MSG_UPDATE); op->SetPhong(TRUE,TRUE,Rad(80.0)); return op; Error: GeFree(uvadr); blDelete(op); return NULL; } static LineObject *GenerateIsoLathe(Vector *cpadr, LONG cpcnt, LONG sub) { LONG i; LineObject *op = LineObject::Alloc(cpcnt*4+sub*4,8); if (!op) return NULL; Segment *sadr = op->GetSegment(); Vector *padr=op->GetPoint(); for (i=0; i<4; i++) { sadr[i].cnt = cpcnt; sadr[i].closed = TRUE; } for (i=0; i<4; i++) { sadr[4+i].cnt = sub; sadr[4+i].closed = TRUE; } Real sn,cs; LONG j; for (i=0; i<4; i++) { SinCos(Real(i)*pi05,sn,cs); for (j=0; j<cpcnt; j++) padr[i*cpcnt+j] = Vector(cpadr[j].x*cs,cpadr[j].y,cpadr[j].x*sn); } for (i=0; i<sub; i++) { SinCos(Real(i)/sub*pi2,sn,cs); for (j=0; j<4; j++) padr[4*cpcnt+j*sub+i] = Vector(cpadr[cpcnt/4*j].x*cs,cpadr[cpcnt/4*j].y,cpadr[cpcnt/4*j].x*sn); } op->Message(MSG_UPDATE); return op; } Bool RoundedTube::Init(GeListNode *node) { test = String("Test"); BaseObject *op = (BaseObject* )node; BaseContainer *data = op->GetDataInstance(); AutoAlloc<SplineData> falloffspline; if ( !falloffspline ) return FALSE; falloffspline->InsertKnot( 0.0, 0.0 ); falloffspline->InsertKnot( 1.0, 1.0 ); data->SetData(TUBEOBJECT_SEG + 42, GeData(CUSTOMDATATYPE_SPLINE, falloffspline) ); data->SetReal(TUBEOBJECT_RAD,200.0); data->SetReal(TUBEOBJECT_IRADX,50.0); data->SetReal(TUBEOBJECT_IRADY,50.0); data->SetLong(TUBEOBJECT_SUB,1); data->SetLong(TUBEOBJECT_ROUNDSUB,8); data->SetReal(TUBEOBJECT_ROUNDRAD,10.0); data->SetLong(TUBEOBJECT_SEG,36); data->SetLong(PRIM_AXIS,PRIM_AXIS_YP); return TRUE; } Bool RoundedTube::Read(GeListNode *node, HyperFile *hf, LONG level) { if (level>=0) { hf->ReadString(&test); } return TRUE; } Bool RoundedTube::Write(GeListNode *node, HyperFile *hf) { hf->WriteString(test); return TRUE; } static void SetAxis(BaseObject *obj, LONG axis) { PointObject *op = ToPoint(obj); if (axis==2) return; Vector *padr = op->GetPoint(); LONG pcnt = op->GetPointCount(),i; switch (axis) { case 0: // +X for (i=0; i<pcnt; i++) padr[i] = Vector(padr[i].y,-padr[i].x,padr[i].z); break; case 1: // -X for (i=0; i<pcnt; i++) padr[i] = Vector(-padr[i].y,padr[i].x,padr[i].z); break; case 3: // -Y for (i=0; i<pcnt; i++) padr[i] = Vector(-padr[i].x,-padr[i].y,padr[i].z); break; case 4: // +Z for (i=0; i<pcnt; i++) padr[i] = Vector(padr[i].x,-padr[i].z,padr[i].y); break; case 5: // -Z for (i=0; i<pcnt; i++) padr[i] = Vector(padr[i].x,padr[i].z,-padr[i].y); break; } op->Message(MSG_UPDATE); } BaseObject *RoundedTube::GetVirtualObjects(PluginObject *op, HierarchyHelp *hh) { LineObject *lop = NULL; BaseObject *ret = NULL; Bool dirty = op->CheckCache(hh) || op->IsDirty(DIRTY_DATA); if (!dirty) return op->GetCache(hh); BaseContainer *data = op->GetDataInstance(); Real rad = data->GetReal(TUBEOBJECT_RAD,200.0); Real iradx = data->GetReal(TUBEOBJECT_IRADX,50.0); Real irady = data->GetReal(TUBEOBJECT_IRADY,50.0); Real rrad = data->GetReal(TUBEOBJECT_ROUNDRAD,10.0); LONG sub = CalcLOD(data->GetLong(TUBEOBJECT_SUB,1),hh->GetLOD(),1,1000); LONG rsub = CalcLOD(data->GetLong(TUBEOBJECT_ROUNDSUB,8),hh->GetLOD(),1,1000); LONG seg = CalcLOD(data->GetLong(TUBEOBJECT_SEG,36),hh->GetLOD(),3,1000); LONG axis = data->GetLong(PRIM_AXIS); LONG i; Real sn,cs; LONG cpcnt = 4*(sub+rsub); Vector *cpadr = (Vector* )GeAlloc(cpcnt*sizeof(Vector)); if (!cpadr) return NULL; for (i=0; i<sub; i++) { cpadr[i ]=Vector(rad-iradx,(1.0-Real(i)/Real(sub)*2.0)*(irady-rrad),0.0); cpadr[i+ sub+rsub ]=Vector(rad+(Real(i)/Real(sub)*2.0-1.0)*(iradx-rrad),-irady,0.0); cpadr[i+2*(sub+rsub)]=Vector(rad+iradx,(Real(i)/Real(sub)*2.0-1.0)*(irady-rrad),0.0); cpadr[i+3*(sub+rsub)]=Vector(rad+(1.0-Real(i)/Real(sub)*2.0)*(iradx-rrad),irady,0.0); } for (i=0; i<rsub; i++) { SinCos(Real(i)/Real(rsub)*pi05,sn,cs); cpadr[i+sub ]=Vector(rad-(iradx-rrad+cs*rrad),-(irady-rrad+sn*rrad),0.0); cpadr[i+sub+ (sub+rsub)]=Vector(rad+(iradx-rrad+sn*rrad),-(irady-rrad+cs*rrad),0.0); cpadr[i+sub+2*(sub+rsub)]=Vector(rad+(iradx-rrad+cs*rrad),+(irady-rrad+sn*rrad),0.0); cpadr[i+sub+3*(sub+rsub)]=Vector(rad-(iradx-rrad+sn*rrad),+(irady-rrad+cs*rrad),0.0); } if (hh->GetVFlags()&VFLAG_POLYGONAL) { ret = GenerateLathe(cpadr,cpcnt,seg,hh->GetThread()); if (!ret) goto Error; SetAxis(ret,axis); ret->KillTag(Tphong); if (!op->CopyTagsTo(ret,TRUE,FALSE,FALSE,NULL)) goto Error; } else { ret = PolygonObject::Alloc(0,0); if (!ret) goto Error; } ret->SetName(op->GetName()); if (hh->GetVFlags()&VFLAG_ISOPARM) { lop = GenerateIsoLathe(cpadr,cpcnt,seg); if (!lop) goto Error; SetAxis(lop,axis); ret->SetIsoparm(lop); } GeFree(cpadr); return ret; Error: GeFree(cpadr); blDelete(ret); return NULL; } static Vector SwapPoint(const Vector &p, LONG axis) { switch (axis) { case 0: return Vector(p.y,-p.x,p.z); break; case 1: return Vector(-p.y,p.x,p.z); break; case 3: return Vector(-p.x,-p.y,p.z); break; case 4: return Vector(p.x,-p.z,p.y); break; case 5: return Vector(p.x,p.z,-p.y); break; } return p; } static Vector GetRTHandle(PluginObject *op, LONG id) { BaseContainer *data = op->GetDataInstance(); Vector p; Real rad = data->GetReal(TUBEOBJECT_RAD); Real iradx = data->GetReal(TUBEOBJECT_IRADX); Real irady = data->GetReal(TUBEOBJECT_IRADY); Real rrad = data->GetReal(TUBEOBJECT_ROUNDRAD); LONG axis = data->GetLong(PRIM_AXIS); switch (id) { case 0: p=Vector(rad,0.0,0.0); break; case 1: p=Vector(rad+iradx,0.0,0.0); break; case 2: p=Vector(rad,irady,0.0); break; case 3: p=Vector(rad+iradx,irady-rrad,0.0); break; case 4: p=Vector(rad+iradx-rrad,irady,0.0); break; } return SwapPoint(p,axis); } #define HANDLES 5 Bool RoundedTube::Draw(PluginObject *op, LONG type, BaseDraw *bd, BaseDrawHelp *bh) { if (type!=DRAWPASS_HANDLES) return TRUE; BaseContainer *data = op->GetDataInstance(); LONG i; Matrix m = bh->GetMg(); Real rad = data->GetReal(TUBEOBJECT_RAD); Real iradx = data->GetReal(TUBEOBJECT_IRADX); Real irady = data->GetReal(TUBEOBJECT_IRADY); LONG axis = data->GetLong(PRIM_AXIS); bd->SetPen(GetWorldColor(COLOR_ACTIVEPOINT)); for (i=0; i<HANDLES; i++) bd->Handle3D(GetRTHandle(op,i)*m,HANDLE_BIG); bd->Line3D(GetRTHandle(op,0)*m,GetRTHandle(op,1)*m); bd->Line3D(GetRTHandle(op,0)*m,GetRTHandle(op,2)*m); bd->Line3D(GetRTHandle(op,3)*m,SwapPoint(Vector(rad+iradx,irady,0.0),axis)*m); bd->Line3D(GetRTHandle(op,4)*m,SwapPoint(Vector(rad+iradx,irady,0.0),axis)*m); return TRUE; } LONG RoundedTube::DetectHandle(PluginObject *op, BaseDraw *bd, LONG x, LONG y, LONG qualifier) { if (qualifier&QUALIFIER_CTRL) return NOTOK; Matrix mg = op->GetMg(); LONG i,ret=NOTOK; Vector p; for (i=0; i<HANDLES; i++) { p = GetRTHandle(op,i); if (bd->PointInRange(p*mg,x,y)) { ret=i; if (!(qualifier&QUALIFIER_SHIFT)) break; } } return ret; } Bool RoundedTube::MoveHandle(PluginObject *op, PluginObject *undo, const Matrix &tm, LONG hit_id, LONG qualifier) { BaseContainer *src = undo->GetDataInstance(); BaseContainer *dst = op ->GetDataInstance(); Vector handle_dir; switch (hit_id) { case 0: handle_dir = Vector( 1.0, 0.0,0.0); break; case 1: handle_dir = Vector( 1.0, 0.0,0.0); break; case 2: handle_dir = Vector( 0.0, 1.0,0.0); break; case 3: handle_dir = Vector( 0.0,-1.0,0.0); break; case 4: handle_dir = Vector(-1.0, 0.0,0.0); break; } handle_dir=SwapPoint(handle_dir,src->GetLong(PRIM_AXIS)); Real val = tm.off*handle_dir; switch (hit_id) { case 0: dst->SetReal(TUBEOBJECT_RAD,FCut(src->GetReal(TUBEOBJECT_RAD)+val,dst->GetReal(TUBEOBJECT_IRADX),MAXRANGE)); break; case 1: dst->SetReal(TUBEOBJECT_IRADX,FCut(src->GetReal(TUBEOBJECT_IRADX)+val,dst->GetReal(TUBEOBJECT_ROUNDRAD),dst->GetReal(TUBEOBJECT_RAD))); break; case 2: dst->SetReal(TUBEOBJECT_IRADY,FCut(src->GetReal(TUBEOBJECT_IRADY)+val,dst->GetReal(TUBEOBJECT_ROUNDRAD),MAXRANGE)); break; case 3: case 4: dst->SetReal(TUBEOBJECT_ROUNDRAD,FCut(src->GetReal(TUBEOBJECT_ROUNDRAD)+val,0.0,FMin(dst->GetReal(TUBEOBJECT_IRADX),dst->GetReal(TUBEOBJECT_IRADY)))); break; } return TRUE; } // be sure to use a unique ID obtained from [www.plugincafe.com](http://www.plugincafe.com) #define ID_ROUNDEDTUBEOBJECT 1001157 Bool RegisterRoundedTube(void) { // decide by name if the plugin shall be registered - just for user convenience String name=GeLoadString(IDS_ROUNDED_TUBE); if (!name.Content()) return TRUE; return RegisterObjectPlugin(ID_ROUNDEDTUBEOBJECT,name,OBJECT_GENERATOR,RoundedTube::Alloc,"Oroundedtube","roundedtube.tif","roundedtube_small.tif",0); }
It works just as fine there. May I ask you to show some of your code that causes the crash? I'd be very interested in reproducing that...
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 28/11/2002 at 09:29, xxxxxxxx wrote:
Btw, have you tried any of the other custom data types? I'm wondering if the spline type or the gradient is an exception...
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 28/11/2002 at 13:31, xxxxxxxx wrote:
Also, are you sure that TPMODIFIER_FALLOFF_SPLINE doesn't collide with anything?
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 28/11/2002 at 13:39, xxxxxxxx wrote:
I took your RoundedTube code and compiled the C4D SDK examples with it. Compiles fine, then, "Not Enough Memory". I removed all other plugins and the error message still happened. Can you send me a .cdl you know works as a test? Are you using WIN2K, VC++6, and C4D v8.012? I need to figure out what is going on here and if it is a bug or an operator error. Thanks for the assistance.
Best Regards, darf - bhodiNUT -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 01/12/2002 at 01:58, xxxxxxxx wrote:
This really puzzles me. I have WinXP, VC++6 and C4D 8.012 and no crashes. I've sent you a fresh SDK with the code. I hope it doesn't crash, because otherwise I'm completely lost...
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 23/03/2003 at 13:31, xxxxxxxx wrote:
several months later , I have the exact same problem !!
I dont
but 2 of my testers do
fo me it works just fine
but for them it gives an out of memory !!!
AutoAlloc<SplineData> falloffspline;
if ( !falloffspline ) return FALSE;falloffspline->InsertKnot( 0.0, 0.0 ); // this line will cause out of memory
falloffspline->InsertKnot( 1.0, 1.0 ); -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 24/03/2003 at 04:06, xxxxxxxx wrote:
I just gave up on this. It would be nice if it worked consistently, blah, blah...
bt
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 24/03/2003 at 06:06, xxxxxxxx wrote:
Hi there
I hope I can help to deconfuse a bit
This is just a little example how to initialize a spline, but it should work similar with every custom data type.GeData d(CUSTOMDATATYPE_SPLINE, DEFAULTVALUE); SplineData* p = (SplineData* )d.GetCustomDataType(CUSTOMDATATYPE_SPLINE); if (p) { p->MakeLinearSpline(2); p->Flip(); } your_data_container->SetData(your_id, d);