(self, strand_features, hyperparams, normalization_dict)
| 294 | |
| 295 | |
| 296 | def forward(self, strand_features, hyperparams, normalization_dict): |
| 297 | nr_strands = strand_features.shape[0] |
| 298 | strand_features = strand_features.view(nr_strands, 1, -1).repeat(1, self.nr_verts_to_create, 1) # nr_strands x 100 x nr_channels |
| 299 | t = self.t.view(1, self.nr_verts_to_create, -1).repeat(nr_strands, 1, 1) #nrstrands, nr_verts, nr_channels |
| 300 | |
| 301 | |
| 302 | point_indices = None |
| 303 | if self.decode_random_verts: |
| 304 | # choose a random t for each strand |
| 305 | # we can create only up until the very last vertex, except the tip, we need to be able to sample the next vertex so as to get a direction vector |
| 306 | probability = torch.ones([nr_strands, self.num_pts - 2], dtype=torch.float32, device=torch.device("cuda")) |
| 307 | point_indices = torch.multinomial(probability, self.nr_verts_to_create, replacement=False) # size of the chunk size we selected |
| 308 | # add also the next vertex on the strand so that we can compute directions |
| 309 | point_indices = torch.cat([point_indices, point_indices + 1], 1) |
| 310 | |
| 311 | t = batched_index_select(t, 1, point_indices) |
| 312 | |
| 313 | # decode xyz |
| 314 | h_siren = t |
| 315 | z_scaling = self.z_scaling |
| 316 | z = strand_features |
| 317 | z_initial = z * z_scaling |
| 318 | z = z * z_scaling |
| 319 | |
| 320 | #cat also T |
| 321 | z=torch.cat([z,t],dim=2) |
| 322 | |
| 323 | |
| 324 | hair_dir=None |
| 325 | for i in range(self.nr_layers): |
| 326 | gain = self.gain_per_layer[i] |
| 327 | |
| 328 | h_modulation = self.activ( self.modulation_layers[i](z)) |
| 329 | |
| 330 | s = self.siren_layers[i](h_siren) |
| 331 | |
| 332 | #the input to the siren has to be unit gaussian, if we multiply by hmodulation, we are reducing the variance by Zscaling, so we boost the variance back up with this so that h_siren is unit gaussian again |
| 333 | h_siren = h_modulation * s * (1.0/(z_scaling*gain)) |
| 334 | |
| 335 | z = torch.cat([z_initial, h_modulation,t], 2) |
| 336 | |
| 337 | |
| 338 | |
| 339 | pred_dict={} |
| 340 | |
| 341 | if self.decode_type=="xyz": |
| 342 | points_pos = self.decode_val(h_siren) |
| 343 | if self.decode_random_verts: |
| 344 | pred_strands = points_pos |
| 345 | else: |
| 346 | # start_positions = torch.zeros(nr_strands, 1, 3).cuda() |
| 347 | start_positions = self.start_positions.repeat(nr_strands,1,1) |
| 348 | pred_strands = torch.cat([start_positions, points_pos], 1) |
| 349 | #positions are normalized to be in unit gaussian so we denormalize them to be in real space |
| 350 | pred_strands=un_normalize_data(pred_strands, normalization_dict["xyz_mean"], normalization_dict["xyz_std"]) |
| 351 | elif self.decode_type=="dir": |
| 352 | # divide by the nr of points on the strand otherwise the direction will have norm=1 and then when integrated you end up with a gigantic strand that has 100 units |
| 353 |
nothing calls this directly
no test coverage detected