Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -146,4 +146,9 @@ wfc_binding.cpp
.gen_files/

.config/

# Mac
*.icloud

# Tests thom
test.gltf
27 changes: 22 additions & 5 deletions examples/procgen_grid.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,36 @@
)
* 0.6
)
scene += sm.ProcgenGrid(specific_map=specific_map)

proc_grid = sm.ProcgenGrid(specific_map=specific_map)

# Example using a predefined colormap from matplotlib
# See https://matplotlib.org/stable/api/cm_api.html#matplotlib.cm.get_cmap
proc_grid.add_texture_cmap_along_axis(axis="y", cmap="viridis", n_colors=5)
scene += proc_grid

scene += sm.LightSun()
scene.show()
scene.show(show_edges=True)

input("Press Enter for second scene")
# input("Press Enter for second scene")
scene.close()
scene.clear()

# Second scene: generating from this map
scene += sm.ProcgenGrid(width=3, height=3, sample_map=specific_map)

# Example creating our own colormap
# https://matplotlib.org/stable/tutorials/colors/colormap-manipulation.html
from matplotlib.colors import ListedColormap


cmap = ListedColormap(["red", "blue", "green"])
scene.tree_children[0].add_texture_cmap_along_axis(axis="x", cmap=cmap)

scene += sm.LightSun()
scene.show()

input("Press Enter for third scene")
# input("Press Enter for third scene")
scene.close()
scene.clear()

Expand All @@ -47,8 +63,9 @@
neighbors = [(tiles[1], tiles[0]), (tiles[0], tiles[0]), (tiles[1], tiles[1])]
scene += sm.ProcgenGrid(width=3, height=3, tiles=tiles, neighbors=neighbors, weights=weights, symmetries=symmetries)
scene += sm.LightSun()
scene.tree_children[0].add_texture_cmap_along_axis(axis="x", cmap="viridis")

scene.show()
input("Press Enter to close")
# input("Press Enter to close")

scene.close()
1 change: 1 addition & 0 deletions src/simenv/assets/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from .asset import Asset
from .camera import Camera, CameraDistant
from .collider import *
from .colors import *
from .light import *
from .material import *
from .object import *
Expand Down
88 changes: 88 additions & 0 deletions src/simenv/assets/colors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# Copyright 2022 The HuggingFace Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Lint as: python3
""" Some predefined RGB colors."""
import numpy as np


BLACK = (0.0, 0.0, 0.0)
BLUE = (0.0, 0.0, 1.0)
CYAN = (0.0, 1.0, 1.0)
GRAY25 = (0.25, 0.25, 0.25)
GRAY50 = (0.5, 0.5, 0.5)
GRAY75 = (0.75, 0.75, 0.75)
GRAY = GRAY50
GREEN = (0.0, 1.0, 0.0)
MAGENTA = (1.0, 0.0, 1.0)
OLIVE = (0.5, 0.5, 0.0)
PURPLE = (0.5, 0.0, 0.5)
RED = (1.0, 0.0, 0.0)
TEAL = (0.0, 0.5, 0.5)
WHITE = (1.0, 1.0, 1.0)
YELLOW = (1.0, 1.0, 0.0)

COLORS_ALL = {
"BLACK": BLACK,
"BLUE": BLUE,
"CYAN": CYAN,
"GRAY25": GRAY25,
"GRAY50": GRAY50,
"GRAY75": GRAY75,
"GRAY": GRAY,
"GREEN": GREEN,
"MAGENTA": MAGENTA,
"OLIVE": OLIVE,
"PURPLE": PURPLE,
"RED": RED,
"TEAL": TEAL,
"WHITE": WHITE,
"YELLOW": YELLOW,
}

COLORS_NO_GRAYSCALE = {
"BLUE": BLUE,
"CYAN": CYAN,
"GREEN": GREEN,
"MAGENTA": MAGENTA,
"OLIVE": OLIVE,
"PURPLE": PURPLE,
"RED": RED,
"TEAL": TEAL,
"YELLOW": YELLOW,
}

COLORS_ONLY_GRAYSCALE = {
"WHITE": WHITE,
"GRAY25": GRAY25,
"GRAY50": GRAY50,
"GRAY75": GRAY75,
"GRAY100": BLACK,
}

CMAP_ALL = np.array([list(COLORS_ALL.values())] * 2) # Final shape: (2, len(colors), 3) for (U, V, RGB)
CMAP_3_COLORS = np.array([[GREEN, GREEN]] * 2) # Final shape: (2, len(colors), 3) for (U, V, RGB)
CMAP_ONLY_COLORS = np.array(
[list(COLORS_NO_GRAYSCALE.values())] * 2
) # Final shape: (2, len(colors), 3) for (U, V, RGB)
CMAP_ONLY_GRAYSCALE = np.array(
[list(COLORS_ONLY_GRAYSCALE.values())] * 2
) # Final shape: (2, len(colors), 3) for (U, V, RGB)

