1
$\begingroup$

I'm trying to use bezier curves for editing paths of a custom game file format.

A weird bug (?) when switching to Edit Mode makes the bezier spline points lose their Z coordinate, it being set to 0, and I have no clue why.

Here's the code that simply creates a new bezier curve, adds a spline with enough points and feeds it the coordinates of the control points and handles.

# Create a bezier curve object representing the Path.
cu = bpy.data.curves.new("Path", 'CURVE')
ob = bpy.data.objects.new("Path", cu)
self.context.scene.objects.link(ob)
self.context.scene.objects.active = ob
# Add the points to a new spline.
sp = cu.splines.new('BEZIER')
sp.use_cyclic_u = path["IsClosed"]
points = path["PathPt"]
sp.bezier_points.add(len(points) - 1)  # There is already one point in new curves, so add one less.
for i, point in enumerate(points):
    pt = sp.bezier_points[i]
    pt.co = vector_from_dict(point["Translate"], invert_z=True)
    pt.handle_left = vector_from_dict(point["ControlPoints"][0], invert_z=True)
    pt.handle_right = vector_from_dict(point["ControlPoints"][1], invert_z=True)
# Lock the transform as paths are always in the global coordinate system.
ob.lock_location = [True] * 3
ob.lock_rotation = [True] * 3
ob.lock_scale = [True] * 3
return ob

def vector_from_dict(dictionary, invert_z=False):
    # Game file format is right handed with Y up, convert accordingly.
    if invert_z:
        return dictionary["X"], -dictionary["Z"], dictionary["Y"]
    else:
        return dictionary["X"], dictionary["Z"], dictionary["Y"]

As said, this imports fine and looks well at first. Hence this path of birds flying around the palm trees and above the house ceiling in the front:

enter image description here

But as soon as I enter Edit Mode, the path drops down to the floor, the Z coordinate of all points has become 0 (0 is far below the game model)!

enter image description here

It's indeed just Z losing its value, I imported the path again without editing it this time, making it very clear - the correct one is above, the one with the edit attempt lieing flat below:

enter image description here

Going back to Object Mode keeps these "corrupted" coordinates! What is going wrong here?

The file format itself is stored as binary, but also nothing special, and a Path in it can be represented as dictionaries and arrays like this:

{
    "IsClosed": True,
    "PathPoints":
    [
        {
            "Handles":
            [
                {"X": -2374.132, "Y": 2985.336, "Z": 2211.747},
                {"X": -2318.274, "Y": 2964.664, "Z": 1901.128}
            ],
            # Can't import Rotate since no Blender support for bezier point normals =(
            "Rotate": {"X": -2.684734, "Y": 0.167497, "Z": -3.044649},
            "Translate": {"X": -2346.203, "Y": 2975, "Z": 2056.438}
        },
        {
            "Handles":
            [
                {"X": -2277.908, "Y": 2960.383, "Z": 1596.964},
                {"X": -2294.248, "Y": 2989.617, "Z": 1175.442}
            ],
            "Rotate": {"X": -2.808016, "Y": -0.1063031, "Z": 3.136256},
            "Translate": {"X": -2286.078, "Y": 2975, "Z": 1386.203}
        },
        # ... and so on for each point ...
    ]
}
$\endgroup$
2
$\begingroup$

I'm not much into scripting or coding and now very little about Python myself, so apologies if this doesn't fix your problem, but I believe this is happening because your bezier curve seems to be in 2D mode (in your first screenshot), hence when entering edit mode it will automatically ignore any Z coordinates that it should not have in the first place.

Set your bezier curve to 3D either through the Properties Window > Object Data (Curve) > Shape > 3D or using the Pyhton API through bpy.types.Curve.dimensions setting it to 3D

$\endgroup$
  • 1
    $\begingroup$ Just wow, how could I miss that? Interesting too see how it behaves when incorrectly set up from code. Setting it to 3D by code with cu.dimensions = '3D' fixes it =D $\endgroup$ – Ray Aug 1 '16 at 21:06
  • $\begingroup$ I had found a few instances of this weird behavior when importing curves with certain addons (DXF, SVG, etc.) The curves would allow setting up points in the Z axis even though they were 2D, then resetting them to 2D would clear up the incorrect Z values, though it had the unexpected benefit of allowing capped 3D curves $\endgroup$ – Duarte Farrajota Ramos Aug 1 '16 at 21:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.