Compare commits

...

3 Commits

Author SHA1 Message Date
Jedd Morgan 201ca5f26e Update blender_commit_object_builder.py 2023-07-22 01:02:23 +01:00
Jedd Morgan 89528437b1 Merge pull request #167 from specklesystems/vertex-color-uint
Fixed issue with uint32 vertex colours not parsing
2023-07-17 21:51:18 +01:00
Jedd Morgan 91bde24fe9 Fixed issue with uint32 vertex colors not parsing 2023-07-17 21:21:28 +01:00
4 changed files with 64 additions and 32 deletions
+1 -15
View File
@@ -73,20 +73,6 @@ class BlenderCommitObjectBuilder(CommitObjectBuilder[Object]):
return convered_collection
# def find_collection_parent(self, col: Collection) -> Optional[Collection]:
# for p in bpy.data.collections:
# if col.name in p.children.keys():
# return p
# return None
#TODO: I've started an approach that will not work
# Goal #1 get all collections sending
# Sync with Claire, ask how we handle this in Rhino with partial selection of layers (proably how I'm expecting it works, but good to double check)
# Goal #2 Figure out how to send collections
# - all collections
# - all collections that contain a child collection that has geometry...
# - only collections explicitly selected
def build_commit_object(self, root_commit_object: Base) -> None:
assert(root_commit_object.applicationId in self.converted)
@@ -131,4 +117,4 @@ class BlenderCommitObjectBuilder(CommitObjectBuilder[Object]):
return should_remove_this_col
if should_remove_unuseful_collection(root_commit_object):
_report("WARNING: Only empty collections have been converted!") #TODO: consider raising exception here, to halt the send operation
_report("WARNING: Only empty collections have been converted!") #TODO: consider raising exception here, to halt the send operation
+22 -6
View File
@@ -22,6 +22,7 @@ from bpy.types import Object, Collection as BCollection
from .util import (
add_to_heirarchy,
get_render_material,
get_vertex_color_material,
render_material_to_native,
add_custom_properties,
add_vertices,
@@ -219,6 +220,8 @@ def view_to_native(speckle_view, name: str, scale: float) -> bpy.types.Object:
def mesh_to_native(speckle_mesh: Mesh, name: str, scale: float) -> bpy.types.Mesh:
return meshes_to_native(speckle_mesh, [speckle_mesh], name, scale)
def meshes_to_native(element: Base, meshes: Collection[Mesh], name: str, scale: float) -> bpy.types.Mesh:
if name in bpy.data.meshes.keys():
return bpy.data.meshes[name]
@@ -242,10 +245,16 @@ def meshes_to_native(element: Base, meshes: Collection[Mesh], name: str, scale:
add_faces(mesh, bm, offset, i)
render_material = get_render_material(mesh) or fallback_material
if render_material is not None:
native_material = render_material_to_native(render_material)
blender_mesh.materials.append(native_material)
try:
render_material = get_render_material(mesh) or fallback_material
if render_material is not None:
native_material = render_material_to_native(render_material)
blender_mesh.materials.append(native_material)
elif mesh.colors:
native_material = get_vertex_color_material()
blender_mesh.materials.append(native_material)
except Exception as ex:
_report(f"Failed converting render material for {name}: {ex}")
offset += len(mesh.vertices) // 3
@@ -254,8 +263,15 @@ def meshes_to_native(element: Base, meshes: Collection[Mesh], name: str, scale:
# Third pass, add vertex instance data
for mesh in meshes:
add_colors(mesh, bm)
add_uv_coords(mesh, bm)
try:
add_colors(mesh, bm)
except Exception as ex:
_report(f"Skipping converting vertex colors for {name}: {ex}")
try:
add_uv_coords(mesh, bm)
except Exception as ex:
_report(f"Skipping converting uv coordinates for {name}: {ex}")
bm.to_mesh(blender_mesh)
bm.free()
+40 -11
View File
@@ -1,14 +1,14 @@
import math
from typing import Any, Dict, Optional, Tuple, Union
from typing import Any, Dict, Optional, Tuple, Union, cast
from bmesh.types import BMesh
import bpy, struct, idprop
import bpy, idprop
from specklepy.objects.base import Base
from specklepy.objects.geometry import Mesh
from specklepy.objects.other import RenderMaterial
from bpy_speckle.convert.constants import IGNORED_PROPERTY_KEYS
from bpy_speckle.functions import _report
from bpy.types import Material, Object, Collection as BCollection
from bpy.types import Material, Object, Collection as BCollection, Node, ShaderNodeVertexColor
from bpy_speckle.specklepy_extras.traversal import TraversalContext
@@ -98,18 +98,42 @@ def render_material_to_native(speckle_mat: RenderMaterial) -> Material:
return blender_mat
_vertex_color_material: Optional[Material] = None
def get_vertex_color_material() -> Material:
global _vertex_color_material
#see https://stackoverflow.com/a/69807985
if not _vertex_color_material:
_vertex_color_material = bpy.data.materials.new("Vertex Color Material")
_vertex_color_material.use_nodes = True
nodes = _vertex_color_material.node_tree.nodes
principled_bsdf_node = cast(Node, nodes.get("Principled BSDF"))
if not "VERTEX_COLOR" in [node.type for node in nodes]:
vertex_color_node = cast(ShaderNodeVertexColor, nodes.new(type = "ShaderNodeVertexColor"))
else:
vertex_color_node = cast(ShaderNodeVertexColor, nodes.get("Vertex Color"))
vertex_color_node.layer_name = "Col"
links = _vertex_color_material.node_tree.links
link = links.new(vertex_color_node.outputs[0], principled_bsdf_node.inputs[0])
return _vertex_color_material
def get_render_material(speckle_object: Base) -> Optional[RenderMaterial]:
"""Trys to get a RenderMaterial on given speckle_object and convert it to a blender material"""
"""Trys to get a RenderMaterial on given speckle_object"""
speckle_mat = getattr(
speckle_object,
"renderMaterial",
getattr(speckle_object, "@renderMaterial", None),
)
if not isinstance(speckle_mat, RenderMaterial):
return None
return speckle_mat
if isinstance(speckle_mat, RenderMaterial):
return speckle_mat
return None
@@ -159,10 +183,8 @@ def add_colors(speckle_mesh: Mesh, blender_mesh: BMesh):
if len(scolors) > 0:
for i in range(len(scolors)):
col = int(scolors[i])
(a, r, g, b) = [
int(x) for x in struct.unpack("!BBBB", struct.pack("!i", col))
]
argb = int(scolors[i])
(a, r, g, b) = argb_split(argb)
colors.append(
(
float(r) / 255.0,
@@ -180,6 +202,13 @@ def add_colors(speckle_mesh: Mesh, blender_mesh: BMesh):
for loop in face.loops:
loop[color_layer] = colors[loop.vert.index]
def argb_split(argb: int) -> Tuple[int, int, int, int]:
alpha = (argb >> 24) & 0xFF
red = (argb >> 16) & 0xFF
green = (argb >> 8) & 0xFF
blue = argb & 0xFF
return (alpha, red, green, blue)
def add_uv_coords(speckle_mesh: Mesh, blender_mesh: BMesh):
s_uvs = speckle_mesh.textureCoordinates
+1
View File
@@ -196,6 +196,7 @@ class ReceiveStreamObjects(bpy.types.Operator):
for item in traversalFunc.traverse(commit_object):
current: Base = item.current
if can_convert_to_native(current) or isinstance(current, SCollection):
try:
if not current or not current.id: raise Exception(f"{current} was an invalid speckle object")