Jump to content

bjlotus

Limited Member
  • Posts

    10
  • Joined

  • Last visited

About bjlotus

  • Birthday 06/15/1985

Profile Information

  • First Name
    Jon
  • Last Name
    B

HW | SW Information

  • OS
    Windows
  • CPU
    Intel

Recent Profile Visitors

868 profile views

bjlotus's Achievements

Newbie

Newbie (1/14)

  • Week One Done
  • One Month Later
  • One Year In

Recent Badges

2

Reputation

  1. Hi @zipit! oh, now I totally understand what you mean! (pun intended 😄) Thanks so much for the clarification; that would explain the tiny differences when I compared the results using your function. PS: it didn't sound pedantic at all! Best, Jon
  2. Hi @zipit, First of all, thank you so much for your reply and the super detailed comments on your code, it really helps me understand a few things (and hopefully to many other beginners as well). Your script does -almost- exactly what I was trying to do... and more importantly, the comments helps to grasp the hows and whys very clearly. Again, really appreciate your input, thanks 😄 I'm calculating the mean (i think) using the "normals_avg" variable. I add each cross product inside the for loop and then divide by the amount of polys selected. This was a quick example so I just calculated normals the way I remembered when I used to play with other software years ago. I'm not even checking if the polys are a triangle hehe... your GetPolygonNormal function is certainly more elegant. I compared the results and, while not always exactly the same, they are pretty close. Yeap, no flattening on the code I posted; what I was trying to do was: given a selection, first translate it by a fixed amount and then flatten it. The flatten part was what I didn't know how to do and what @Cairyn was kindly trying to explain. Sure thing! I know it's a bit messy and that there're probably some extra assignments, or things I should rewrite as functions; Being just an example I was just throwing lines testing what happens. I'm just starting to explore python's possibilities inside c4d (never used python before), so your version does definitely helps in many ways (even about how to keep things tidy!) Once again, thank you. Have a great day! Jon
  3. Hi @Cairyn, thanks again for your input! You're right about the flattening area position, I should use the average of the points and then mess with bounding boxes if needed, which of course can be tricky on odd shaped objects. Well, I'm a bit rusty when it comes to 3D to be honest. I'm not sure how I can create my flatten plane based on the avg normal and avg points... but rainy day ahead, so I'll be trying! Thanks! Jon
  4. Hi @Cairyn, thanks for your reply. I think I conceptually understand what you said, but I don't have a clue about how to implement it... I wrote a little example as an exercise, where I create a tube, select a couple polygons and translate the selected polygons based on the average normals. After that, I'd like to flatten out the selection... At some point I calculated the average points to see if that could be where the flattening might be applied (which is close to the modelling axis, when orientation is set to 'normals'), but I think I'd like to flatten where the selection starts, as shown in red on the following image: I've also added a couple colored nulls where the average normals (yellow) and average points (cyan) are, just for reference. import c4d from c4d import utils # ----------------------------------------------------------------------------------------------------------------------- # Main function # ----------------------------------------------------------------------------------------------------------------------- def main(): doc = c4d.documents.GetActiveDocument() #create an object and make it editable (use clone when using csto) obj = c4d.BaseObject(c4d.Otube) obj[c4d.PRIM_TUBE_IRAD] = 50 # inner rad obj[c4d.PRIM_TUBE_ORAD] = 100 # outer rad obj[c4d.PRIM_TUBE_HEIGHT] = 20 # height obj[c4d.PRIM_TUBE_SEG] = 12 # rotation segments obj[c4d.PRIM_TUBE_CSUB] = 1 # cap segments obj[c4d.PRIM_TUBE_HSUB] = 1 # height segments obj[c4d.PRIM_AXIS] = 2 # axis (2 = +Y) result = utils.SendModelingCommand( command=c4d.MCOMMAND_CURRENTSTATETOOBJECT, list=[obj.GetClone()], mode=c4d.MODELINGCOMMANDMODE_ALL, doc=doc) obj = result[0] # optimize the obj bc = c4d.BaseContainer() # contain settings # set optimize (default c4d) bc.SetFloat(c4d.MDATA_OPTIMIZE_TOLERANCE, .01) bc.SetBool(c4d.MDATA_OPTIMIZE_POINTS, True) bc.SetBool(c4d.MDATA_OPTIMIZE_POLYGONS, True) bc.SetBool(c4d.MDATA_OPTIMIZE_UNUSEDPOINTS, True) result = c4d.utils.SendModelingCommand( # optimize, result returns Boolean command=c4d.MCOMMAND_OPTIMIZE, list=[obj], doc=doc, bc=bc) obj.Message(c4d.MSG_UPDATE) # update object doc.InsertObject(obj) # add to scene selected_polys = obj.GetPolygonS() #get selected polys/base select #select arbitrary polys selected_polys.Select(9) selected_polys.Select(13) selected_points = [] #to hold point vectors selected_points_indexes = [] #to hold points indexes selected_polygons_indexes = [] #to hold polygons indexes polys_count = obj.GetPolygonCount() #get number of polys polys_list = selected_polys.GetAll(polys_count) #list of poly indexes holding boolean values: 1: selected, 0: not selected points = obj.GetAllPoints() # get all object points normals_avg = 0 #store average of normals #loop through polys, process if selected (true) for i in xrange(polys_count): if polys_list[i]: polygon = obj.GetPolygon(i) #get polygon selected_polygons_indexes.append(i) a, b, c, d = points[polygon.a], points[polygon.b], points[polygon.c], points[polygon.d] #there could be shared points on neighbour polys, this checks they're not added multiple times if a not in selected_points: selected_points.append(a) selected_points_indexes.append(polygon.a) if b not in selected_points: selected_points.append(b) selected_points_indexes.append(polygon.b) if c not in selected_points: selected_points.append(c) selected_points_indexes.append(polygon.c) if d not in selected_points: selected_points.append(d) selected_points_indexes.append(polygon.d) #cross product cross = (b - a).Cross(d - a).GetNormalized() #add to avg normals_avg += cross #calculate avg normals_avg = normals_avg / selected_polys.GetCount() doc.InsertObject(createColorNull(normals_avg, "normals_avg", 255, 255, 0), parent=None)#display a yellow null where normals_avg is #translate points offset = 30 # arbitrary amount in cm for i in xrange(len(selected_points)): obj.SetPoint(selected_points_indexes[i], selected_points[i] + normals_avg * offset) #update selected points points = obj.GetAllPoints() points_avg = 0 # average pos of selected points selected_points = [] #reset for i in xrange(len(selected_polygons_indexes)): polygon = obj.GetPolygon(selected_polygons_indexes[i]) # get polygon a, b, c, d = points[polygon.a], points[polygon.b], points[polygon.c], points[polygon.d] if a not in selected_points: selected_points.append(a) if b not in selected_points: selected_points.append(b) if c not in selected_points: selected_points.append(c) if d not in selected_points: selected_points.append(d) print("sel points", selected_points) #calculate avg points for i in xrange(len(selected_points)): points_avg += selected_points[i] points_avg = points_avg / len(selected_points) doc.InsertObject(createColorNull(points_avg, "points_avg", 0, 255, 255), parent=None) #display a cyan null where points_avg is obj.Message(c4d.MSG_UPDATE) # update object doc.Message(c4d.MSG_UPDATE) # update doc c4d.EventAdd() # refresh viewport # ----------------------------------------------------------------------------------------------------------------------- # Creates a color null/point # ----------------------------------------------------------------------------------------------------------------------- def createColorNull(pos, name, red, green, blue): null = c4d.BaseObject(c4d.Onull) if null is None: sys.exit('Could not create parent Null object!') null.SetName(name) null.SetRelPos(pos) null[c4d.NULLOBJECT_DISPLAY] = 1 null[c4d.NULLOBJECT_RADIUS] = 3 null[c4d.NULLOBJECT_ASPECTRATIO] = 1 null[c4d.NULLOBJECT_ORIENTATION] = 1 null[c4d.ID_BASEOBJECT_USECOLOR] = 2 null[c4d.NULLOBJECT_ICONCOL] = True r = c4d.utils.RangeMap(value=red, mininput=0, maxinput=255, minoutput=0, maxoutput=1, clampval=True) g = c4d.utils.RangeMap(value=green, mininput=0, maxinput=255, minoutput=0, maxoutput=1, clampval=True) b = c4d.utils.RangeMap(value=blue, mininput=0, maxinput=255, minoutput=0, maxoutput=1, clampval=True) null[c4d.ID_BASEOBJECT_COLOR] = c4d.Vector(r, g, b) return null # ----------------------------------------------------------------------------------------------------------------------- # Execute main() # ----------------------------------------------------------------------------------------------------------------------- if __name__ == '__main__': main() Any inputs on how should I continue to be able to flatten? Please keep in mind I'm kinda slow on this things 🙂 Thanks! Jon
  5. Hi all, I've been playing around with python inside c4d for the last couple days, just for the sake of learning something new (and open future creative possibilities, why not). I've been able to manipulate splines and polygons, create objects from scratch and send modelling commands... now, I want to do this 'simple thing' and I'm a bit stuck: I want to be able to 'flatten' a polygon selection based on the normals, like when you drag the scale axis to 0% on z handle when modelling. So far I've been able to move the selected polygons (or its points) based on the normal direction, but can't seem to get this one. Any hints will be greatly appreciated. PS: I know there're a few plugins around, but I just want to know how it works internally and the math involved, so I can try and implement a modelling sequence. Thanks! Jon
×
×
  • Create New...