mifth / mifthtools

MifthTools
BSD 3-Clause "New" or "Revised" License
871 stars 129 forks source link

Fix "RuntimeError: Error: Object 'Sphere' has no evaluated mesh data" in snap_surface on Blender 2.83 #29

Closed feynmanliang closed 4 years ago

feynmanliang commented 4 years ago

Repro: On blender 2.83 (527c81), try to run the example in https://media.blenderartists.org/uploads/default/original/4X/5/a/2/5a20849c44986cc039c5fa2b528a557ccb8fd08e.png

Expected: dragging the blue dot should extrude along sphere by raycasting from mouse

Actual: Error modal with RuntimeError: Error: Object 'Sphere' has no evaluated mesh data

This change forces evaluation of the mesh for the object which we are trying to raycast. It looks like Object.ray_cast should be doing the BVHTree conversion itself (https://git.blender.org/gitweb/gitweb.cgi/blender.git/blob/HEAD:/source/blender/makesrna/intern/rna_object_api.c#l540), but for some reason removing the BVHTree.FromObject reproduces the error.


This change is Reviewable

mifth commented 4 years ago

I'm trying blender 2.90 and I cannot reproduce the issue. ((

feynmanliang commented 4 years ago

Here is a screen recording of the issue on Blender 2.83 release, and I uploaded the secene at https://gofile.io/d/J8RkLs. I also verified this on 2.90a release 76324 as well as master 3bc3b58.

I tried updating the scene ("view layer" in 2.80+ so bpy.context.view_layer.update()) but it has no effect on the issue. I dove into the Blender source and it looks like making the BVHTree using FromObject results in a call to bvh_get_mesh, which calls DerivedMesh's mesh_get_eval_final and mesh_build_data, which ultimately calls BKE_object_eval_assign_data to assign the object_eval->runtime.data_eval field which is checked at the start of Object.ray_cast method's C implementation by eval_object_ensure (which is where our error is produced).

I agree that creating this tree in the loop is not very efficient, but I think the current code's use of Object.ray_cast might also already be creating BVHTrees every polling frame.

One way we might be able to get around is like you said: instantiate the BVHTree directly in the addon rather than relying on Object.ray_cast, maybe in the get_obj_dup_meshes method when obj_snap_mode is SELECTED? It seemed to me that this would change behavior since the BVHTrees would be created once on operator invoke rather than recalculated every ray-cast, so in particular changing the geometry of the snapping surface after invoking would result in ray casts against the stale cached mesh geometry. This might be OK for curve draw (where we are not changing the geometry of the snapping surface), but since get_obj_dup_meshes is used in a few other places I wasn't familiar enough with the codebase to comfortably make this change.

mifth commented 4 years ago

Great! Thank you for the blend file and explanation. I have put your code into get_obj_dup_meshes(). When any tool is activeted it will pass through this method if snapping is enabled. Could you check it, please? https://github.com/mifth/mifthtools/commit/10b8cd7bd85336c0e1453374ac5854ebf6735ccf

feynmanliang commented 4 years ago

Yes, it works great. Thank you very much for sharing your tools, they are some of my favorite :)

mifth commented 4 years ago

Thank you too. ))

I have another question. If I have 5 hipoly objects(3 million polygons, for example) which I will raycast... Will this function takes more memory and time? As the function parses all visible objects. I just dunno know what BVHTree does. Maybe this is a bug and we should report it to blender devs?

mifth commented 4 years ago

I did another test with hipoly models.

https://www.dropbox.com/s/cmzriakbz4jcf62/tmp.zip?dl=0

image

And performance is very bad. I wait for the tool(DrawExtrude, CurveSurfaces) about one second. It's too long. But if I comment BVHTree.FromObject(obj, depsgraph) all will be fast.

mifth commented 4 years ago

I figured out why you had the crash in your original scene. The sphere was in Edit Mode. image

Raycast system was designed to raycast at all objects which are not in edit mode. It should be like this: image

I did another fix for this case. Now all should work ok. https://github.com/mifth/mifthtools/commit/cf99bc5811215a8747c43d84895ba4fa806812b7

feynmanliang commented 4 years ago

Thank you for following up :+1: I verified it works on 2.90, and performance in https://github.com/mifth/mifthtools/commit/cf99bc5811215a8747c43d84895ba4fa806812b7 when ray-casting to visible in large scenes is improved compared to https://github.com/mifth/mifthtools/commit/10b8cd7bd85336c0e1453374ac5854ebf6735ccf

You're absolutely right that I had the sphere in edit mode. I was trying to snap to selected objects (https://github.com/mifth/mifthtools/blob/master/blender/addons/2.8/mira_tools/mi_settings.py#L49) by following the instructions:

In fact, what I should have done is:

  1. Select the plane
  2. Switch to edit mode first.
  3. After, select the object to snap to.

BTW, I think edit-mode raycasting used to work in 2.7x when we didn't have depsgraph (as long as the scene was updated after linking the object), but with the depsgraph update in 2.8x the mesh data is not there until BKE_object_eval_assign_data is called. It looks like others are having this issue too. I'm not sure if ray_cast in edit mode is unsupported by design or not... the API is quite messy (there are two ray_cast methods, one on Object and one on BVHTree, and they return arguments in different order) but if it turns out that the developers don't intend to support this then maybe it's better for us to raise a warning instead of relying on BVHTree.FromObject to internally call BKE_object_eval_assign_data to make this work ;)

mifth commented 4 years ago

Ah! Now I get you. This guide was made when there was the first version of the tool. It allowed to raycast only selected objects. And in 2.7 there was no possibility to edit multiple objects.

feynmanliang commented 4 years ago

Makes sense, thanks for explaining!

On Fri, May 8, 2020, 8:21 AM mifth notifications@github.com wrote:

Ah! Now I get you. This guide was made when there was the first version of the tool. It allowed to raycast only selected objects. And in 2.7 there was no possibility to edit multiple objects.

— You are receiving this because you modified the open/close state. Reply to this email directly, view it on GitHub https://github.com/mifth/mifthtools/pull/29#issuecomment-625867699, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAHRW5IQNJ3QCZZHRGWKLS3RQQPQZANCNFSM4M2EPXLQ .