Beispiel #1
0
//This method does all the work for the brush. Every time the mouse moves this will be called for each brush on the surface of the model.
Bool ExampleSculptGrabBrush::MovePointsFunc(BrushDabData* dab)
{
	PolygonObject* polyObj = dab->GetPolygonObject();
	if (!polyObj)
		return false;

	Int32 a;

	//Get the world matrix for the model so that we can turn local coordinates into world coordinates.
	Matrix mat = polyObj->GetMg();

	//Get the location of the hitpoint on the model in world coordinates
	Vector hitPointWorld = mat * dab->GetHitPoint();

	//Zero out the offset since its no longer required
	mat.off = Vector(0, 0, 0);

	const BaseContainer* pData = dab->GetData();

	//Get our custom direction value that we added to our .res file.
	Int32 dirMode = pData->GetInt32(MDATA_TOOLSCULPTGRABBRUSH_DIRMODE);

	//Find the distance the mouse has moved in world coordinates by getting the world position of the mouse and subtracting the current grab brush world coordinate
	Vector moveAmnt = (dab->GetMousePos3D() - hitPointWorld);

	//Transform this distance into a vector that is in the local coordinates of the model.
	moveAmnt = ~mat * moveAmnt;

	Vector normal = dab->GetNormal();

	switch (dirMode)
	{
		case MDATA_TOOLSCULPTGRABBRUSH_DIRMODE_NORMAL:
		{
			//If we are moving the point in the direction of its normal then use the length of the distance vector to scale the normal.
			moveAmnt = normal * moveAmnt.GetLength();

			//Adjust the direction of the vector depending on if its moving above the surface or below it.
			Float dot = Dot(normal, moveAmnt);
			if (dot < 0)
				moveAmnt *= -1;
			break;
		}
		case MDATA_TOOLSCULPTGRABBRUSH_DIRMODE_MOUSEDIR:
		default:
			//Nothing to do here since moveAmnt is already correct.
			break;
	}

	//Get the original points on the surface of the object. These points are the state of the object when the
	//user first clicks on the model to do a mouse stroke. This allows you to compare where the points are during
	//a stroke, since you have moved them, when the original positions.
	const Vector32* pOriginalPoints = dab->GetOriginalPoints();

	Int32									pointCount = dab->GetPointCount();
	const Vector*					pPoints = dab->GetPoints();
	const BrushPointData* pPointData = dab->GetPointData();

	//If any of the symmetry settings have been enabled, and this is a symmetry stroke instance, then this will return true.
	Bool mirror = dab->IsMirroredDab();

	//Loop over every point on the dab and move them by the moveAmnt.
	for (a = 0; a < pointCount; ++a)
	{
		Int32 pointIndex = pPointData[a].pointIndex;

		//Get the falloff value for this point. This value will take into account the current stencil, stamp settings and the falloff curve to create this value.
		Float fallOff = dab->GetBrushFalloff(a);

		//Get the original location for this point
		Vector original = (Vector64)pOriginalPoints[pointIndex];

		//Get the vector of the point we are going to change.
		const Vector& currentPoint = pPoints[pointIndex];

		//If the user has any of the symmetry settings enabled and this is one of the symmetrical brush instance then mirror will be True.
		//We can check to see if another brush instance has already touched this point and moved it by calling the IsPointModified method.
		//If a point has been touched then that means it has already been moved by a certain vector by that brush instance.
		//This happens when the brushes overlap the same area of the model, which can easily happen if you have a large brush size and are using symmetry.
		//So we just offset it by another vector and do not worry about the original location of the point.
		if (mirror && dab->IsPointModified(pointIndex))
		{
			//Adjust the offset by the new amount.
			dab->OffsetPoint(pointIndex, moveAmnt * fallOff);
		}
		else
		{
			//If there is no symmetry or the point hasn't been touched then we can just set the position of the point normally.
			//First determine the offset vector by using the original location of the point and adding on the new point after it has been adjusted by the falloff value.
			Vector newPosOffset = original + moveAmnt * fallOff;

			//A new offset is calculated by using this new point and its current position.
			Vector offset = newPosOffset - currentPoint;

			//Offset the point to place it in the correct location.
			dab->OffsetPoint(pointIndex, offset);
		}
	}

	//Ensure that all the points for the dab are marked as dirty. This is required to ensure that they all update even if they were not directly
	//touched by this brush instance. Marking all points as dirty ensures that the normals for all points are updated. This is only required
	//for grab brushes when multiple brush instances are touching the same points.
	dab->DirtyAllPoints(SCULPTBRUSHDATATYPE_POINT);
	return true;
}