vpVolumeNormals(3)

πŸ’– vpVolumeNormals β€” the Library Functions Manual glow-up πŸ’–

okay bestie, gather round, because we're about to talk about vpVolumeNormals(3) from the VolPack library, and honestly? it's giving "quietly doing the most important work in the whole pipeline." ✨


🌸 NAME 🌸

vpVolumeNormals β€” compute surface normal vectors and gradient magnitudes for a volume. yeah. that's the whole job. she's an overachiever and she's not sorry. πŸ’…


✨ SYNOPSIS ✨

#include <volpack.h>

vpResult
vpVolumeNormals(vpc, scalar_data, length, scalar_field, grad_field,
        norm_field)
    vpContext *vpc;
    unsigned char *scalar_data;
    int length;
    int scalar_field;
    int grad_field;
    int norm_field;

like. look at her. six arguments, zero drama (okay maybe a little drama, wait for the ERRORS section). 🌈


πŸŽ€ ARGUMENTS πŸŽ€

  • vpc β€” the VolPack context you got from vpCreateContext. your girl's whole identity lives in here. πŸ’œ
  • scalar_data β€” a 3D array of scalar samples. the raw material, the moment, the lore. πŸ¦‹
  • length β€” the size of the scalar_data array, in bytes. she checks it, she does not trust it blindly, and honestly? good for her. πŸ‘‘
  • scalar_field β€” a voxel field number. it says "hey, put the scalar samples in this field." πŸ“¦
  • grad_field β€” another voxel field number, this time for the gradient magnitudes of the scalar samples. the spicy derivative info goes here. πŸ”₯
  • norm_field β€” voxel field number for the encoded surface normal vectors. the glow-up field. ✨

πŸ’« DESCRIPTION πŸ’«

so vpVolumeNormals is the precompute girlie. she exists to fill in voxel fields that classification and shading algorithms are obsessed with. her input is a 3D array of scalar values, and if you'd rather process scanlines of voxel data instead, there's a separate routine for that β€” go look at vpScanlineNormals(3), she's got you covered too. 🫢

for each voxel, this routine computes an approximation for the gradient of the scalar field, using a central-difference operator. from that vector she can compute:

  • the magnitude of the gradient β€” lowkey essential for some classification schemes, see vpSetClassifierTable(3) πŸ’…
  • a surface normal vector pointing in the direction of the gradient vector β€” the main character for implementing lighting models, see vpShadeTable(3) 🌟

then the scalar value, the gradient magnitude, and the surface normal vector all get stored into the fields of the voxel array. and yes, that voxel array is separate from the array of scalar values. two different arrays, two different vibes, no confusion. πŸ’€

the scalar array must be an array of 8-bit values β€” other sizes are not currently supported, periodt. the dimensions of that array must match the volume dimensions you previously specified with vpSetVolumeSize. the size argument is there to make sure the array actually has the correct size (she's checking, bestie, she always checks). and the voxel array must also be initialized by calling vpSetRawVoxels prior to calling vpVolumeNormals. no skipping steps. πŸ™ˆ

the three voxel field number arguments tell her which voxel fields the computed information should be stored into, and which field the scalar samples should be copied to. those field numbers must correspond to appropriately-sized voxel fields you previously specified with vpSetVoxelField. 🎯

any of these arguments can be the constant VP_SKIP_FIELD, in which case the corresponding quantity is not computed or copied. she'll just... not do that part. iconic behavior honestly.

size rules, listen up: the voxel fields for the scalar value and the gradient magnitude must be one-byte fields, and the field for the surface normal vector must be a two-byte field. the constants VP_SCALAR_MAX, VP_GRAD_MAX and VP_NORM_MAX give the maximum value that might be stored in each field, respectively. πŸ“

and the value stored in the surface normal vector field is actually an encoded surface normal β€” not a raw one, an encoded one. see vpNormalIndex(3) for the whole story. iykyk. 🧚


πŸ’€ ERRORS πŸ’€

the normal return value is VP_OK. when she's happy, she's happy. but here's where things can go sideways:

  • VPERROR_BAD_SIZE β€” the size of the scalar array does not match the volume dimensions. bestie. the math is not mathing. 😭
  • VPERROR_BAD_VALUE β€” one or more of the voxel fields specified is invalid, or the corresponding voxel field has the wrong size. wrong field, wrong size, wrong everything. πŸ’”
  • VPERROR_BAD_VOXEL β€” the voxel size or the voxel fields have not been specified, or have been incorrectly specified. you forgot a step, didn't you. πŸ™ˆ
  • VPERROR_BAD_VOLUME β€” the volume array or volume dimensions have not been specified, or the size of the volume array does not match the volume dimensions. the whole foundation is missing. no volume, no normals, no nothing. 🫠

πŸ‘‘ SEE ALSO πŸ‘‘

go read them, they're all part of the same friend group. 🌸


and that's the whole page, bestie. this lil manual lives in the VolPack source, filed under the Library Functions Manual, and goes by the name vpVolumeNormals(3). stay slay, stay 8-bit, and always initialize your voxels before you call her. πŸ’–βœ¨πŸŽ€πŸ¦‹

πŸ“¦ where this page comes from