ent_getvertex(ENTITY* ent, CONTACT* c, var num);
ent_setvertex(ENTITY* ent, CONTACT* c, var num);
Returns or sets a single vertex of a model or terrain mesh.
The functions can be used to deform a mesh in real time.
Parameters:
ent |
model or terrain entity pointer. |
num |
vertex number, beginning with 1. |
c |
Pointer to a pre-filled CONTACT* struct (defined in atypes.h) for setting or reading the vertex content. With ent_getvertex, NULL can be given for returning the pointer to an internal static CONTACT struct. |
The following members of the CONTACT struct are used (see also hit):
c.v |
D3DVERTEX* pointer of the current animated and interpolated mesh position, set by ent_getvertex and used by ent_setvertex for updating the mesh. Note that the vertex position is float instead of var and uses the DX coordinate system. The D3DVERTEX format is described in the shader section and defined in atypes.h. |
c.x,y,z |
VECTOR containing the vertex position in local entity coordinates, set by ent_getvertex. On non animated entities, the position is the same as in c.v; on vertex animated entities, it's the vertex position in the current non-interpolated frame; on bones animated entities, it's the vertex position of the base frame. Set c.v to NULL when ent_setvertex should update this vector rather than c.v. Updating c.v is faster, but won't work for animated entities. |
c.nx,ny,nz |
VECTOR containing the vertex normal, set by ent_getvertex. For changing the vertex normal, use c.v. |
c.vertex |
Local vertex number within the sub-mesh. Set by by ent_getvertex and used by ent_setvertex for multi-mesh entities. |
c.chunk |
Sub-mesh number in case of multi-mesh entities, such as map entities or chunked terrain. Set by ent_getvertex and used by ent_setvertex. |
c.model |
Sub-mesh pointer, set by by ent_getvertex.
If this pointer is nonzero, ent_getvertex uses the c.vertex value for the vertex number, instead of the num parameter. This speeds up the function on multi-mesh entities. Set this pointer to NULL when ent_getvertex was not called before ent_setvertex. |
Returns
CONTACT* struct pointer, or NULL if the function failed.
Speed:
Slow on first call, fast
on subsequent calls.
Remarks:
- Modifying a mesh of a certain entity affects all entities that use the same mesh. For preventing this, use ent_clone.
- Updating shared vertices of terrain chunks, mesh seams, or LOD meshes, as well as updating the visual bounding box automatically handled by ent_setvertex at the end of the frame cycle.
Therefore after modifying a mesh, functions like c_setminmax, vec_for_min and vec_for_max reflect the new mesh size one frame cycle later.
The physics hull, collision hull, and collision bounding box is unchanged; if required,
call c_updatehull or set min_x .. max_x manually afterwards.
- A8.23 Updating the positions of duplicated model vertices is automatically handled by ent_setmesh when only non-duplicated vertices are modified. When a duplicated vertex is modified, the duplicated positions are not updated.
- Updating the collision hull of a large terrain can take a long time. For temporarily preventing this, set the PASSABLE flag of the terrain, and reset it in the frame cycle when terrain deformation is finished.
- Vertex manipulation on chunked terrain only supports square chunks. For this reason, the x and y size of chunked terrain must be a multiple of the chunk size (terrain_chunk) - otherwise the terrain gets non-square 'cut-off chunks' at its borders. For the default chunk size of 32 mesh squares, examples of valid terrain sizes are 64x64, 160x160, 256x256 squares resp. 65x65, 161x161, or 257x257 vertices.
- The c.v pointer points into the mesh vertex buffer, which is an array of D3DVERTEX structs with a
total size given by ent_status(ent,1)*ent_status(ent,22)
. Calling ent_getvertex(ent,NULL,1) followed by ent_setvertex(ent,c,1) retrieves a pointer to the start of the vertex buffer, and allows to modify the whole vertex buffer without further ent_getvertex or ent_setvertex calls.
However this fast method only affects one mesh chunk of multi-mesh entities, and the row/column order of the vertices in the buffer correspond to the chunk size in that case, and not to the whole terrain size.
- For level geometry and chunked terrain, entity coordinates (c.x,y,z vector) are the same as world coordinates.
!! For entity meshes and nonchunked terrain, entity coordinates are local coordinates without position and scale. Local coordinates
can be converted to or from world coordinates with vec_for_ent / vec_to_ent, and normals can be converted with vec_rotate.
- In terrain meshes, vertices are sorted in a row-and-column order. In irregular meshes, vertices are sorted according to their numbers displayed in MED's status line, first the original vertices with unique xyz positions, and then the duplicated vertices with the same xyz positions but different uv values.
- These functions replace vec_for_mesh and vec_to_mesh, which didn't support multi-mesh objects.
Version
A7.62 LC
Examples (lite-C):
// raise all terrain vertices by 5 units
function raise_terrain(ENTITY* terrain)
{
int i = ent_status(terrain,0); // number of vertices
for (; i>0; i--) {
CONTACT* c = ent_getvertex(terrain,NULL,i);
c.v.y += 5.0; // raise the vertex (y is the height in DX coorcinates)
ent_setvertex(terrain,c,i);
}
}
// use a gun to produce mole-hills in terrain
function mole_gun()
{
while (1)
{
// calculate the target vector
VECTOR trace_target;
vec_set(trace_target,vector(5000,0,0)); // firing range 5000 quants
vec_rotate(trace_target, camera.pan);
vec_add(trace_target, camera.x);
// display a red spot at the target position
if (c_trace(camera.x,trace_target, IGNORE_PASSABLE | USE_POLYGON| SCAN_TEXTURE) > 0) // hit something?
draw_point3d(hit.x,vector(50,50,255),100,3);
if (key_ctrl && HIT_TARGET && you && ent_type(you) == 4) // fire onto terrain
{
// create a mole-hill by elevating the closest terrain vertex
var vertex_num = ent_nextvertex(you,hit.x);
CONTACT* contact = ent_getvertex(you,NULL,vertex_num);
c.z += 10; // increase the vertex height
c.v = NULL; // c.x,y,z was changed, instead of c.v
ent_setvertex(you,c,vertex_num); // update the mesh
wait(-0.5); // reload
}
wait(1);
}
}
See also:
ent_status, ent_nextvertex, ent_getmesh, ent_buffers, hit
► latest
version online