TEXTURES_ALL = {
"cmap_all": CMAP_ALL,
"cmap_3_colors": CMAP_3_COLORS,
"cmap_only_colors": CMAP_ONLY_COLORS,
"cmap_only_grayscale": CMAP_ONLY_GRAYSCALE,
}
74 changes: 42 additions & 32 deletions src/simenv/assets/material.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,13 @@
import copy
import itertools
from dataclasses import dataclass
from typing import ClassVar, List, Optional
from typing import ClassVar, List, Optional, Union

import numpy as np
import pyvista

from .utils import camelcase_to_snakecase


class classproperty(object):
# required to use a classmethod as a property
# see https://stackoverflow.com/questions/128573/using-property-on-classmethods
def __init__(self, fget):
self.fget = fget

def __get__(self, owner_self, owner_cls):
return self.fget(owner_cls)
from . import colors
from .utils import camelcase_to_snakecase, classproperty


# TODO thom this is a very basic PBR Metrial class, mostly here to be able to load a gltf - strongly base on GLTF definitions
Expand Down Expand Up @@ -101,14 +92,14 @@ class Material:
__NEW_ID: ClassVar[int] = itertools.count() # Singleton to count instances of the classes for automatic naming

base_color: Optional[List[float]] = None
base_color_texture: Optional[pyvista.Texture] = None
base_color_texture: Optional[Union[np.ndarray, pyvista.Texture]] = None
metallic_factor: Optional[float] = None
roughness_factor: Optional[float] = None
metallic_roughness_texture: Optional[pyvista.Texture] = None
metallic_roughness_texture: Optional[Union[np.ndarray, pyvista.Texture]] = None

normal_texture: Optional[pyvista.Texture] = None
occlusion_texture: Optional[pyvista.Texture] = None
emissive_texture: Optional[pyvista.Texture] = None
normal_texture: Optional[Union[np.ndarray, pyvista.Texture]] = None
occlusion_texture: Optional[Union[np.ndarray, pyvista.Texture]] = None
emissive_texture: Optional[Union[np.ndarray, pyvista.Texture]] = None
emissive_factor: Optional[List[float]] = None
alpha_mode: Optional[str] = None
alpha_cutoff: Optional[float] = None
Expand All @@ -118,6 +109,21 @@ class Material:

def __post_init__(self):
# Setup all our default values

# Convert numpy array textures to
for tex in [
"base_color_texture",
"metallic_roughness_texture",
"normal_texture",
"occlusion_texture",
"emissive_texture",
]:
tex_value = getattr(self, tex, None)
if isinstance(tex_value, np.ndarray):
if tex_value.ndim != 3:
raise ValueError(f"{tex} must be a 3D numpy array (U, V, RGB)")
setattr(self, tex, pyvista.Texture(tex_value))

if self.base_color is None:
self.base_color = [1.0, 1.0, 1.0, 1.0]
elif isinstance(self.base_color, np.ndarray):
Expand Down Expand Up @@ -168,60 +174,64 @@ def copy(self):
# Various default colors
@classproperty
def RED(cls):
return cls(base_color=(1.0, 0.0, 0.0))
return cls(base_color=colors.RED)

@classproperty
def GREEN(cls):
return cls(base_color=(0.0, 1.0, 0.0))
return cls(base_color=colors.GREEN)

@classproperty
def BLUE(cls):
return cls(base_color=(0.0, 0.0, 1.0))
return cls(base_color=colors.BLUE)

@classproperty
def CYAN(cls):
return cls(base_color=(0.0, 1.0, 1.0))
return cls(base_color=colors.CYAN)

@classproperty
def MAGENTA(cls):
return cls(base_color=(1.0, 0.0, 1.0))
return cls(base_color=colors.MAGENTA)

@classproperty
def YELLOW(cls):
return cls(base_color=(1.0, 1.0, 0.0))
return cls(base_color=colors.YELLOW)

@classproperty
def BLACK(cls):
return cls(base_color=(0.0, 0.0, 0.0))
return cls(base_color=colors.BLACK)

@classproperty
def WHITE(cls):
return cls(base_color=(1.0, 1.0, 1.0))
return cls(base_color=colors.WHITE)

@classproperty
def GRAY(cls):
return cls.GRAY50
return cls(base_color=colors.GRAY)

@classproperty
def GRAY25(cls):
return cls(base_color=(0.25, 0.25, 0.25))
return cls(base_color=colors.GRAY25)

@classproperty
def GRAY50(cls):
return cls(base_color=(0.5, 0.5, 0.5))
return cls(base_color=colors.GRAY50)

@classproperty
def GRAY75(cls):
return cls(base_color=(0.75, 0.75, 0.75))
return cls(base_color=colors.GRAY75)

@classproperty
def TEAL(cls):
return cls(base_color=(0.0, 0.5, 0.5))
return cls(base_color=colors.TEAL)

@classproperty
def PURPLE(cls):
return cls(base_color=(0.5, 0.0, 0.5))
return cls(base_color=colors.PURPLE)

@classproperty
def OLIVE(cls):
return cls(base_color=(0.5, 0.5, 0.0))
return cls(base_color=colors.OLIVE)

@classproperty
def CMAP_3_COLORS(cls):
return cls(base_color_texture=colors.CMAP_3_COLORS)
Loading