Skip to content

Commit

Permalink
Merge pull request #16 from OmooLab/feature/dev
Browse files Browse the repository at this point in the history
fix: label join scalar cannot get scalar offset
  • Loading branch information
icrdr authored May 31, 2024
2 parents 56606fd + 2528d98 commit e0c46e9
Show file tree
Hide file tree
Showing 8 changed files with 93 additions and 114 deletions.
4 changes: 2 additions & 2 deletions bioxelnodes/assets/Nodes/BioxelNodes_4.0.blend
Git LFS file not shown
4 changes: 2 additions & 2 deletions bioxelnodes/assets/Nodes/BioxelNodes_4.1.blend
Git LFS file not shown
12 changes: 7 additions & 5 deletions bioxelnodes/customnodes/menus.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,16 +163,18 @@ def find_item(self, node_type: str):

def add_node(self, node_tree, node_type: str):
item = self.find_item(node_type)
op = AddCustomNode()
op.nodes_file = self.nodes_file
op.node_type = node_type
if item:
op = AddCustomNode()
op.nodes_file = self.nodes_file
op.node_type = item['node_type']
op.node_label = item.get('label') or ""
op.node_link = item.get('link') or True
op.node_callback = item.get('node_callback') or ""
return op.add_node(node_tree)
else:
raise RuntimeError("Not found in menu.")
op.node_label = ""
op.node_link = True
op.node_callback = ""
return op.add_node(node_tree)

def register(self):
for cls in self.menu_classes:
Expand Down
30 changes: 16 additions & 14 deletions bioxelnodes/io.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,14 +236,14 @@ def execute(self, context):

if self.read_as == "labels":
if "vector" in image.GetPixelIDTypeAsString():
print("Convet to Grayscale...")
print("Conveting to Grayscale...")
image = x2gray(image)
else:
image = sitk.Cast(image, sitk.sitkUInt16)
default_value = 0
elif self.read_as == "scalar":
if "vector" in image.GetPixelIDTypeAsString():
print("Convet to Grayscale...")
print("Conveting to Grayscale...")
image = rgb2gray(image)
else:
image = sitk.Cast(image, sitk.sitkFloat32)
Expand All @@ -258,6 +258,9 @@ def execute(self, context):
interpolator = sitk.sitkNearestNeighbor
elif self.resample_method == "gaussian":
interpolator = sitk.sitkGaussian

if self.read_as == "labels":
interpolator = sitk.sitkNearestNeighbor

print(f"Resampling...")
image = sitk.Resample(
Expand Down Expand Up @@ -448,16 +451,15 @@ def create_layer(array, layer_name, layer_type="scalar"):
input_node = get_node_by_type(nodes, 'NodeGroupInput')[0]
output_node = get_node_by_type(nodes, 'NodeGroupOutput')[0]

node_type = 'BioxelNodes_AsLabel' if layer_type == "label" else 'BioxelNodes_AsScalar'
source_node = custom_nodes.add_node(nodes, node_type)
to_layer_node = custom_nodes.add_node(nodes, "BioxelNodes__ConvertToLayer")

links.new(input_node.outputs[0], source_node.inputs[0])
links.new(source_node.outputs[0], output_node.inputs[0])
links.new(input_node.outputs[0], to_layer_node.inputs[0])
links.new(to_layer_node.outputs[0], output_node.inputs[0])

source_node.inputs['Bioxel Size'].default_value = bioxel_size
source_node.inputs['Shape'].default_value = layer_shape
source_node.inputs['Origin'].default_value = layer_origin
source_node.inputs['Rotation'].default_value = layer_rotation
to_layer_node.inputs['Bioxel Size'].default_value = bioxel_size
to_layer_node.inputs['Shape'].default_value = layer_shape
to_layer_node.inputs['Origin'].default_value = layer_origin
to_layer_node.inputs['Rotation'].default_value = layer_rotation

return layer

Expand Down Expand Up @@ -511,10 +513,10 @@ def create_layer(array, layer_name, layer_type="scalar"):
layer_type="scalar")

layer_node_tree = layer.modifiers[0].node_group
source_node = layer_node_tree.nodes['BioxelNodes_AsScalar']
source_node.inputs['Offset'].default_value = scalar_offset
source_node.inputs['Max'].default_value = orig_max
source_node.inputs['Min'].default_value = orig_min
to_layer_node = layer_node_tree.nodes['BioxelNodes__ConvertToLayer']
to_layer_node.inputs['Scalar Offset'].default_value = scalar_offset
to_layer_node.inputs['Scalar Max'].default_value = orig_max
to_layer_node.inputs['Scalar Min'].default_value = orig_min

