Skip to content

Commit 6365934

Browse files
committed
Added uvs to PBD solver for rendering
1 parent a702209 commit 6365934

File tree

2 files changed

+64
-0
lines changed

2 files changed

+64
-0
lines changed

genesis/engine/entities/particle_entity.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ def _add_to_solver(self):
184184
self._add_particles_to_solver()
185185
if self._need_skinning:
186186
self._add_vverts_to_solver()
187+
self._add_uvs_and_faces_to_solver()
187188

188189
def _add_particles_to_solver(self):
189190
raise NotImplementedError
@@ -229,6 +230,45 @@ def _kernel_add_vverts_to_solver(
229230
for j in range(self.solver._n_vvert_supports):
230231
self.solver.vverts_info.support_idxs[i_vv][j] = support_idxs_local[i_vv_, j] + self._particle_start
231232

233+
def _add_uvs_and_faces_to_solver(self):
234+
"""Add UV coordinates and face indices to the solver's global buffers."""
235+
# Get UVs from vmesh (may be None if no texture)
236+
uvs = self._vmesh.uvs if self._vmesh is not None else None
237+
if uvs is not None and len(uvs) == self.n_vverts:
238+
uvs_np = np.asarray(uvs, dtype=gs.np_float)
239+
else:
240+
# No UVs available, use zeros
241+
uvs_np = np.zeros((self.n_vverts, 2), dtype=gs.np_float)
242+
243+
# Get face indices and offset them by vvert_start for global indexing
244+
faces_np = np.asarray(self._vfaces, dtype=gs.np_int)
245+
246+
self._kernel_add_uvs_and_faces_to_solver(
247+
uvs=uvs_np,
248+
faces=faces_np,
249+
)
250+
251+
@ti.kernel
252+
def _kernel_add_uvs_and_faces_to_solver(
253+
self,
254+
uvs: ti.types.ndarray(element_dim=1),
255+
faces: ti.types.ndarray(element_dim=1),
256+
):
257+
# Copy UVs to solver's global UV buffer
258+
for i_vv_ in range(self.n_vverts):
259+
i_vv = i_vv_ + self._vvert_start
260+
self.solver.vverts_uvs[i_vv] = uvs[i_vv_]
261+
262+
# Copy faces to solver's global face buffer (with global vertex indices)
263+
for i_vf_ in range(self.n_vfaces):
264+
i_vf = i_vf_ + self._vface_start
265+
# Offset face indices by vvert_start for global vertex indexing
266+
self.solver.vfaces_indices[i_vf] = ti.Vector([
267+
ti.cast(faces[i_vf_][0], gs.ti_int) + self._vvert_start,
268+
ti.cast(faces[i_vf_][1], gs.ti_int) + self._vvert_start,
269+
ti.cast(faces[i_vf_][2], gs.ti_int) + self._vvert_start,
270+
])
271+
232272
def sample(self):
233273
"""
234274
Sample particles from the morph based on its type and the specified sampler.

genesis/engine/solvers/pbd_solver.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,12 @@ def init_vvert_fields(self):
102102
shape=(max(self._n_vverts, 1), self._B), layout=ti.Layout.SOA
103103
)
104104

105+
# UV coordinates for visual vertices (static, same across all batch envs)
106+
self.vverts_uvs = ti.field(dtype=gs.ti_vec2, shape=(max(self._n_vverts, 1),))
107+
108+
# Triangle face indices for visual mesh (static)
109+
self.vfaces_indices = ti.field(dtype=gs.ti_ivec3, shape=(max(self._n_vfaces, 1),))
110+
105111
def init_particle_fields(self):
106112
# particles information (static)
107113
struct_particle_info = ti.types.struct(
@@ -829,6 +835,24 @@ def get_state(self, f):
829835
state = None
830836
return state
831837

838+
def get_state_render(self):
839+
"""
840+
Get visual vertex positions, UVs, and face indices for rendering.
841+
842+
Returns
843+
-------
844+
tuple
845+
(vverts_pos, vverts_uvs, vfaces_indices) - vertex positions, UV coords, and triangle indices
846+
"""
847+
if not self.is_active or self._n_vverts == 0:
848+
return None, None, None
849+
850+
# Make sure render fields are up to date
851+
self.update_render_fields()
852+
853+
# Return the Taichi fields directly for GPU access
854+
return self.vverts_render.pos, self.vverts_uvs, self.vfaces_indices
855+
832856
@ti.kernel
833857
def _kernel_get_state(
834858
self,

0 commit comments

Comments
 (0)