Plugin Cafe Homepage
Forum Home Forum Home > Plugin Cafe > PYTHON Development
  New Posts New Posts
  FAQ FAQ  Forum Search   Register Register  Login Login

Generating Topo Map from Object

 Post Reply Post Reply
Author
Message
Remo Pini View Drop Down
Member
Member


Joined: 2017 Aug 05
Online Status: Offline
Posts: 24
Post Options Post Options   Quote Remo Pini Quote  Post ReplyReply Direct Link To This Post Topic: Generating Topo Map from Object
    Posted: 2017 Aug 10 at 12:55pm
This is driving me crazy...

I have an object with a few vertices and try to create a topo map from it (an image with color based on the Y value).

Here's the script I use:

import c4d

def main():
    doc = c4d.documents.GetActiveDocument()
    png = c4d.bitmaps.BaseBitmap()
    png.Init(257, 257)
   
    obj = doc.GetFirstObject()
       
    for i,pt in enumerate(obj.GetAllPoints()):
        mx = 128 + int(pt.x)
        my = 128 - int(pt.z)
        col = 128 + pt.y
        png.SetPixel(mx, my, col, col, col)

    png.Save("e:\test.png", c4d.FILTER_PNG)
       
if __name__=='__main__':
    main()


The resulting PNG should look like a checker board, however, it absolutely doesn't:


I'm doing something really really wrong, but I have no clue what it could be...
Here's the C4D file I use: http://35.io/media/test.c4d
Back to Top
gr4ph0s View Drop Down
Member
Member


Joined: 2015 Jul 07
Location: France
Online Status: Offline
Posts: 306
Post Options Post Options   Quote gr4ph0s Quote  Post ReplyReply Direct Link To This Post Posted: 2017 Aug 10 at 3:03pm
I can't see any bug or any unexcepted event. You mesh is not evently distrubuted. By that I mean each raw are not valid int so basicly you round it (so it's why some pixel are never printed).
Another solution for you would be to use https://developers.maxon.net/docs/Cinema4DPythonSDK/html/modules/c4d.utils/GeRayCollider/index.html#c4d.utils.GeRayCollider and create an even spaced grid and not use actual geometry.
So it will end with something like this
import c4d

def get_height(ray, x, y, height=10000):
    start_pos = c4d.Vector(x, height, y)
    ray_dir = c4d.Vector(0, -1, 0)
    ray_lenght = height*2
    if ray.Intersect(start_pos, ray_dir, ray_lenght):
        intersection = ray.GetNearestIntersection()
        hit_pos = intersection["hitpos"]
        
        return hit_pos.y
    
    return 0

def optimize(obj, tolerance):
    doc = c4d.documents.GetActiveDocument()
    doc.AddUndo(c4d.UNDOTYPE_CHANGE, obj)

    settings = c4d.BaseContainer()
    settings[c4d.MDATA_OPTIMIZE_TOLERANCE] = tolerance
    settings[c4d.MDATA_OPTIMIZE_POINTS] = True
    settings[c4d.MDATA_OPTIMIZE_POLYGONS] = True
    settings[c4d.MDATA_OPTIMIZE_UNUSEDPOINTS] = True
    c4d.utils.SendModelingCommand(command=c4d.MCOMMAND_OPTIMIZE,
                                  list=[obj],
                                  mode=c4d.MODELINGCOMMANDMODE_ALL,
                                  bc=settings,
                                  doc=doc)

def main():    
    doc = c4d.documents.GetActiveDocument()
    obj = doc.GetFirstObject()
    optimize(obj, 0.001)
    
    ray = c4d.utils.GeRayCollider()
    ray.Init(obj)
    
    bmp = c4d.bitmaps.BaseBitmap()
    bmp.Init(256, 256)
    
    bounding_box_y = obj.GetRad().y
    for x in range(-128, 128):
        for y in range(-128, 128):
            
            h = get_height(ray, x, y)
            
            mx = 128 + int(x)
            my = 255 - (128 + int(y))
            
            normalized_height = c4d.utils.Smoothstep(-bounding_box_y, bounding_box_y, h)
            heigt_color = normalized_height * 255
            bmp.SetPixel(mx, my, heigt_color, heigt_color, heigt_color)
            
    c4d.bitmaps.ShowBitmap(bmp)
    

        
if __name__=='__main__':
    main()
Btw I this example I assume, the obj is in the default c4d orientation and his pivot is centered in the object.


Edited by gr4ph0s - 2017 Aug 10 at 3:18pm
Technical lover.
Aviable for job in october.
Back to Top
Remo Pini View Drop Down
Member
Member


Joined: 2017 Aug 05
Online Status: Offline
Posts: 24
Post Options Post Options   Quote Remo Pini Quote  Post ReplyReply Direct Link To This Post Posted: 2017 Aug 11 at 2:48am
Thx for the input. I was looking at GeRayCollider, but was afraid that the performance of calculating all those intersections is waaay lower than just getting the Z values of "known" points. The grid should be perfectly distributed, i.e. if I look at the X/Z coordinates of the mesh, they are all on pure integers (0, 1, ...., 256) for both axes... that's why I'm confused by getting these rounding artifacts.

I'll do the ray thing to see what happens performance wise.


Edited by Remo Pini - 2017 Aug 11 at 2:48am
Back to Top
gr4ph0s View Drop Down
Member
Member


Joined: 2015 Jul 07
Location: France
Online Status: Offline
Posts: 306
Post Options Post Options   Quote gr4ph0s Quote  Post ReplyReply Direct Link To This Post Posted: 2017 Aug 11 at 5:19am
I guess you will understand in a second with this picture why I said your mesh is not a trully even spaced grid.
https://img4.hostingpics.net/pics/179097point.jpg

About performence Ray are pretty fast, just make sure to init the ray object before the loop and not inside the loop.
Technical lover.
Aviable for job in october.
Back to Top
Remo Pini View Drop Down
Member
Member


Joined: 2017 Aug 05
Online Status: Offline
Posts: 24
Post Options Post Options   Quote Remo Pini Quote  Post ReplyReply Direct Link To This Post Posted: 2017 Aug 11 at 1:06pm
I guess our view on what "evenly spaced" means is different :). What I mean is that the coordinates of the points are perfectly aligned to 256, 254, 252, ... 0, ... -2, ... -256 (X and Y). There are "two grids", the outer on all even integers and the inner on all odd integers. Theoretically, this should lead to a perfect checker board pattern in the depth map (with every other pixel not set), but it doesn't. I don't understand where the rounding errors come from...



Back to Top
Andreas Block View Drop Down
Forum Moderator
Forum Moderator
Avatar

Joined: 2014 Oct 01
Location: Hannover
Online Status: Offline
Posts: 1430
Post Options Post Options   Quote Andreas Block Quote  Post ReplyReply Direct Link To This Post Posted: 2017 Aug 14 at 9:17am
It's of course a bit hard to tell without knowing your scene. But for example keep in mind int() will always truncate the decimals, so for example int(0.99999999) will result in zero. So maybe you want to try proper rounding first to see if it changes anything.
Cheers,
Andreas
SDK Support Engineer
Back to Top
 Post Reply Post Reply

Forum Jump Forum Permissions View Drop Down

Bulletin Board Software by Web Wiz Forums® version 9.61 [Free Express Edition]
Copyright ©2001-2009 Web Wiz

This page was generated in 0.102 seconds.