output_node = get_node_by_type(container_node_tree.nodes,
'NodeGroupOutput')[0]
Expand Down
50 changes: 2 additions & 48 deletions bioxelnodes/nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,29 +166,6 @@ def set_prop_to_node_factory(source_prop, target_prop):
'icon': 'CONSTRAINT_BONE',
'node_type': 'BioxelNodes_JoinComponent',
'node_description': ''
},
{
'label': 'Separate Component',
'node_type': 'BioxelNodes_SeparateComponent',
'node_description': ''
}
]
},
{
'label': 'Others',
'icon': 'PACKAGE',
'items': [
{
'label': 'Source As Label',
'icon': 'GP_SELECT_POINTS',
'node_type': 'BioxelNodes_AsLabel',
'node_description': ''
},
{
'label': 'Source As Scalar',
'icon': 'GP_SELECT_STROKES',
'node_type': 'BioxelNodes_AsScalar',
'node_description': ''
}
]
}
Expand Down Expand Up @@ -286,9 +263,9 @@ def set_prop_to_node_factory(source_prop, target_prop):
'icon': 'MOD_BEVEL',
'items': [
{
'label': 'Apply Cutters',
'label': 'Cut',
'icon': 'MOD_BEVEL',
'node_type': 'BioxelNodes_ApplyCutters',
'node_type': 'BioxelNodes_Cut',
'node_description': ''
},
"separator",
Expand All @@ -315,29 +292,6 @@ def set_prop_to_node_factory(source_prop, target_prop):
'icon': 'CONSTRAINT_BONE',
'node_type': 'BioxelNodes_JoinComponent',
'node_description': ''
},
{
'label': 'Separate Component',
'node_type': 'BioxelNodes_SeparateComponent',
'node_description': ''
}
]
},
{
'label': 'Others',
'icon': 'PACKAGE',
'items': [
{
'label': 'Source As Label',
'icon': 'GP_SELECT_POINTS',
'node_type': 'BioxelNodes_AsLabel',
'node_description': ''
},
{
'label': 'Source As Scalar',
'icon': 'GP_SELECT_STROKES',
'node_type': 'BioxelNodes_AsScalar',
'node_description': ''
}
]
}
Expand Down
52 changes: 45 additions & 7 deletions bioxelnodes/operators.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,14 @@ def execute(self, context):

layers = []
if self.scalar_layer != "None":
layers.append(bpy.data.objects[self.scalar_layer])
scalar_layer = bpy.data.objects[self.scalar_layer]
layers.append(scalar_layer)

if self.label_layer != "None":
layers.append(bpy.data.objects[self.label_layer])
label_layer = bpy.data.objects[self.label_layer]
layers.append(label_layer)

# if self.color_layer:
# layers.append(bpy.data.objects[self.color_layer])
# TODO: add color and vector

if len(layers) == 0:
self.report({"WARNING"}, "No additinal layers setted.")
Expand All @@ -106,8 +107,45 @@ def execute(self, context):
filepath=str(vdb_path), align='WORLD', location=(0, 0, 0), scale=(1, 1, 1))

joined_layer = bpy.context.active_object
bpy.ops.object.modifier_add(type='NODES')
joined_layer.modifiers[0].node_group = base_layer.modifiers[0].node_group

base_layer_node = base_layer.modifiers[0].node_group.nodes['BioxelNodes__ConvertToLayer']
bioxel_size = base_layer_node.inputs['Bioxel Size'].default_value
layer_shape = base_layer_node.inputs['Shape'].default_value
layer_origin = base_layer_node.inputs['Origin'].default_value
layer_rotation = base_layer_node.inputs['Rotation'].default_value
scalar_offset = base_layer_node.inputs['Scalar Offset'].default_value
scalar_min = base_layer_node.inputs['Scalar Min'].default_value
scalar_max = base_layer_node.inputs['Scalar Max'].default_value

if self.scalar_layer != "None":
scalar_layer_node = scalar_layer.modifiers[0].node_group.nodes['BioxelNodes__ConvertToLayer']
scalar_offset = scalar_layer_node.inputs['Scalar Offset'].default_value
scalar_min = scalar_layer_node.inputs['Scalar Min'].default_value
scalar_max = scalar_layer_node.inputs['Scalar Max'].default_value

