Accessing Particle Information
Previous to version 3.0 of Softimage, .ptp files were used to transfer particle information to mental ray shaders. As of version 3.0, Softimage uses mental ray’s user data format to transfer particle cloud data from Softimage to a mental ray particle rendering shader. You may find this data useful for your own shaders as well.
The particle user data is split into two different userdata blocks: Particle Cloud data and Particle Sprite data.
• The Particle Cloud data holds information on the particle cloud such as number of particles, location/velocity/etc. of each particle. This document describes the exact data structures that comprise the user data.
• The Particle Sprite data holds information on particle sprite sequences. This document does not cover the formats used for this.
Particle Data Types Enumeration
Declaration
typedef enum {
E3D_PDT_ID, // miUlong
E3D_PDT_POSITION, // miVector
E3D_PDT_VELOCITY, // miVector
E3D_PDT_SIZE, // miScalar
E3D_PDT_ROTATION, // miVector
E3D_PDT_ROTATION_SPEED, // miVector
E3D_PDT_SPRITE_ANGLE, // miScalar
E3D_PDT_SPRITE_ANGLE_SPEED, // miScalar
E3D_PDT_COLOR, // miColor
E3D_PDT_UVW, // miVector
E3D_PDT_PATH_LENGTH, // miScalar
E3D_PDT_PRESSURE, // miScalar
E3D_PDT_DENSITY, // miScalar
E3D_PDT_AGE, // miUlong
E3D_PDT_AGE_LIMIT, // miUlong
E3D_PDT_SEED, // miUlong
E3D_PDT_SPRITE_ID, // miUlong
NB_PARTICLE_DATA_TYPES
} E3DParticleDataType;An enumeration of the data types that are associated with each particle. The type in the comment column after each data type enumeration is the actual data type used, in mental ray terms.
Particle Cloud User Data Header Block
Declaration
typedef struct {
miUlong m_one;
miUlong m_nbPartType;
miUlong m_offsetPartType; // In bytes
miUlong m_nbData; // In words
miUlong m_offsetData; // In bytes
miVector m_vBBoxMin;
miVector m_vBBoxMax;
miScalar m_dMotionScale;
miUlong m_nNotUsed[ 4 ];
;
} S3DParticleHeaderUD;S3DParticleHeaderUD defines the header information for the entire particle cloud userdata. It contains information on the number of particle types and the size and location of the particle data.
The head block starts at byte 0 of the user data.
• m_one should be of value 0x00000001. It is used both as a version number and a byteswapping marker. If m_one has the value of 0x01000000 then byteswapping of the entire particle data is required. For future versions this will morph into m_two, with a value of 0x00000002, et cetera. The semantics will remain the same.
• m_nbPartType is the number of particle types and, therefore, particle type blocks in the user data.
• m_offsetPartType is an offset, in bytes, from the start of the user data to the first particle type data block.
• m_nbData is the number of data entries for the particle individual data. Each data entry is 4 bytes long. Each data entry is either miUlong or miScalar (miVector is simply taken as three miScalars).
• m_offsetData is a an offset, in bytes, from the start of the user data to the first data entry.
• m_vBBoxMin is the point defining the minimum coordinate of an axis-aligned bounding box of the entire particle cloud.
• m_vBBoxMax is the point defining the maximum coordinate of an axis-aligned bounding box of the entire particle cloud.
• m_dMotionScale is a multiplier to scale the particle velocity values before use (E3D_PDT_VELOCITY, E3D_PDT_ROTATION_SPEED and E3D_PDT_SPRITE_ANGLE_SPEED ). This multiplier will change if motion blur in Softimage is set to evaluate motion SRT for the entire frame.
Example: Accessing the Particle Data Blocks
To access the particle type data blocks:
// in_pHeader is a pointer to the header block.
S3DParticleTypeUD *l_pParTypeUD = (S3DParticleTypeUD *)
((miUchar *)in_pHeader + in_pHeader->m_offsetPartType);
for(i = 0; i < in_pHeader->m_nbPartType; i++) {
mi_info( “Number of particles for type %d: %d\n”,
i, l_pParTypeUD[ i].m_nbParticles );
}
Declaration
typedef struct {
miUlong m_nbParticles;
miUlong m_shaderIndex;
miUlong m_dupeFlag;
miUlong m_offset[ NB_PARTICLE_DATA_TYPES ];
miUlong m_nNotUsed[ 4 ];
} S3DParticleTypeUD;• m_nbParticles specifies the number of particles for this type.
• m_shaderIndex is an index into a shader used by this type. DO NOT USE.
• m_dupeFlag is a bit field indicating which data types are identical for every particle associated with this type. If a type’s bit is set then only one data entry is defined for the entire particle range. To check which bits are set use the value one, shifed left by the type enumeration value. For example to check whether the sprite angle is the same across the entire range, use this expression:
m_dupeFlag & ( 1 << E3D_PDT_SPRITE_ANGLE )
• m_offset[] is an array of offsets, for each data type, into the start of their definitions in the user data. The offsets are defined in bytes relative to the start of the userdata. For example to retrieve the offset to the rotation speed data use: m_offset[E3D_PDT_ROTATION ].
Examples: Retrieving a Specific Value
To retrieve a specific value for a particle use this function. Cast the resulting pointer into the data type you’re interested (see E3DParticleDataType for more information):
void *getDataValue(
int in_nParticle, // Index of particle to get data for
int in_nParType, // Particle type the particle lives in
int in_nDataType, // Data type (from E3DParticleDataType)
int in_nDataSize, // Size of the data type
S3DParticleHeaderUD *in_pParHeaderUD;
) {
S3DParticleTypeUD *l_pParTypeUD;
miUchar *l_pData;
// Get the required pointers.
l_pParTypeUD = ( S3DParticleTypeUD *)
((miUchar *) in_pParHeaderUD + in_pParHeaderUD->m_offsetPartType );
l_pParTypeUD = &l_pParTypeUD[ in_nParType ];
// Get a pointer into the block of data for this data type on the
// given particle type.
l_pData = (miUchar *) in_pParHeaderUD +
l_pParTypeUD->m_offset[ in_nDataType ];
// If type is duplicated, always return the zeroth entry
if( l_pParTypeUD->m_dupeFlags & ( 1 << in_nDataType ) )
return( &l_pData[ 0 ] );
// Otherwise return the actual data pointer
return( &l_pData[in_nParticle * in_nDataSize ] );
}Retrieving the User Data Block
To retrieve the userdata block we need to get the instance item from the instance given in miState->instance.
The magic number of that user data is 0xF00D.
Example: Retrieving the User Data Block
This example assumes that the userdata lives on the item of the instance given with the current hit point.
S3DParticleHeaderUD * findUserData(
miState *in_pMI,
miTag in_tInstance )
{
miTag l_tUserData, l_tObject;
miUint l_label;
// Get the item tag and the item’s userdata block tag.
mi_query(miQ_INST_ITEM, in_pMI, in_tInstance, (void *)&l_tObject);
mi_query(miQ_OBJ_DATA, in_pMI, l_tObject, (void *)&l_tUserData);
for(;;) {
l_label = 0;
// Couldn’t retrieve a label. Exit.
if(!mi_query(miQ_DATA_LABEL, in_pMI, l_tUserData, &l_label))
break;
// Is it a particle cloud data?
if( l_label == 0xF00D ) {
S3DParticleHeaderUD *l_pData = NULL;
// Return the data pointer if found
if(mi_query(miQ_DATA_PARAM, NULL, l_tUserData,
(void*)&l_pData))
return( l_pData );
}
// Get the next data block
if(!mi_query(miQ_DATA_NEXT, in_pMI, l_tUserData, &l_tUserData))
break;
}
return( NULL );Autodesk Softimage v7.5