Object Editing must be implemented using the following four actions:
The above actions and callbacks do not change the object data. It is up to the application to modify the object points using function XintView3DVectorSetValue. This allows the application to implement complex editing procedures; for example, procedures where more than just a single point is modified. Other convenience functions such as XintView3DVectorGetCount or XintView3DVectorGetValue can be used to obtain information about the points of a specified object.
After a point or a set of points have been edited, it is usually necessary to call functions XintView3DUpdateObject and XintView3DUpdateModel. Function XintView3DUpdateObject recalculates the object normals and updates the object bounding box. Function XintView3DUpdateModel recalculates the limits of the View3D model.
In this example, object editing is implemented using Button2. The user selects the portion of the surface to edit by pressing Button2. The surface is then modified as the mouse is moved while Button2 is pressed. Finally, the editing operation ends when the user releases Button2. Below is the translation table used to implement this behavior.
static char translations[] =
"<Btn2Down>: View3DPickObject() View3DEditVectorStart() \n\
<Btn2Up>: View3DEditVectorEnd() \n\
<Btn2Motion>: View3DEditVector() \n";
The application registers callback XmNpickCallback. This callback is used to initialize some global variables containing the ID of the object being picked and the index of the vertex being edited. It also initiates the editing operation.
static void PickCallback( Widget widget,
XtPointer not_used,
XintView3DCallbackStruct *cb)
{
/*
* Enable editing
*/
edit_object = cb->object;
index = cb->pick_data.index;
XintView3DEnableEditVector(widget, *(cb->pick_data.vertex),
cb->pick_data.normal, XintEDIT_VECTOR_LINE,
XintLIMIT_NONE,NULL,NULL);
}
The other callback registered by the application is XmNeditVectorCallback. This callback handles the actual object editing by calling function EditPoints.
static void EditCallback( Widget widget, XtPointer not_used,
XintView3DCallbackStruct *cb)
{
XintRealLimits x_limits, y_limits, z_limits;
XintReal distance_x, distance_y;
int radius;
switch (cb->reason) {
case XintCR_EDIT_VECTOR:
if (edit_object) {
XintView3DGetModelLimits(view3d, &x_limits, &y_limits,
&z_limits);
/* all the points within radius will be modified */
XtVaGetValues(scale_radius, XmNvalue, &radius, NULL);
distance_x = (float) radius * .01 * (x_limits.maximum -
x_limits.minimum);
distance_y = (float) radius * .01 * (y_limits.maximum -
y_limits.minimum);
EditPoints(edit_object, index, cb->edit_vector_data.point,
distance_x, distance_y);
}
break;
case XintCR_EDIT_VECTOR_START:
break;
case XintCR_EDIT_VECTOR_END:
XintView3DDisableEditVector(widget);
XintView3DUpdateObject(edit_object);
XintView3DUpdateModel(widget);
edit_object = NULL;
break;
}
}
The code for function EditPoints is shown below. This function modifies the point being edited, as well as all the points contained with the ellipse defined by distance_x and distance_y. The amount of change applied to each point modified is proportional to its distance from the original point being edited.
static void EditPoints(XintView3DObject *object,
int index,
XintVector3 new_value,
XintReal distance_x,
XintReal distance_y)
{
XintVector3 value, old_value;
XintReal dx, dy, dz;
XintReal distance, max_distance;
int count, i;
/*
* If single point edit, this is easy!
*/
if (distance_x == 0 || distance_y == 0) {
XintView3DVectorSetValue(edit_object, index, new_value);
} else {
XintView3DVectorGetValue(edit_object, index, old_value);
dx = new_value[0] - old_value[0];
dy = new_value[1] - old_value[1];
dz = new_value[2] - old_value[2];
max_distance = sqrt((double) (distance_x*distance_x +
distance_y*distance_y));
count = XintView3DVectorGetCount(edit_object);
for (i=0; i<count; i++) {
XintView3DVectorGetValue(edit_object, i, value);
distance = sqrt((double) (value[0] - old_value[0]) *
(value[0] - old_value[0]) + (value[1] -
old_value[1])*(value[1] - old_value[1]));
if (distance < max_distance) {
value[0] += dx * (1. - distance / max_distance);
value[1] += dy * (1. - distance / max_distance);
value[2] += dz * (1. - distance / max_distance);
XintView3DVectorSetValue(edit_object, i, value);
}
}
}
}
The output of example surface_edit.c is shown below.

Figure 26: Surface editing example.