bpy.ops.node.new_geometry_nodes_modifier()
node_tree = joined_layer.modifiers[0].node_group
nodes = node_tree.nodes
links = node_tree.links

input_node = get_node_by_type(nodes, 'NodeGroupInput')[0]
output_node = get_node_by_type(nodes, 'NodeGroupOutput')[0]


joined_layer_node = custom_nodes.add_node(
nodes, "BioxelNodes__ConvertToLayer")


links.new(input_node.outputs[0], joined_layer_node.inputs[0])
links.new(joined_layer_node.outputs[0], output_node.inputs[0])

joined_layer_node.inputs['Bioxel Size'].default_value = bioxel_size
joined_layer_node.inputs['Shape'].default_value = layer_shape
joined_layer_node.inputs['Origin'].default_value = layer_origin
joined_layer_node.inputs['Rotation'].default_value = layer_rotation
joined_layer_node.inputs['Scalar Offset'].default_value = scalar_offset
joined_layer_node.inputs['Scalar Min'].default_value = scalar_min
joined_layer_node.inputs['Scalar Max'].default_value = scalar_max

# Set props to VDB object
joined_layer.name = f"{base_layer.name}_Joined"
Expand Down Expand Up @@ -169,7 +207,7 @@ def execute(self, context):
object_node = nodes.new("GeometryNodeObjectInfo")
realize_nodes = nodes.new("GeometryNodeRealizeInstances")
separate_node = custom_nodes.add_node(
nodes, "BioxelNodes_SeparateComponent")
nodes, "BioxelNodes__SeparateComponent")

object_node.inputs[0].default_value = container
separate_node.inputs[1].default_value = 1
Expand Down
2 changes: 1 addition & 1 deletion docs/features.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## Bioxel Design Concept

According to Bioxel design concept, Bioxel Nodes imports volume data and put it into a **Container** as a **Layer**. One container may has more than one layer, and each layer stores the information of different fields under the same location, which is similar to the view layer of map app, except that here it is in 3D space. In order to render the volume the way we want it to, we need to build a renderable object from layers. We call this object **Component**. The following diagram shows the relationship of **Container**, **Layer**, and **Component**:
According to Bioxel design concept, Bioxel Nodes imports volume data and put it into a **Container** as a **Layer**. One container may has more than one layer, and each layer stores the information of different fields under the same location, which is similar to the view layers in map app, except that here it is in 3D space. In order to render the volume the way we want it to, we need to build renderable objects from layers. We call those objects **Component**. The following diagram shows the relationship of **Container**, **Layer**, and **Component**:

![alt text](assets/features_concept.png)

Expand Down
53 changes: 18 additions & 35 deletions docs/nodes.md
Original file line number Diff line number Diff line change
Expand Up @@ -251,41 +251,6 @@ This type of node is responsible for cutting components to present cross-section

</div>

## Utils

### 📦 Join Component

<div class="grid cards" markdown>

- ![alt text](assets/nodes_join-component.png)

- Components' combination should not be done by "Join Geometry" node because Blender Cycles can't render volumes in the same position, so the node will slightly offset all components randomly to avoid this problem.

***

Node Parameter:

- **Component 0~4**, _the components_

</div>

### 🗂️ Separate Component

<div class="grid cards" markdown>

- ![alt text](assets/nodes_separate-component.png)

- Volumes, previews, and guides are included within a component. This node can split them by type.

***

Node Parameter:

- **Component**, _the upstream component_
- **Type**, _the sub-object type, 0 is volume, 1 is preview, 2 is guide_

</div>

## Colors

This type of node is responsible for setting the color properties of the shader
Expand Down Expand Up @@ -406,3 +371,21 @@ This type of node is responsible for setting the color properties of the shader
- **Contrast**, _the larger the contrast, the harder color ramp will be_

</div>

## Utils

### 📦 Join Component

<div class="grid cards" markdown>

- ![alt text](assets/nodes_join-component.png)

- Components' combination should not be done by "Join Geometry" node because Blender Cycles can't render volumes in the same position, so the node will slightly offset all components randomly to avoid this problem.

***

Node Parameter:

- **Component 0~4**, _the components_

</div>

0 comments on commit e0c46e9

Please sign in to comment.