// linear interpolation
LLQuaternion lerp(F32 t, const LLQuaternion &p, const LLQuaternion &q)
{
	LLQuaternion r;
	r = t * (q - p) + p;
	r.normalize();
	return r;
}
示例#2
0
void LLViewerCamera::updateCameraLocation(const LLVector3 &center,
											const LLVector3 &up_direction,
											const LLVector3 &point_of_interest)
{
	// do not update if avatar didn't move
	if (!LLViewerJoystick::getInstance()->getCameraNeedsUpdate())
	{
		return;
	}

	LLVector3 last_position;
	LLVector3 last_axis;
	last_position = getOrigin();
	last_axis = getAtAxis();

	mLastPointOfInterest = point_of_interest;

	// constrain to max distance from avatar
	LLVector3 camera_offset = center - gAgent.getPositionAgent();

	LLViewerRegion * regp = gAgent.getRegion();
	F32 water_height = (NULL != regp) ? regp->getWaterHeight() : 0.f;

	LLVector3 origin = center;
	if (origin.mV[2] > water_height)
	{
		origin.mV[2] = llmax(origin.mV[2], water_height+0.20f);
	}
	else
	{
		origin.mV[2] = llmin(origin.mV[2], water_height-0.20f);
	}

	setOriginAndLookAt(origin, up_direction, point_of_interest);

	mVelocityDir = center - last_position ; 
	F32 dpos = mVelocityDir.normVec() ;
	LLQuaternion rotation;
	rotation.shortestArc(last_axis, getAtAxis());

	F32 x, y, z;
	F32 drot;
	rotation.getAngleAxis(&drot, &x, &y, &z);

	mVelocityStat.addValue(dpos);
	mAngularVelocityStat.addValue(drot);
	
	mAverageSpeed = mVelocityStat.getMeanPerSec() ;
	mAverageAngularSpeed = mAngularVelocityStat.getMeanPerSec() ;
	mCosHalfCameraFOV = cosf(0.5f * getView() * llmax(1.0f, getAspect()));

	// update pixel meter ratio using default fov, not modified one
	mPixelMeterRatio = getViewHeightInPixels()/ (2.f*tanf(mCameraFOVDefault*0.5));
	// update screen pixel area
	mScreenPixelArea =(S32)((F32)getViewHeightInPixels() * ((F32)getViewHeightInPixels() * getAspect()));
}
// lerp from identity to q
LLQuaternion lerp(F32 t, const LLQuaternion &q)
{
	LLQuaternion r;
	r.mQ[VX] = t * q.mQ[VX];
	r.mQ[VY] = t * q.mQ[VY];
	r.mQ[VZ] = t * q.mQ[VZ];
	r.mQ[VW] = t * (q.mQ[VZ] - 1.f) + 1.f;
	r.normalize();
	return r;
}
示例#4
0
void LLToolGrab::startGrab()
{
	// Compute grab_offset in the OBJECT's root's coordinate frame
	// (sometimes root == object)
	LLViewerObject* objectp = mGrabPick.getObject();
	if (!objectp)
	{
		return;
	}

	LLViewerObject *root = (LLViewerObject *)objectp->getRoot();

	// drag from center
	LLVector3d grab_start_global = root->getPositionGlobal();

	// Where the grab starts, relative to the center of the root object of the set.
	// JC - This code looks wonky, but I believe it does the right thing.
	// Otherwise, when you grab a linked object set, it "pops" on the start
	// of the drag.
	LLVector3d grab_offsetd = root->getPositionGlobal() - objectp->getPositionGlobal();

	LLVector3 grab_offset;
	grab_offset.setVec(grab_offsetd);

	LLQuaternion rotation = root->getRotation();
	rotation.conjQuat();
	grab_offset = grab_offset * rotation;

	// This planar drag starts at the grab point
	mDragStartPointGlobal = grab_start_global;
	mDragStartFromCamera = grab_start_global - gAgent.getCameraPositionGlobal();

	LLMessageSystem	*msg = gMessageSystem;
	msg->newMessageFast(_PREHASH_ObjectGrab);
	msg->nextBlockFast(_PREHASH_AgentData);
	msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
	msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
	msg->nextBlockFast(_PREHASH_ObjectData);
	msg->addU32Fast(_PREHASH_LocalID, objectp->mLocalID);
	msg->addVector3Fast(_PREHASH_GrabOffset, grab_offset );
	msg->nextBlock("SurfaceInfo");
	msg->addVector3("UVCoord", LLVector3(mGrabPick.mUVCoords));
	msg->addVector3("STCoord", LLVector3(mGrabPick.mSTCoords));
	msg->addS32Fast(_PREHASH_FaceIndex, mGrabPick.mObjectFace);
	msg->addVector3("Position", mGrabPick.mIntersection);
	msg->addVector3("Normal", mGrabPick.mNormal);
	msg->addVector3("Binormal", mGrabPick.mBinormal);
	msg->sendMessage( objectp->getRegion()->getHost());

	mGrabOffsetFromCenterInitial = grab_offset;
	mGrabHiddenOffsetFromCamera = mDragStartFromCamera;

	mGrabTimer.reset();
}
LLQuaternion lerp(F32 t, const LLQuaternion &p, const LLQuaternion &q)
{
	LLQuaternion r;
	F32 inv_t;

	inv_t = 1.f - t;

	r.mQ[VX] = t * q.mQ[VX] + (inv_t * p.mQ[VX]);
	r.mQ[VY] = t * q.mQ[VY] + (inv_t * p.mQ[VY]);
	r.mQ[VZ] = t * q.mQ[VZ] + (inv_t * p.mQ[VZ]);
	r.mQ[VW] = t * q.mQ[VW] + (inv_t * p.mQ[VW]);
	r.normalize();
	return r;
}
示例#6
0
void lggBeamMaps::fireCurrentBeams(LLPointer<LLHUDEffectSpiral> mBeam, const LLColor4U& rgb)
{
	if (mScale == 0.0f)
	{
		return;
	}

	static LLCachedControl<std::string> colorf(gSavedSettings, "FSBeamColorFile");
	bool colorsDisabled = (colorf().empty());
	
	for (std::vector<lggBeamData>::iterator it = mDots.begin(); it != mDots.end(); ++it)
	{
		LLColor4U myColor = rgb;
		if (colorsDisabled)
		{
			myColor = (*it).c;
		}

		F32 distanceAdjust = dist_vec(mBeam->getPositionGlobal(), gAgent.getPositionGlobal());
		F32 pulse = (F32)(.75f + sinf(gFrameTimeSeconds * 1.0f) * 0.25f);
		LLVector3d offset = (*it).p;
		offset.mdV[VY] *= -1.f;
		offset *= pulse * mScale * distanceAdjust * 0.1f;
		
		LLVector3 beamLine = LLVector3( mBeam->getPositionGlobal() - gAgent.getPositionGlobal());
		LLVector3 beamLineFlat = beamLine;
		beamLineFlat.mV[VZ]= 0.0f;

		LLVector3 newDirFlat = LLVector3::x_axis;
		beamLine.normalize();
		beamLineFlat.normalize();
		LLQuaternion change;
		change.shortestArc(newDirFlat, beamLineFlat);
		offset.rotVec(change);
		newDirFlat.rotVec(change);
		change.shortestArc(newDirFlat, beamLine);
		offset.rotVec(change);

		LLPointer<LLHUDEffectSpiral> myBeam = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM);
		myBeam->setPositionGlobal(mBeam->getPositionGlobal() + offset + (LLVector3d(beamLine) * sinf(gFrameTimeSeconds * 2.0f) * 0.2f));
		
		myBeam->setColor(myColor);
		myBeam->setTargetObject(mBeam->getTargetObject());
		myBeam->setSourceObject(mBeam->getSourceObject());
		myBeam->setNeedsSendToSim(mBeam->getNeedsSendToSim());
		myBeam->setDuration(mDuration * 1.2f);
	}
}
void ImportTracker::wear(LLSD &prim)
{
	LLMessageSystem* msg = gMessageSystem;
	msg->newMessageFast(_PREHASH_ObjectAttach);
	msg->nextBlockFast(_PREHASH_AgentData);
	msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
	msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
	msg->addU8Fast(_PREHASH_AttachmentPoint, U8(prim["Attachment"].asInteger()));
	
	msg->nextBlockFast(_PREHASH_ObjectData);
	msg->addU32Fast(_PREHASH_ObjectLocalID, prim["LocalID"].asInteger());
	msg->addQuatFast(_PREHASH_Rotation, LLQuaternion(0.0f, 0.0f, 0.0f, 1.0f));
	
	msg->sendReliable(gAgent.getRegion()->getHost());

	LLVector3 position = prim["attachpos"];
	
	LLSD rot = prim["attachrot"];
	LLQuaternion rotq;
	rotq.mQ[VX] = (F32)(rot[0].asReal());
	rotq.mQ[VY] = (F32)(rot[1].asReal());
	rotq.mQ[VZ] = (F32)(rot[2].asReal());
	rotq.mQ[VW] = (F32)(rot[3].asReal());
	LLVector3 rotation = rotq.packToVector3();
	U8 data[256];
	
	LLMessageSystem* msg2 = gMessageSystem;
	msg2->newMessageFast(_PREHASH_MultipleObjectUpdate);
	msg2->nextBlockFast(_PREHASH_AgentData);
	msg2->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
	msg2->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
	
	msg2->nextBlockFast(_PREHASH_ObjectData);
	msg2->addU32Fast(_PREHASH_ObjectLocalID, prim["LocalID"].asInteger());
	msg2->addU8Fast(_PREHASH_Type, U8(0x01 | 0x08));
	htonmemcpy(&data[0], &(position.mV), MVT_LLVector3, 12);
	msg2->addBinaryDataFast(_PREHASH_Data, data, 12);
	
	msg2->nextBlockFast(_PREHASH_ObjectData);
	msg2->addU32Fast(_PREHASH_ObjectLocalID, prim["LocalID"].asInteger());
	msg2->addU8Fast(_PREHASH_Type, U8(0x02 | 0x08));
	htonmemcpy(&data[0], &(rotation.mV), MVT_LLQuaternion, 12); 
	msg2->addBinaryDataFast(_PREHASH_Data, data, 12);
	
	msg2->sendReliable(gAgent.getRegion()->getHost());
	llinfos << "POSITIONED, IMPORT COMPLETED" << llendl;
	cleanUp();
}
示例#8
0
	void llquat_test_object_t::test<22>()
	{
		//test case for void LLQuaternion::getEulerAngles(F32 *roll, F32 *pitch, F32 *yaw) const fn
		F32 roll = -12.0f;
		F32 pitch = -22.43f;
		F32 yaw = 11.0f;

		LLQuaternion llquat;
		llquat.getEulerAngles(&roll, &pitch, &yaw);
		ensure(
			"LLQuaternion::getEulerAngles(F32 *roll, F32 *pitch, F32 *yaw) failed",
			is_approx_equal(0.000f, llquat.mQ[0]) &&
			is_approx_equal(0.000f, llquat.mQ[1]) &&
			is_approx_equal(0.000f, llquat.mQ[2]) &&
			is_approx_equal(1.000f, llquat.mQ[3]));
	}
示例#9
0
void LLTemplateMessageReader::getQuat(const char *block, const char *var, 
									  LLQuaternion &q, S32 blocknum)
{
	LLVector3 vec;
	getData(block, var, &vec.mV[0], sizeof(vec.mV), blocknum);
	if( vec.isFinite() )
	{
		q.unpackFromVector3( vec );
	}
	else
	{
		llwarns << "non-finite in getQuatFast " << block << " " << var 
				<< llendl;
		q.loadIdentity();
	}
}
示例#10
0
// SJB: This code is correct for a logicly stored (non-transposed) matrix;
//		Our matrices are stored transposed, OpenGL style, so this generates the
//		INVERSE quaternion (-x, -y, -z, w)!
//		Because we use similar logic in LLQuaternion::getMatrix3,
//		we are internally consistant so everything works OK :)
LLQuaternion	LLMatrix3::quaternion() const
{
	LLQuaternion	quat;
	F32		tr, s, q[4];
	U32		i, j, k;
	U32		nxt[3] = {1, 2, 0};

	tr = mMatrix[0][0] + mMatrix[1][1] + mMatrix[2][2];

	// check the diagonal
	if (tr > 0.f) 
	{
		s = (F32)sqrt (tr + 1.f);
		quat.mQ[VS] = s / 2.f;
		s = 0.5f / s;
		quat.mQ[VX] = (mMatrix[1][2] - mMatrix[2][1]) * s;
		quat.mQ[VY] = (mMatrix[2][0] - mMatrix[0][2]) * s;
		quat.mQ[VZ] = (mMatrix[0][1] - mMatrix[1][0]) * s;
	} 
	else
	{		
		// diagonal is negative
		i = 0;
		if (mMatrix[1][1] > mMatrix[0][0]) 
			i = 1;
		if (mMatrix[2][2] > mMatrix[i][i]) 
			i = 2;

		j = nxt[i];
		k = nxt[j];


		s = (F32)sqrt ((mMatrix[i][i] - (mMatrix[j][j] + mMatrix[k][k])) + 1.f);

		q[i] = s * 0.5f;

		if (s != 0.f) 
			s = 0.5f / s;

		q[3] = (mMatrix[j][k] - mMatrix[k][j]) * s;
		q[j] = (mMatrix[i][j] + mMatrix[j][i]) * s;
		q[k] = (mMatrix[i][k] + mMatrix[k][i]) * s;

		quat.setQuat(q);
	}
	return quat;
}
void LLToolGrab::startGrab()
{
	// Compute grab_offset in the OBJECT's root's coordinate frame
	// (sometimes root == object)
	LLViewerObject* objectp = mGrabPick.getObject();
	if (!objectp)
	{
		return;
	}

	LLViewerObject *root = (LLViewerObject *)objectp->getRoot();

	// drag from center
	LLVector3d grab_start_global = root->getPositionGlobal();

	// Where the grab starts, relative to the center of the root object of the set.
	// JC - This code looks wonky, but I believe it does the right thing.
	// Otherwise, when you grab a linked object set, it "pops" on the start
	// of the drag.
	LLVector3d grab_offsetd = root->getPositionGlobal() - objectp->getPositionGlobal();

	LLVector3 grab_offset;
	grab_offset.setVec(grab_offsetd);

	LLQuaternion rotation = root->getRotation();
	rotation.conjQuat();
	grab_offset = grab_offset * rotation;

	// This planar drag starts at the grab point
	mDragStartPointGlobal = grab_start_global;
	mDragStartFromCamera = grab_start_global - gAgentCamera.getCameraPositionGlobal();

	send_ObjectGrab_message(objectp, mGrabPick, grab_offset);

	mGrabOffsetFromCenterInitial = grab_offset;
	mGrabHiddenOffsetFromCamera = mDragStartFromCamera;

	mGrabTimer.reset();

	mLastUVCoords = mGrabPick.mUVCoords;
	mLastSTCoords = mGrabPick.mSTCoords;
	mLastFace = mGrabPick.mObjectFace;
	mLastIntersection = mGrabPick.mIntersection;
	mLastNormal = mGrabPick.mNormal;
	mLastBinormal = mGrabPick.mBinormal;
	mLastGrabPos = LLVector3(-1.f, -1.f, -1.f);
}
void lggBeamMaps::fireCurrentBeams(LLPointer<LLHUDEffectSpiral> mBeam, LLColor4U rgb)
{
	if (scale == 0.0f)
	{
		return;
	}

	static LLCachedControl<std::string> colorf(gSavedSettings, "FSBeamColorFile");
	bool colorsDisabled = std::string(colorf) == "===OFF===";
	
	for(int i = 0; i < (int)dots.size(); i++)
	{
		LLColor4U myColor = rgb;
		if (colorsDisabled) myColor = dots[i].c;

		F32 distanceAdjust = dist_vec(mBeam->getPositionGlobal(),gAgent.getPositionGlobal()) ;
		F32 pulse = (F32)(.75f+sinf(gFrameTimeSeconds*1.0f)*0.25f);
		LLVector3d offset = dots[i].p;
		offset.mdV[VY] *= -1;
		offset *= pulse * scale * distanceAdjust * 0.1;
		
		//llinfos << "dist is " << distanceAdjust << "scale is " << scale << llendl;
		LLVector3 beamLine = LLVector3( mBeam->getPositionGlobal() - gAgent.getPositionGlobal());
		LLVector3 beamLineFlat = beamLine;
		beamLineFlat.mV[VZ]= 0.0f;

		LLVector3 newDirFlat = LLVector3::x_axis;
		beamLine.normalize();
		beamLineFlat.normalize();
		LLQuaternion change;
		change.shortestArc(newDirFlat,beamLineFlat);
		offset.rotVec(change);
		newDirFlat.rotVec(change);
		change.shortestArc(newDirFlat,beamLine);
		offset.rotVec(change);

		LLPointer<LLHUDEffectSpiral> myBeam =  (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM);
		myBeam->setPositionGlobal(mBeam->getPositionGlobal() + offset + (LLVector3d(beamLine) * sinf(gFrameTimeSeconds*2.0f) * 0.2f));
		
		myBeam->setColor(myColor);
		myBeam->setTargetObject(mBeam->getTargetObject());
		myBeam->setSourceObject(mBeam->getSourceObject());
		myBeam->setNeedsSendToSim(mBeam->getNeedsSendToSim());
		myBeam->setDuration(duration* 1.2f);
	}
}
示例#13
0
void setup_transforms_bbox(LLBBox bbox)
{
	// translate to center
	LLVector3 center = bbox.getCenterAgent();
	gGL.translatef(center.mV[VX], center.mV[VY], center.mV[VZ]);

	// rotate
	LLQuaternion rotation = bbox.getRotation();
	F32 angle_radians, x, y, z;
	rotation.getAngleAxis(&angle_radians, &x, &y, &z);
	gGL.flush();
	gGL.rotatef(angle_radians * RAD_TO_DEG, x, y, z); 

	// scale
	LLVector3 scale = bbox.getMaxLocal() - bbox.getMinLocal();
	gGL.scalef(scale.mV[VX], scale.mV[VY], scale.mV[VZ]);
}
void ImportTracker::send_vectors(LLSD& prim,int counter)
{
	LLVector3 position = ((LLVector3)prim["position"] * rootrot) + root;
	LLSD rot = prim["rotation"];
	LLQuaternion rotq;
	rotq.mQ[VX] = (F32)(rot[0].asReal());
	rotq.mQ[VY] = (F32)(rot[1].asReal());
	rotq.mQ[VZ] = (F32)(rot[2].asReal());
	rotq.mQ[VW] = (F32)(rot[3].asReal());
	LLVector3 rotation;
	if(counter == 1)
		rotation = rotq.packToVector3();
	else
		rotation = (rotq * rootrot).packToVector3();
	LLVector3 scale = prim["scale"];
	U8 data[256];
	
	LLMessageSystem* msg = gMessageSystem;
	msg->newMessageFast(_PREHASH_MultipleObjectUpdate);
	msg->nextBlockFast(_PREHASH_AgentData);
	msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
	msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
	
	msg->nextBlockFast(_PREHASH_ObjectData);
	msg->addU32Fast(_PREHASH_ObjectLocalID, prim["LocalID"].asInteger());
	msg->addU8Fast(_PREHASH_Type, U8(0x01));
	htonmemcpy(&data[0], &(position.mV), MVT_LLVector3, 12);
	msg->addBinaryDataFast(_PREHASH_Data, data, 12);
	
	msg->nextBlockFast(_PREHASH_ObjectData);
	msg->addU32Fast(_PREHASH_ObjectLocalID, prim["LocalID"].asInteger());
	msg->addU8Fast(_PREHASH_Type, U8(0x02));
	htonmemcpy(&data[0], &(rotation.mV), MVT_LLQuaternion, 12); 
	msg->addBinaryDataFast(_PREHASH_Data, data, 12);
	
	msg->nextBlockFast(_PREHASH_ObjectData);
	msg->addU32Fast(_PREHASH_ObjectLocalID, prim["LocalID"].asInteger());
	msg->addU8Fast(_PREHASH_Type, U8(0x04));
	htonmemcpy(&data[0], &(scale.mV), MVT_LLVector3, 12); 
	msg->addBinaryDataFast(_PREHASH_Data, data, 12);
	
	msg->sendReliable(gAgent.getRegion()->getHost());
}
void setup_transforms_bbox(LLBBox bbox)
{
	// translate to center
	LLVector3 center = bbox.getCenterAgent();
	gGL.translatef(center.mV[VX], center.mV[VY], center.mV[VZ]);

	// rotate
	LLQuaternion rotation = bbox.getRotation();
	F32 angle_radians, x, y, z;
	rotation.getAngleAxis(&angle_radians, &x, &y, &z);
	// gGL has no rotate method (despite having translate and scale) presumably because
	// its authors smoke crack.  so we hack.
	gGL.flush();
	glRotatef(angle_radians * RAD_TO_DEG, x, y, z); 

	// scale
	LLVector3 scale = bbox.getMaxLocal() - bbox.getMinLocal();
	gGL.scalef(scale.mV[VX], scale.mV[VY], scale.mV[VZ]);
}
示例#16
0
void multiple_object_update(LLViewerObject* object, U8 type)
{
	gMessageSystem->newMessageFast(_PREHASH_MultipleObjectUpdate);

	gMessageSystem->nextBlockFast(_PREHASH_AgentData);
	gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
	gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());

	U8	data[256];

	gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
	gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID,	object->getLocalID() );
	gMessageSystem->addU8Fast(_PREHASH_Type, type );

	S32 offset = 0;

	// JC: You MUST pack the data in this order.  The receiving
	// routine process_multiple_update_message on simulator will
	// extract them in this order.

	if (type & UPD_POSITION)
	{
		htonmemcpy(&data[offset], &(object->getPosition().mV), MVT_LLVector3, 12); 
		offset += 12;
	}
	if (type & UPD_ROTATION)
	{
		LLQuaternion quat = object->getRotation();
		LLVector3 vec = quat.packToVector3();
		htonmemcpy(&data[offset], &(vec.mV), MVT_LLQuaternion, 12); 
		offset += 12;
	}
	if (type & UPD_SCALE)
	{
		//llinfos << "Sending object scale " << object->getScale() << llendl;
		htonmemcpy(&data[offset], &(object->getScale().mV), MVT_LLVector3, 12); 
		offset += 12;
	}
	gMessageSystem->addBinaryDataFast(_PREHASH_Data, data, offset);

	gAgent.sendReliableMessage();
}
示例#17
0
//--------------------------------------------------------------------
// setRotation()
//--------------------------------------------------------------------
void LLJoint::setRotation( const LLQuaternion& rot )
{
	if (rot.isFinite())
	{
	//	if (mXform.getRotation() != rot)
		{
			mXform.setRotation(rot);
			touch(MATRIX_DIRTY | ROTATION_DIRTY);
		}
	}
}
示例#18
0
void hud_render_text(const LLWString &wstr, const LLVector3 &pos_agent,
					const LLFontGL &font,
					const U8 style,
					const LLFontGL::ShadowType shadow,
					const F32 x_offset, const F32 y_offset,
					const LLColor4& color,
					const BOOL orthographic)
{
	LLViewerCamera* camera = LLViewerCamera::getInstance();
	// Do cheap plane culling
	LLVector3 dir_vec = pos_agent - camera->getOrigin();
	dir_vec /= dir_vec.magVec();

	if (wstr.empty() || (!orthographic && dir_vec * camera->getAtAxis() <= 0.f))
	{
		return;
	}

	LLVector3 right_axis;
	LLVector3 up_axis;
	if (orthographic)
	{
		right_axis.setVec(0.f, -1.f / gViewerWindow->getWorldViewHeightScaled(), 0.f);
		up_axis.setVec(0.f, 0.f, 1.f / gViewerWindow->getWorldViewHeightScaled());
	}
	else
	{
		camera->getPixelVectors(pos_agent, up_axis, right_axis);
	}
	LLCoordFrame render_frame = *camera;
	LLQuaternion rot;
	if (!orthographic)
	{
		rot = render_frame.getQuaternion();
		rot = rot * LLQuaternion(-F_PI_BY_TWO, camera->getYAxis());
		rot = rot * LLQuaternion(F_PI_BY_TWO, camera->getXAxis());
	}
	else
	{
		rot = LLQuaternion(-F_PI_BY_TWO, LLVector3(0.f, 0.f, 1.f));
		rot = rot * LLQuaternion(-F_PI_BY_TWO, LLVector3(0.f, 1.f, 0.f));
	}
	F32 angle;
	LLVector3 axis;
	rot.getAngleAxis(&angle, axis);

	LLVector3 render_pos = pos_agent + (floorf(x_offset) * right_axis) + (floorf(y_offset) * up_axis);

	//get the render_pos in screen space
	
	LLVector3 window_coordinates;
	F32& winX = window_coordinates.mV[VX];
	F32& winY = window_coordinates.mV[VY];
	F32& winZ = window_coordinates.mV[VZ];

	const LLRect& world_view_rect = gViewerWindow->getWorldViewRectRaw();
	
	glProjectf(render_pos, gGLModelView, gGLProjection, world_view_rect, window_coordinates);

	//fonts all render orthographically, set up projection``
	gGL.matrixMode(LLRender::MM_PROJECTION);
	gGL.pushMatrix();
	gGL.matrixMode(LLRender::MM_MODELVIEW);
	gGL.pushMatrix();
	LLUI::pushMatrix();
		
	gl_state_for_2d(world_view_rect.getWidth(), world_view_rect.getHeight());
	gViewerWindow->setup3DViewport();
	
	winX -= world_view_rect.mLeft;
	winY -= world_view_rect.mBottom;
	LLUI::loadIdentity();
	gGL.loadIdentity();
	LLUI::translate((F32) winX*1.0f/LLFontGL::sScaleX, (F32) winY*1.0f/(LLFontGL::sScaleY), -(((F32) winZ*2.f)-1.f));
	F32 right_x;
	
	font.render(wstr, 0, 0, 0, color, LLFontGL::LEFT, LLFontGL::BASELINE, style, shadow, wstr.length(), 1000, &right_x);
	LLUI::popMatrix();
	gGL.popMatrix();
	
	gGL.matrixMode(LLRender::MM_PROJECTION);
	gGL.popMatrix();
	gGL.matrixMode(LLRender::MM_MODELVIEW);
}
示例#19
0
void hud_render_text(const LLWString &wstr, const LLVector3 &pos_agent,
					const LLFontGL &font,
					const U8 style,
					const F32 x_offset, const F32 y_offset,
					const LLColor4& color,
					const BOOL orthographic)
{
	LLViewerCamera* camera = LLViewerCamera::getInstance();
	// Do cheap plane culling
	LLVector3 dir_vec = pos_agent - camera->getOrigin();
	dir_vec /= dir_vec.magVec();

	if (wstr.empty() || (!orthographic && dir_vec * camera->getAtAxis() <= 0.f))
	{
		return;
	}

	LLVector3 right_axis;
	LLVector3 up_axis;
	if (orthographic)
	{
		right_axis.setVec(0.f, -1.f / gViewerWindow->getWindowHeight(), 0.f);
		up_axis.setVec(0.f, 0.f, 1.f / gViewerWindow->getWindowHeight());
	}
	else
	{
		camera->getPixelVectors(pos_agent, up_axis, right_axis);
	}
	LLCoordFrame render_frame = *camera;
	LLQuaternion rot;
	if (!orthographic)
	{
		rot = render_frame.getQuaternion();
		rot = rot * LLQuaternion(-F_PI_BY_TWO, camera->getYAxis());
		rot = rot * LLQuaternion(F_PI_BY_TWO, camera->getXAxis());
	}
	else
	{
		rot = LLQuaternion(-F_PI_BY_TWO, LLVector3(0.f, 0.f, 1.f));
		rot = rot * LLQuaternion(-F_PI_BY_TWO, LLVector3(0.f, 1.f, 0.f));
	}
	F32 angle;
	LLVector3 axis;
	rot.getAngleAxis(&angle, axis);

	LLVector3 render_pos = pos_agent + (floorf(x_offset) * right_axis) + (floorf(y_offset) * up_axis);

	//get the render_pos in screen space
	
	F64 winX, winY, winZ;
	gluProject(render_pos.mV[0], render_pos.mV[1], render_pos.mV[2],
				gGLModelView, gGLProjection, (GLint*) gGLViewport,
				&winX, &winY, &winZ);
		
	//fonts all render orthographically, set up projection
	glMatrixMode(GL_PROJECTION);
	glPushMatrix();
	glMatrixMode(GL_MODELVIEW);
	
	LLUI::pushMatrix();
		
	gViewerWindow->setup2DRender();

	LLUI::loadIdentity();
	LLUI::translate((F32) winX*1.0f/LLFontGL::sScaleX, (F32) winY*1.0f/(LLFontGL::sScaleY), -(((F32) winZ*2.f)-1.f));
	//glRotatef(angle * RAD_TO_DEG, axis.mV[VX], axis.mV[VY], axis.mV[VZ]);
	//glScalef(right_scale, up_scale, 1.f);
	F32 right_x;
	
	font.render(wstr, 0, 0, 0, color, LLFontGL::LEFT, LLFontGL::BASELINE, style, wstr.length(), 1000, &right_x);
	LLUI::popMatrix();
	
	glMatrixMode(GL_PROJECTION);
	glPopMatrix();
	glMatrixMode(GL_MODELVIEW);
}
//-----------------------------------------------------------------------------
// LLEditingMotion::onUpdate()
//-----------------------------------------------------------------------------
BOOL LLEditingMotion::onUpdate(F32 time, U8* joint_mask)
{
	LLVector3 focus_pt;
	LLVector3* pointAtPt = (LLVector3*)mCharacter->getAnimationData("PointAtPoint");


	BOOL result = TRUE;

	if (!pointAtPt)
	{
		focus_pt = mLastSelectPt;
		result = FALSE;
	}
	else
	{
		focus_pt = *pointAtPt;
		mLastSelectPt = focus_pt;
	}

	focus_pt += mCharacter->getCharacterPosition();

	// propagate joint positions to kinematic chain
	mParentJoint.setPosition(	mParentState->getJoint()->getWorldPosition() );
	mShoulderJoint.setPosition(	mShoulderState->getJoint()->getPosition() );
	mElbowJoint.setPosition(	mElbowState->getJoint()->getPosition() );
	mWristJoint.setPosition(	mWristState->getJoint()->getPosition() + mWristOffset );

	// propagate current joint rotations to kinematic chain
	mParentJoint.setRotation(	mParentState->getJoint()->getWorldRotation() );
	mShoulderJoint.setRotation(	mShoulderState->getJoint()->getRotation() );
	mElbowJoint.setRotation(	mElbowState->getJoint()->getRotation() );

	// update target position from character
	LLVector3 target = focus_pt - mParentJoint.getPosition();
	F32 target_dist = target.normVec();
	
	LLVector3 edit_plane_normal(1.f / F_SQRT2, 1.f / F_SQRT2, 0.f);
	edit_plane_normal.normVec();

	edit_plane_normal.rotVec(mTorsoState->getJoint()->getWorldRotation());
	
	F32 dot = edit_plane_normal * target;

	if (dot < 0.f)
	{
		target = target + (edit_plane_normal * (dot * 2.f));
		target.mV[VZ] += clamp_rescale(dot, 0.f, -1.f, 0.f, 5.f);
		target.normVec();
	}

	target = target * target_dist;
	if (!target.isFinite())
	{
		LL_WARNS() << "Non finite target in editing motion with target distance of " << target_dist << 
			" and focus point " << focus_pt << " and pointAtPt: ";
		if (pointAtPt)
		{
		  LL_CONT << *pointAtPt;
		}
		else
		{
		  LL_CONT << "NULL";
		}
		LL_CONT << LL_ENDL;
		target.setVec(1.f, 1.f, 1.f);
	}
	
	mTarget.setPosition( target + mParentJoint.getPosition());

//	LL_INFOS() << "Point At: " << mTarget.getPosition() << LL_ENDL;

	// update the ikSolver
	if (!mTarget.getPosition().isExactlyZero())
	{
		LLQuaternion shoulderRot = mShoulderJoint.getRotation();
		LLQuaternion elbowRot = mElbowJoint.getRotation();
		mIKSolver.solve();

		// use blending...
		F32 slerp_amt = LLSmoothInterpolation::getInterpolant(TARGET_LAG_HALF_LIFE);
		shoulderRot = slerp(slerp_amt, mShoulderJoint.getRotation(), shoulderRot);
		elbowRot = slerp(slerp_amt, mElbowJoint.getRotation(), elbowRot);

		// now put blended values back into joints
		llassert(shoulderRot.isFinite());
		llassert(elbowRot.isFinite());
		mShoulderState->setRotation(shoulderRot);
		mElbowState->setRotation(elbowRot);
		mWristState->setRotation(LLQuaternion::DEFAULT);
	}

	mCharacter->setAnimationData("Hand Pose", &sHandPose);
	mCharacter->setAnimationData("Hand Pose Priority", &sHandPosePriority);
	return result;
}
示例#21
0
// writes contents to datapacker
BOOL LLBVHLoader::serialize(LLDataPacker& dp)
{
	JointVector::iterator ji;
	KeyVector::iterator ki;
	F32 time;

	// count number of non-ignored joints
	S32 numJoints = 0;
	for (ji=mJoints.begin(); ji!=mJoints.end(); ++ji)
	{
		Joint *joint = *ji;
		if ( ! joint->mIgnore )
			numJoints++;
	}

	// print header
	dp.packU16(KEYFRAME_MOTION_VERSION, "version");
	dp.packU16(KEYFRAME_MOTION_SUBVERSION, "sub_version");
	dp.packS32(mPriority, "base_priority");
	dp.packF32(mDuration, "duration");
	dp.packString(mEmoteName, "emote_name");
	dp.packF32(mLoopInPoint, "loop_in_point");
	dp.packF32(mLoopOutPoint, "loop_out_point");
	dp.packS32(mLoop, "loop");
	dp.packF32(mEaseIn, "ease_in_duration");
	dp.packF32(mEaseOut, "ease_out_duration");
	dp.packU32(mHand, "hand_pose");
	dp.packU32(numJoints, "num_joints");

	for (	ji = mJoints.begin();
			ji != mJoints.end();
			++ji )
	{
		Joint *joint = *ji;
		// if ignored, skip it
		if ( joint->mIgnore )
			continue;

		LLQuaternion first_frame_rot;
		LLQuaternion fixup_rot;

		dp.packString(joint->mOutName, "joint_name");
		dp.packS32(joint->mPriority, "joint_priority");

		// compute coordinate frame rotation
		LLQuaternion frameRot( joint->mFrameMatrix );
		LLQuaternion frameRotInv = ~frameRot;

		LLQuaternion offsetRot( joint->mOffsetMatrix );

		// find mergechild and mergeparent joints, if specified
		LLQuaternion mergeParentRot;
		LLQuaternion mergeChildRot;
		Joint *mergeParent = NULL;
		Joint *mergeChild = NULL;

		JointVector::iterator mji;
		for (mji=mJoints.begin(); mji!=mJoints.end(); ++mji)
		{
			Joint *mjoint = *mji;
			if ( !joint->mMergeParentName.empty() && (mjoint->mName == joint->mMergeParentName) )
			{
				mergeParent = *mji;
			}
			if ( !joint->mMergeChildName.empty() && (mjoint->mName == joint->mMergeChildName) )
			{
				mergeChild = *mji;
			}
		}

		dp.packS32(joint->mNumRotKeys, "num_rot_keys");

		LLQuaternion::Order order = bvhStringToOrder( joint->mOrder );
		S32 outcount = 0;
		S32 frame = 1;
		for (	ki = joint->mKeys.begin();
				ki != joint->mKeys.end();
				++ki )
		{
			if ((frame == 1) && joint->mRelativeRotationKey)
			{
				first_frame_rot = mayaQ( ki->mRot[0], ki->mRot[1], ki->mRot[2], order);
				
				fixup_rot.shortestArc(LLVector3::z_axis * first_frame_rot * frameRot, LLVector3::z_axis);
			}

			if (ki->mIgnoreRot)
			{
				frame++;
				continue;
			}

			time = (F32)frame * mFrameTime;

			if (mergeParent)
			{
				mergeParentRot = mayaQ(	mergeParent->mKeys[frame-1].mRot[0], 
										mergeParent->mKeys[frame-1].mRot[1],
										mergeParent->mKeys[frame-1].mRot[2],
										bvhStringToOrder(mergeParent->mOrder) );
				LLQuaternion parentFrameRot( mergeParent->mFrameMatrix );
				LLQuaternion parentOffsetRot( mergeParent->mOffsetMatrix );
				mergeParentRot = ~parentFrameRot * mergeParentRot * parentFrameRot * parentOffsetRot;
			}
			else
			{
				mergeParentRot.loadIdentity();
			}

			if (mergeChild)
			{
				mergeChildRot = mayaQ(	mergeChild->mKeys[frame-1].mRot[0], 
										mergeChild->mKeys[frame-1].mRot[1],
										mergeChild->mKeys[frame-1].mRot[2],
										bvhStringToOrder(mergeChild->mOrder) );
				LLQuaternion childFrameRot( mergeChild->mFrameMatrix );
				LLQuaternion childOffsetRot( mergeChild->mOffsetMatrix );
				mergeChildRot = ~childFrameRot * mergeChildRot * childFrameRot * childOffsetRot;
				
			}
			else
			{
				mergeChildRot.loadIdentity();
			}

			LLQuaternion inRot = mayaQ( ki->mRot[0], ki->mRot[1], ki->mRot[2], order);

			LLQuaternion outRot =  frameRotInv* mergeChildRot * inRot * mergeParentRot * ~first_frame_rot * frameRot * offsetRot;

			U16 time_short = F32_to_U16(time, 0.f, mDuration);
			dp.packU16(time_short, "time");
			U16 x, y, z;
			LLVector3 rot_vec = outRot.packToVector3();
			rot_vec.quantize16(-1.f, 1.f, -1.f, 1.f);
			x = F32_to_U16(rot_vec.mV[VX], -1.f, 1.f);
			y = F32_to_U16(rot_vec.mV[VY], -1.f, 1.f);
			z = F32_to_U16(rot_vec.mV[VZ], -1.f, 1.f);
			dp.packU16(x, "rot_angle_x");
			dp.packU16(y, "rot_angle_y");
			dp.packU16(z, "rot_angle_z");
			outcount++;
			frame++;
		}
		
		// output position keys (only for 1st joint)
		if ( ji == mJoints.begin() && !joint->mIgnorePositions )
		{
			dp.packS32(joint->mNumPosKeys, "num_pos_keys");

			LLVector3 relPos = joint->mRelativePosition;
			LLVector3 relKey;

			frame = 1;
			for (	ki = joint->mKeys.begin();
					ki != joint->mKeys.end();
					++ki )
			{
				if ((frame == 1) && joint->mRelativePositionKey)
				{
					relKey.setVec(ki->mPos);
				}

				if (ki->mIgnorePos)
				{
					frame++;
					continue;
				}

				time = (F32)frame * mFrameTime;

				LLVector3 inPos = (LLVector3(ki->mPos) - relKey) * ~first_frame_rot;// * fixup_rot;
				LLVector3 outPos = inPos * frameRot * offsetRot;

				outPos *= INCHES_TO_METERS;

				outPos -= relPos;
				outPos.clamp(-LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET);

				U16 time_short = F32_to_U16(time, 0.f, mDuration);
				dp.packU16(time_short, "time");

				U16 x, y, z;
				outPos.quantize16(-LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET, -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET);
				x = F32_to_U16(outPos.mV[VX], -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET);
				y = F32_to_U16(outPos.mV[VY], -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET);
				z = F32_to_U16(outPos.mV[VZ], -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET);
				dp.packU16(x, "pos_x");
				dp.packU16(y, "pos_y");
				dp.packU16(z, "pos_z");

				frame++;
			}
		}
		else
		{
			dp.packS32(0, "num_pos_keys");
		}
	}

	S32 num_constraints = (S32)mConstraints.size();
	dp.packS32(num_constraints, "num_constraints");

	for (ConstraintVector::iterator constraint_it = mConstraints.begin();
		constraint_it != mConstraints.end();
		constraint_it++)
		{
			U8 byte = constraint_it->mChainLength;
			dp.packU8(byte, "chain_lenght");
			
			byte = constraint_it->mConstraintType;
			dp.packU8(byte, "constraint_type");
			dp.packBinaryDataFixed((U8*)constraint_it->mSourceJointName, 16, "source_volume");
			dp.packVector3(constraint_it->mSourceOffset, "source_offset");
			dp.packBinaryDataFixed((U8*)constraint_it->mTargetJointName, 16, "target_volume");
			dp.packVector3(constraint_it->mTargetOffset, "target_offset");
			dp.packVector3(constraint_it->mTargetDir, "target_dir");
			dp.packF32(constraint_it->mEaseInStart,	"ease_in_start");
			dp.packF32(constraint_it->mEaseInStop,	"ease_in_stop");
			dp.packF32(constraint_it->mEaseOutStart,	"ease_out_start");
			dp.packF32(constraint_it->mEaseOutStop,	"ease_out_stop");
		}

	return TRUE;
}
示例#22
0
BOOL LLToolPlacer::addObject( LLPCode pcode, S32 x, S32 y, U8 use_physics )
{
    LLVector3 ray_start_region;
    LLVector3 ray_end_region;
    LLViewerRegion* regionp = NULL;
    BOOL b_hit_land = FALSE;
    S32 hit_face = -1;
    LLViewerObject* hit_obj = NULL;
    U8 state = 0;
    BOOL success = raycastForNewObjPos( x, y, &hit_obj, &hit_face, &b_hit_land, &ray_start_region, &ray_end_region, &regionp );
    if( !success )
    {
        return FALSE;
    }

    if( hit_obj && (hit_obj->isAvatar() || hit_obj->isAttachment()) )
    {
        // Can't create objects on avatars or attachments
        return FALSE;
    }

    if (NULL == regionp)
    {
        llwarns << "regionp was NULL; aborting function." << llendl;
        return FALSE;
    }

    if (regionp->getRegionFlags() & REGION_FLAGS_SANDBOX)
    {
        LLFirstUse::useSandbox();
    }

    // Set params for new object based on its PCode.
    LLQuaternion	rotation;
    LLVector3		scale = DEFAULT_OBJECT_SCALE;
    U8				material = LL_MCODE_WOOD;
    BOOL			create_selected = FALSE;
    LLVolumeParams	volume_params;

    switch (pcode)
    {
    case LL_PCODE_LEGACY_GRASS:
        //  Randomize size of grass patch
        scale.setVec(10.f + ll_frand(20.f), 10.f + ll_frand(20.f),  1.f + ll_frand(2.f));
        state = rand() % LLVOGrass::sMaxGrassSpecies;
        break;


    case LL_PCODE_LEGACY_TREE:
    case LL_PCODE_TREE_NEW:
        state = rand() % LLVOTree::sMaxTreeSpecies;
        break;

    case LL_PCODE_SPHERE:
    case LL_PCODE_CONE:
    case LL_PCODE_CUBE:
    case LL_PCODE_CYLINDER:
    case LL_PCODE_TORUS:
    case LLViewerObject::LL_VO_SQUARE_TORUS:
    case LLViewerObject::LL_VO_TRIANGLE_TORUS:
    default:
        create_selected = TRUE;
        break;
    }

    // Play creation sound
    if (gAudiop)
    {
        F32 volume = gSavedSettings.getBOOL("MuteUI") ? 0.f : gSavedSettings.getF32("AudioLevelUI");
        gAudiop->triggerSound( LLUUID(gSavedSettings.getString("UISndObjectCreate")), gAgent.getID(), volume);
    }

    gMessageSystem->newMessageFast(_PREHASH_ObjectAdd);
    gMessageSystem->nextBlockFast(_PREHASH_AgentData);
    gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
    gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
    gMessageSystem->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID());
    gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
    gMessageSystem->addU8Fast(_PREHASH_Material,	material);

    U32 flags = 0;		// not selected
    if (use_physics)
    {
        flags |= FLAGS_USE_PHYSICS;
    }
    if (create_selected)
    {
        flags |= FLAGS_CREATE_SELECTED;
    }
    gMessageSystem->addU32Fast(_PREHASH_AddFlags, flags );

    LLPCode volume_pcode;	// ...PCODE_VOLUME, or the original on error
    switch (pcode)
    {
    case LL_PCODE_SPHERE:
        rotation.setQuat(90.f * DEG_TO_RAD, LLVector3::y_axis);

        volume_params.setType( LL_PCODE_PROFILE_CIRCLE_HALF, LL_PCODE_PATH_CIRCLE );
        volume_params.setBeginAndEndS( 0.f, 1.f );
        volume_params.setBeginAndEndT( 0.f, 1.f );
        volume_params.setRatio	( 1, 1 );
        volume_params.setShear	( 0, 0 );
        LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
        volume_pcode = LL_PCODE_VOLUME;
        break;

    case LL_PCODE_TORUS:
        rotation.setQuat(90.f * DEG_TO_RAD, LLVector3::y_axis);

        volume_params.setType( LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_CIRCLE );
        volume_params.setBeginAndEndS( 0.f, 1.f );
        volume_params.setBeginAndEndT( 0.f, 1.f );
        volume_params.setRatio	( 1.f, 0.25f );	// "top size"
        volume_params.setShear	( 0, 0 );
        LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
        volume_pcode = LL_PCODE_VOLUME;
        break;

    case LLViewerObject::LL_VO_SQUARE_TORUS:
        rotation.setQuat(90.f * DEG_TO_RAD, LLVector3::y_axis);

        volume_params.setType( LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_CIRCLE );
        volume_params.setBeginAndEndS( 0.f, 1.f );
        volume_params.setBeginAndEndT( 0.f, 1.f );
        volume_params.setRatio	( 1.f, 0.25f );	// "top size"
        volume_params.setShear	( 0, 0 );
        LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
        volume_pcode = LL_PCODE_VOLUME;
        break;

    case LLViewerObject::LL_VO_TRIANGLE_TORUS:
        rotation.setQuat(90.f * DEG_TO_RAD, LLVector3::y_axis);

        volume_params.setType( LL_PCODE_PROFILE_EQUALTRI, LL_PCODE_PATH_CIRCLE );
        volume_params.setBeginAndEndS( 0.f, 1.f );
        volume_params.setBeginAndEndT( 0.f, 1.f );
        volume_params.setRatio	( 1.f, 0.25f );	// "top size"
        volume_params.setShear	( 0, 0 );
        LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
        volume_pcode = LL_PCODE_VOLUME;
        break;

    case LL_PCODE_SPHERE_HEMI:
        volume_params.setType( LL_PCODE_PROFILE_CIRCLE_HALF, LL_PCODE_PATH_CIRCLE );
        //volume_params.setBeginAndEndS( 0.5f, 1.f );
        volume_params.setBeginAndEndT( 0.f, 0.5f );
        volume_params.setRatio	( 1, 1 );
        volume_params.setShear	( 0, 0 );
        LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
        volume_pcode = LL_PCODE_VOLUME;
        break;

    case LL_PCODE_CUBE:
        volume_params.setType( LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE );
        volume_params.setBeginAndEndS( 0.f, 1.f );
        volume_params.setBeginAndEndT( 0.f, 1.f );
        volume_params.setRatio	( 1, 1 );
        volume_params.setShear	( 0, 0 );
        LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
        volume_pcode = LL_PCODE_VOLUME;
        break;

    case LL_PCODE_PRISM:
        volume_params.setType( LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE );
        volume_params.setBeginAndEndS( 0.f, 1.f );
        volume_params.setBeginAndEndT( 0.f, 1.f );
        volume_params.setRatio	( 0, 1 );
        volume_params.setShear	( -0.5f, 0 );
        LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
        volume_pcode = LL_PCODE_VOLUME;
        break;

    case LL_PCODE_PYRAMID:
        volume_params.setType( LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE );
        volume_params.setBeginAndEndS( 0.f, 1.f );
        volume_params.setBeginAndEndT( 0.f, 1.f );
        volume_params.setRatio	( 0, 0 );
        volume_params.setShear	( 0, 0 );
        LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
        volume_pcode = LL_PCODE_VOLUME;
        break;

    case LL_PCODE_TETRAHEDRON:
        volume_params.setType( LL_PCODE_PROFILE_EQUALTRI, LL_PCODE_PATH_LINE );
        volume_params.setBeginAndEndS( 0.f, 1.f );
        volume_params.setBeginAndEndT( 0.f, 1.f );
        volume_params.setRatio	( 0, 0 );
        volume_params.setShear	( 0, 0 );
        LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
        volume_pcode = LL_PCODE_VOLUME;
        break;

    case LL_PCODE_CYLINDER:
        volume_params.setType( LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_LINE );
        volume_params.setBeginAndEndS( 0.f, 1.f );
        volume_params.setBeginAndEndT( 0.f, 1.f );
        volume_params.setRatio	( 1, 1 );
        volume_params.setShear	( 0, 0 );
        LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
        volume_pcode = LL_PCODE_VOLUME;
        break;

    case LL_PCODE_CYLINDER_HEMI:
        volume_params.setType( LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_LINE );
        volume_params.setBeginAndEndS( 0.25f, 0.75f );
        volume_params.setBeginAndEndT( 0.f, 1.f );
        volume_params.setRatio	( 1, 1 );
        volume_params.setShear	( 0, 0 );
        LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
        volume_pcode = LL_PCODE_VOLUME;
        break;

    case LL_PCODE_CONE:
        volume_params.setType( LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_LINE );
        volume_params.setBeginAndEndS( 0.f, 1.f );
        volume_params.setBeginAndEndT( 0.f, 1.f );
        volume_params.setRatio	( 0, 0 );
        volume_params.setShear	( 0, 0 );
        LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
        volume_pcode = LL_PCODE_VOLUME;
        break;

    case LL_PCODE_CONE_HEMI:
        volume_params.setType( LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_LINE );
        volume_params.setBeginAndEndS( 0.25f, 0.75f );
        volume_params.setBeginAndEndT( 0.f, 1.f );
        volume_params.setRatio	( 0, 0 );
        volume_params.setShear	( 0, 0 );
        LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
        volume_pcode = LL_PCODE_VOLUME;
        break;

    default:
        LLVolumeMessage::packVolumeParams(0, gMessageSystem);
        volume_pcode = pcode;
        break;
    }
    gMessageSystem->addU8Fast(_PREHASH_PCode, volume_pcode);

    gMessageSystem->addVector3Fast(_PREHASH_Scale,			scale );
    gMessageSystem->addQuatFast(_PREHASH_Rotation,			rotation );
    gMessageSystem->addVector3Fast(_PREHASH_RayStart,		ray_start_region );
    gMessageSystem->addVector3Fast(_PREHASH_RayEnd,			ray_end_region );
    gMessageSystem->addU8Fast(_PREHASH_BypassRaycast,		(U8)b_hit_land );
    gMessageSystem->addU8Fast(_PREHASH_RayEndIsIntersection, (U8)FALSE );
    gMessageSystem->addU8Fast(_PREHASH_State, state);

    // Limit raycast to a single object.
    // Speeds up server raycast + avoid problems with server ray hitting objects
    // that were clipped by the near plane or culled on the viewer.
    LLUUID ray_target_id;
    if( hit_obj )
    {
        ray_target_id = hit_obj->getID();
    }
    else
    {
        ray_target_id.setNull();
    }
    gMessageSystem->addUUIDFast(_PREHASH_RayTargetID,			ray_target_id );

    // Pack in name value pairs
    gMessageSystem->sendReliable(regionp->getHost());

    // Spawns a message, so must be after above send
    if (create_selected)
    {
        gSelectMgr->deselectAll();
        gViewerWindow->getWindow()->incBusyCount();
    }

    // VEFFECT: AddObject
    LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)gHUDManager->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE);
    effectp->setSourceObject((LLViewerObject*)gAgent.getAvatarObject());
    effectp->setPositionGlobal(regionp->getPosGlobalFromRegion(ray_end_region));
    effectp->setDuration(LL_HUD_DUR_SHORT);
    effectp->setColor(LLColor4U(gAgent.getEffectColor()));

    gViewerStats->incStat(LLViewerStats::ST_CREATE_COUNT);

    return TRUE;
}
void LLSDMessageBuilder::copyFromMessageData(const LLMsgData& data)
{
	// copy the blocks
	// counting variables used to encode multiple block info
	S32 block_count = 0;
    char* block_name = NULL;

	// loop through msg blocks to loop through variables, totalling up size
	// data and filling the new (send) message
	LLMsgData::msg_blk_data_map_t::const_iterator iter = 
		data.mMemberBlocks.begin();
	LLMsgData::msg_blk_data_map_t::const_iterator end = 
		data.mMemberBlocks.end();
	for(; iter != end; ++iter)
	{
		const LLMsgBlkData* mbci = iter->second;
		if(!mbci) continue;

		// do we need to encode a block code?
		if (block_count == 0)
		{
			block_count = mbci->mBlockNumber;
			block_name = (char*)mbci->mName;
		}

		// counting down mutliple blocks
		block_count--;

		nextBlock(block_name);

		// now loop through the variables
		LLMsgBlkData::msg_var_data_map_t::const_iterator dit = mbci->mMemberVarData.begin();
		LLMsgBlkData::msg_var_data_map_t::const_iterator dend = mbci->mMemberVarData.end();
		
		for(; dit != dend; ++dit)
		{
			const LLMsgVarData& mvci = *dit;
			const char* varname = mvci.getName();

			switch(mvci.getType())
			{
			case MVT_FIXED:
				addBinaryData(varname, mvci.getData(), mvci.getSize());
				break;

			case MVT_VARIABLE:
				{
					const char end = ((const char*)mvci.getData())[mvci.getSize()-1]; // Ensure null terminated
					if (mvci.getDataSize() == 1 && end == 0) 
					{
						addString(varname, (const char*)mvci.getData());
					}
					else
					{
						addBinaryData(varname, mvci.getData(), mvci.getSize());
					}
					break;
				}

			case MVT_U8:
				addU8(varname, *(U8*)mvci.getData());
				break;

			case MVT_U16:
				addU16(varname, *(U16*)mvci.getData());
				break;

			case MVT_U32:
				addU32(varname, *(U32*)mvci.getData());
				break;

			case MVT_U64:
				addU64(varname, *(U64*)mvci.getData());
				break;

			case MVT_S8:
				addS8(varname, *(S8*)mvci.getData());
				break;

			case MVT_S16:
				addS16(varname, *(S16*)mvci.getData());
				break;

			case MVT_S32:
				addS32(varname, *(S32*)mvci.getData());
				break;

			// S64 not supported in LLSD so we just truncate it
			case MVT_S64:
				addS32(varname, *(S64*)mvci.getData());
				break;

			case MVT_F32:
				addF32(varname, *(F32*)mvci.getData());
				break;

			case MVT_F64:
				addF64(varname, *(F64*)mvci.getData());
				break;

			case MVT_LLVector3:
				addVector3(varname, *(LLVector3*)mvci.getData());
				break;

			case MVT_LLVector3d:
				addVector3d(varname, *(LLVector3d*)mvci.getData());
				break;

			case MVT_LLVector4:
				addVector4(varname, *(LLVector4*)mvci.getData());
				break;

			case MVT_LLQuaternion:
				{
					LLVector3 v = *(LLVector3*)mvci.getData();
					LLQuaternion q;
					q.unpackFromVector3(v);
					addQuat(varname, q);
					break;
				}

			case MVT_LLUUID:
				addUUID(varname, *(LLUUID*)mvci.getData());
				break;	

			case MVT_BOOL:
				addBOOL(varname, *(BOOL*)mvci.getData());
				break;

			case MVT_IP_ADDR:
				addIPAddr(varname, *(U32*)mvci.getData());
				break;

			case MVT_IP_PORT:
				addIPPort(varname, *(U16*)mvci.getData());
				break;

			case MVT_U16Vec3:
				//treated as an array of 6 bytes
				addBinaryData(varname, mvci.getData(), 6);
				break;

			case MVT_U16Quat:
				//treated as an array of 8 bytes
				addBinaryData(varname, mvci.getData(), 8);
				break;

			case MVT_S16Array:
				addBinaryData(varname, mvci.getData(), mvci.getSize());
				break;

			default:
				llwarns << "Unknown type in conversion of message to LLSD" << llendl;
				break;
			}
		}
	}
}
//-----------------------------------------------------------------------------
// solve()
//-----------------------------------------------------------------------------
void LLJointSolverRP3::solve()
{
//	llinfos << llendl;
//	llinfos << "LLJointSolverRP3::solve()" << llendl;

	//-------------------------------------------------------------------------
	// setup joints in their base rotations
	//-------------------------------------------------------------------------
	mJointA->setRotation( mJointABaseRotation );
	mJointB->setRotation( mJointBBaseRotation );

	//-------------------------------------------------------------------------
	// get joint positions in world space
	//-------------------------------------------------------------------------
	LLVector3 aPos = mJointA->getWorldPosition();
	LLVector3 bPos = mJointB->getWorldPosition();
	LLVector3 cPos = mJointC->getWorldPosition();
	LLVector3 gPos = mJointGoal->getWorldPosition();

//	llinfos << "bPosLocal = " << mJointB->getPosition() << llendl;
//	llinfos << "cPosLocal = " << mJointC->getPosition() << llendl;
//	llinfos << "bRotLocal = " << mJointB->getRotation() << llendl;
//	llinfos << "cRotLocal = " << mJointC->getRotation() << llendl;

//	llinfos << "aPos : " << aPos << llendl;
//	llinfos << "bPos : " << bPos << llendl;
//	llinfos << "cPos : " << cPos << llendl;
//	llinfos << "gPos : " << gPos << llendl;

	//-------------------------------------------------------------------------
	// get the poleVector in world space
	//-------------------------------------------------------------------------
	LLVector3 poleVec = mPoleVector;
	if ( mJointA->getParent() )
	{
		LLVector4a pole_veca;
		pole_veca.load3(mPoleVector.mV);
		mJointA->getParent()->getWorldMatrix().rotate(pole_veca,pole_veca);
		poleVec.set(pole_veca.getF32ptr());
	}

	//-------------------------------------------------------------------------
	// compute the following:
	// vector from A to B
	// vector from B to C
	// vector from A to C
	// vector from A to G (goal)
	//-------------------------------------------------------------------------
	LLVector3 abVec = bPos - aPos;
	LLVector3 bcVec = cPos - bPos;
	LLVector3 acVec = cPos - aPos;
	LLVector3 agVec = gPos - aPos;

//	llinfos << "abVec : " << abVec << llendl;
//	llinfos << "bcVec : " << bcVec << llendl;
//	llinfos << "acVec : " << acVec << llendl;
//	llinfos << "agVec : " << agVec << llendl;

	//-------------------------------------------------------------------------
	// compute needed lengths of those vectors
	//-------------------------------------------------------------------------
	F32 abLen = abVec.magVec();
	F32 bcLen = bcVec.magVec();
	F32 agLen = agVec.magVec();

//	llinfos << "abLen : " << abLen << llendl;
//	llinfos << "bcLen : " << bcLen << llendl;
//	llinfos << "agLen : " << agLen << llendl;

	//-------------------------------------------------------------------------
	// compute component vector of (A->B) orthogonal to (A->C)
	//-------------------------------------------------------------------------
	LLVector3 abacCompOrthoVec = abVec - acVec * ((abVec * acVec)/(acVec * acVec));

//	llinfos << "abacCompOrthoVec : " << abacCompOrthoVec << llendl;

	//-------------------------------------------------------------------------
	// compute the normal of the original ABC plane (and store for later)
	//-------------------------------------------------------------------------
	LLVector3 abcNorm;
	if (!mbUseBAxis)
	{
		if( are_parallel(abVec, bcVec, 0.001f) )
		{
			// the current solution is maxed out, so we use the axis that is
			// orthogonal to both poleVec and A->B
			if ( are_parallel(poleVec, abVec, 0.001f) )
			{
				// ACK! the problem is singular
				if ( are_parallel(poleVec, agVec, 0.001f) )
				{
					// the solutions is also singular
					return;
				}
				else
				{
					abcNorm = poleVec % agVec;
				}
			}
			else
			{
				abcNorm = poleVec % abVec;
			}
		}
		else
		{
			abcNorm = abVec % bcVec;
		}
	}
	else
	{
		abcNorm = mBAxis * mJointB->getWorldRotation();
	}

	//-------------------------------------------------------------------------
	// compute rotation of B
	//-------------------------------------------------------------------------
	// angle between A->B and B->C
	F32 abbcAng = angle_between(abVec, bcVec);

	// vector orthogonal to A->B and B->C
	LLVector3 abbcOrthoVec = abVec % bcVec;
	if (abbcOrthoVec.magVecSquared() < 0.001f)
	{
		abbcOrthoVec = poleVec % abVec;
		abacCompOrthoVec = poleVec;
	}
	abbcOrthoVec.normVec();

	F32 agLenSq = agLen * agLen;

	// angle arm for extension
	F32 cosTheta =	(agLenSq - abLen*abLen - bcLen*bcLen) / (2.0f * abLen * bcLen);
	if (cosTheta > 1.0f)
		cosTheta = 1.0f;
	else if (cosTheta < -1.0f)
		cosTheta = -1.0f;

	F32 theta = acos(cosTheta);

	LLQuaternion bRot(theta - abbcAng, abbcOrthoVec);

//	llinfos << "abbcAng      : " << abbcAng << llendl;
//	llinfos << "abbcOrthoVec : " << abbcOrthoVec << llendl;
//	llinfos << "agLenSq      : " << agLenSq << llendl;
//	llinfos << "cosTheta     : " << cosTheta << llendl;
//	llinfos << "theta        : " << theta << llendl;
//	llinfos << "bRot         : " << bRot << llendl;
//	llinfos << "theta abbcAng theta-abbcAng: " << theta*180.0/F_PI << " " << abbcAng*180.0f/F_PI << " " << (theta - abbcAng)*180.0f/F_PI << llendl;

	//-------------------------------------------------------------------------
	// compute rotation that rotates new A->C to A->G
	//-------------------------------------------------------------------------
	// rotate B->C by bRot
	bcVec = bcVec * bRot;

	// update A->C
	acVec = abVec + bcVec;

	LLQuaternion cgRot;
	cgRot.shortestArc( acVec, agVec );

//	llinfos << "bcVec : " << bcVec << llendl;
//	llinfos << "acVec : " << acVec << llendl;
//	llinfos << "cgRot : " << cgRot << llendl;

	// update A->B and B->C with rotation from C to G
	abVec = abVec * cgRot;
	bcVec = bcVec * cgRot;
	abcNorm = abcNorm * cgRot;
	acVec = abVec + bcVec;

	//-------------------------------------------------------------------------
	// compute the normal of the APG plane
	//-------------------------------------------------------------------------
	if (are_parallel(agVec, poleVec, 0.001f))
	{
		// the solution plane is undefined ==> we're done
		return;
	}
	LLVector3 apgNorm = poleVec % agVec;
	apgNorm.normVec();

	if (!mbUseBAxis)
	{
		//---------------------------------------------------------------------
		// compute the normal of the new ABC plane
		// (only necessary if we're NOT using mBAxis)
		//---------------------------------------------------------------------
		if( are_parallel(abVec, bcVec, 0.001f) )
		{
			// G is either too close or too far away
			// we'll use the old ABCnormal 
		}
		else
		{
			abcNorm = abVec % bcVec;
		}
		abcNorm.normVec();
	}

	//-------------------------------------------------------------------------
	// calcuate plane rotation
	//-------------------------------------------------------------------------
	LLQuaternion pRot;
	if ( are_parallel( abcNorm, apgNorm, 0.001f) )
	{
		if (abcNorm * apgNorm < 0.0f)
		{
			// we must be PI radians off ==> rotate by PI around agVec
			pRot.setQuat(F_PI, agVec);
		}
		else
		{
			// we're done
		}
	}
	else
	{
		pRot.shortestArc( abcNorm, apgNorm );
	}

//	llinfos << "abcNorm = " << abcNorm << llendl;
//	llinfos << "apgNorm = " << apgNorm << llendl;
//	llinfos << "pRot = " << pRot << llendl;

	//-------------------------------------------------------------------------
	// compute twist rotation
	//-------------------------------------------------------------------------
	LLQuaternion twistRot( mTwist, agVec );

//	llinfos	<< "twist    : " << mTwist*180.0/F_PI << llendl;
//	llinfos << "agNormVec: " << agNormVec << llendl;
//	llinfos << "twistRot : " << twistRot << llendl;

	//-------------------------------------------------------------------------
	// compute rotation of A
	//-------------------------------------------------------------------------
	LLQuaternion aRot = cgRot * pRot * twistRot;

	//-------------------------------------------------------------------------
	// apply the rotations
	//-------------------------------------------------------------------------
	mJointB->setWorldRotation( mJointB->getWorldRotation() * bRot );
	mJointA->setWorldRotation( mJointA->getWorldRotation() * aRot );
}
示例#25
0
BOOL LLToolPlacer::addObject( LLPCode pcode, S32 x, S32 y, U8 use_physics )
{
	LLVector3 ray_start_region;
	LLVector3 ray_end_region;
	LLViewerRegion* regionp = NULL;
	BOOL b_hit_land = FALSE;
	S32 hit_face = -1;
	LLViewerObject* hit_obj = NULL;
	U8 state = 0;
	BOOL success = raycastForNewObjPos( x, y, &hit_obj, &hit_face, &b_hit_land, &ray_start_region, &ray_end_region, &regionp );
	if( !success )
	{
		return FALSE;
	}

	if( hit_obj && (hit_obj->isAvatar() || hit_obj->isAttachment()) )
	{
		// Can't create objects on avatars or attachments
		return FALSE;
	}

	if (NULL == regionp)
	{
		llwarns << "regionp was NULL; aborting function." << llendl;
		return FALSE;
	}

	if (regionp->getRegionFlags() & REGION_FLAGS_SANDBOX)
	{
		LLFirstUse::useSandbox();
	}

	// Set params for new object based on its PCode.
	LLQuaternion	rotation;
	LLVector3		scale = LLVector3(
		gSavedSettings.getF32("EmeraldBuildPrefs_Xsize"),
		gSavedSettings.getF32("EmeraldBuildPrefs_Ysize"),
		gSavedSettings.getF32("EmeraldBuildPrefs_Zsize"));
	
	U8				material = LL_MCODE_WOOD;
	if(gSavedSettings.getString("EmeraldBuildPrefs_Material")== "Stone") material = LL_MCODE_STONE;
	if(gSavedSettings.getString("EmeraldBuildPrefs_Material")== "Metal") material = LL_MCODE_METAL;
	if(gSavedSettings.getString("EmeraldBuildPrefs_Material")== "Wood") material = LL_MCODE_WOOD;
	if(gSavedSettings.getString("EmeraldBuildPrefs_Material")== "Flesh") material = LL_MCODE_FLESH;
	if(gSavedSettings.getString("EmeraldBuildPrefs_Material")== "Rubber") material = LL_MCODE_RUBBER;
	if(gSavedSettings.getString("EmeraldBuildPrefs_Material")== "Plastic") material = LL_MCODE_PLASTIC;
		

	

	BOOL			create_selected = FALSE;
	LLVolumeParams	volume_params;
	
	switch (pcode) 
	{
	case LL_PCODE_LEGACY_GRASS:
		//  Randomize size of grass patch 
		scale.setVec(10.f + ll_frand(20.f), 10.f + ll_frand(20.f),  1.f + ll_frand(2.f));
		state = rand() % LLVOGrass::sMaxGrassSpecies;
		break;


	case LL_PCODE_LEGACY_TREE:
	case LL_PCODE_TREE_NEW:
		state = rand() % LLVOTree::sMaxTreeSpecies;
		break;

	case LL_PCODE_SPHERE:
	case LL_PCODE_CONE:
	case LL_PCODE_CUBE:
	case LL_PCODE_CYLINDER:
	case LL_PCODE_TORUS:
	case LLViewerObject::LL_VO_SQUARE_TORUS:
	case LLViewerObject::LL_VO_TRIANGLE_TORUS:
	default:
		create_selected = TRUE;
		break;
	}

	// Play creation sound
	if (gAudiop)
	{
		gAudiop->triggerSound( LLUUID(gSavedSettings.getString("UISndObjectCreate")),
							   gAgent.getID(), 1.0f, LLAudioEngine::AUDIO_TYPE_UI);
	}

	gMessageSystem->newMessageFast(_PREHASH_ObjectAdd);
	gMessageSystem->nextBlockFast(_PREHASH_AgentData);
	gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
	gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
	//MOYMOD 2009-05, If avatar is in land group/land owner group,
	//	it rezzes it with it to prevent autoreturn/whatever
	if(gSavedSettings.getBOOL("mm_alwaysRezWithLandGroup")){
		LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
		if(gAgent.isInGroup(parcel->getGroupID())){
			gMessageSystem->addUUIDFast(_PREHASH_GroupID, parcel->getGroupID());
		}else if(gAgent.isInGroup(parcel->getOwnerID())){
			gMessageSystem->addUUIDFast(_PREHASH_GroupID, parcel->getOwnerID());
		}else gMessageSystem->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID());
	}else gMessageSystem->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID());
	gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
	gMessageSystem->addU8Fast(_PREHASH_Material,	material);

	U32 flags = 0;		// not selected
	if (use_physics || gSavedSettings.getBOOL("EmeraldBuildPrefs_Physical"))
	{
		flags |= FLAGS_USE_PHYSICS;
	}
	//if (create_selected)
// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0b) | Added: RLVa-1.0.0b
	if ( (create_selected) && (!gRlvHandler.hasBehaviour(RLV_BHVR_EDIT)) )
// [/RLVa:KB]
	{
		flags |= FLAGS_CREATE_SELECTED;
	}
	gMessageSystem->addU32Fast(_PREHASH_AddFlags, flags );

	LLPCode volume_pcode;	// ...PCODE_VOLUME, or the original on error
	switch (pcode)
	{
	case LL_PCODE_SPHERE:
		rotation.setQuat(90.f * DEG_TO_RAD, LLVector3::y_axis);

		volume_params.setType( LL_PCODE_PROFILE_CIRCLE_HALF, LL_PCODE_PATH_CIRCLE );
		volume_params.setBeginAndEndS( 0.f, 1.f );
		volume_params.setBeginAndEndT( 0.f, 1.f );
		volume_params.setRatio	( 1, 1 );
		volume_params.setShear	( 0, 0 );
		LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
		volume_pcode = LL_PCODE_VOLUME;
		break;

	case LL_PCODE_TORUS:
		rotation.setQuat(90.f * DEG_TO_RAD, LLVector3::y_axis);

		volume_params.setType( LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_CIRCLE );
		volume_params.setBeginAndEndS( 0.f, 1.f );
		volume_params.setBeginAndEndT( 0.f, 1.f );
		volume_params.setRatio	( 1.f, 0.25f );	// "top size"
		volume_params.setShear	( 0, 0 );
		LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
		volume_pcode = LL_PCODE_VOLUME;
		break;

	case LLViewerObject::LL_VO_SQUARE_TORUS:
		rotation.setQuat(90.f * DEG_TO_RAD, LLVector3::y_axis);

		volume_params.setType( LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_CIRCLE );
		volume_params.setBeginAndEndS( 0.f, 1.f );
		volume_params.setBeginAndEndT( 0.f, 1.f );
		volume_params.setRatio	( 1.f, 0.25f );	// "top size"
		volume_params.setShear	( 0, 0 );
		LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
		volume_pcode = LL_PCODE_VOLUME;
		break;

	case LLViewerObject::LL_VO_TRIANGLE_TORUS:
		rotation.setQuat(90.f * DEG_TO_RAD, LLVector3::y_axis);

		volume_params.setType( LL_PCODE_PROFILE_EQUALTRI, LL_PCODE_PATH_CIRCLE );
		volume_params.setBeginAndEndS( 0.f, 1.f );
		volume_params.setBeginAndEndT( 0.f, 1.f );
		volume_params.setRatio	( 1.f, 0.25f );	// "top size"
		volume_params.setShear	( 0, 0 );
		LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
		volume_pcode = LL_PCODE_VOLUME;
		break;

	case LL_PCODE_SPHERE_HEMI:
		volume_params.setType( LL_PCODE_PROFILE_CIRCLE_HALF, LL_PCODE_PATH_CIRCLE );
		//volume_params.setBeginAndEndS( 0.5f, 1.f );
		volume_params.setBeginAndEndT( 0.f, 0.5f );
		volume_params.setRatio	( 1, 1 );
		volume_params.setShear	( 0, 0 );
		LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
		volume_pcode = LL_PCODE_VOLUME;
		break;

	case LL_PCODE_CUBE:
		volume_params.setType( LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE );
		volume_params.setBeginAndEndS( 0.f, 1.f );
		volume_params.setBeginAndEndT( 0.f, 1.f );
		volume_params.setRatio	( 1, 1 );
		volume_params.setShear	( 0, 0 );
		LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
		volume_pcode = LL_PCODE_VOLUME;
		break;

	case LL_PCODE_PRISM:
		volume_params.setType( LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE );
		volume_params.setBeginAndEndS( 0.f, 1.f );
		volume_params.setBeginAndEndT( 0.f, 1.f );
		volume_params.setRatio	( 0, 1 );
		volume_params.setShear	( -0.5f, 0 );
		LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
		volume_pcode = LL_PCODE_VOLUME;
		break;

	case LL_PCODE_PYRAMID:
		volume_params.setType( LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE );
		volume_params.setBeginAndEndS( 0.f, 1.f );
		volume_params.setBeginAndEndT( 0.f, 1.f );
		volume_params.setRatio	( 0, 0 );
		volume_params.setShear	( 0, 0 );
		LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
		volume_pcode = LL_PCODE_VOLUME;
		break;

	case LL_PCODE_TETRAHEDRON:
		volume_params.setType( LL_PCODE_PROFILE_EQUALTRI, LL_PCODE_PATH_LINE );
		volume_params.setBeginAndEndS( 0.f, 1.f );
		volume_params.setBeginAndEndT( 0.f, 1.f );
		volume_params.setRatio	( 0, 0 );
		volume_params.setShear	( 0, 0 );
		LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
		volume_pcode = LL_PCODE_VOLUME;
		break;

	case LL_PCODE_CYLINDER:
		volume_params.setType( LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_LINE );
		volume_params.setBeginAndEndS( 0.f, 1.f );
		volume_params.setBeginAndEndT( 0.f, 1.f );
		volume_params.setRatio	( 1, 1 );
		volume_params.setShear	( 0, 0 );
		LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
		volume_pcode = LL_PCODE_VOLUME;
		break;

	case LL_PCODE_CYLINDER_HEMI:
		volume_params.setType( LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_LINE );
		volume_params.setBeginAndEndS( 0.25f, 0.75f );
		volume_params.setBeginAndEndT( 0.f, 1.f );
		volume_params.setRatio	( 1, 1 );
		volume_params.setShear	( 0, 0 );
		LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
		volume_pcode = LL_PCODE_VOLUME;
		break;

	case LL_PCODE_CONE:
		volume_params.setType( LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_LINE );
		volume_params.setBeginAndEndS( 0.f, 1.f );
		volume_params.setBeginAndEndT( 0.f, 1.f );
		volume_params.setRatio	( 0, 0 );
		volume_params.setShear	( 0, 0 );
		LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
		volume_pcode = LL_PCODE_VOLUME;
		break;

	case LL_PCODE_CONE_HEMI:
		volume_params.setType( LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_LINE );
		volume_params.setBeginAndEndS( 0.25f, 0.75f );
		volume_params.setBeginAndEndT( 0.f, 1.f );
		volume_params.setRatio	( 0, 0 );
		volume_params.setShear	( 0, 0 );
		LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
		volume_pcode = LL_PCODE_VOLUME;
		break;

	default:
		LLVolumeMessage::packVolumeParams(0, gMessageSystem);
		volume_pcode = pcode;
		break;
	}
	gMessageSystem->addU8Fast(_PREHASH_PCode, volume_pcode);

	gMessageSystem->addVector3Fast(_PREHASH_Scale,			scale );
	gMessageSystem->addQuatFast(_PREHASH_Rotation,			rotation );
	gMessageSystem->addVector3Fast(_PREHASH_RayStart,		ray_start_region );
	gMessageSystem->addVector3Fast(_PREHASH_RayEnd,			ray_end_region );
	gMessageSystem->addU8Fast(_PREHASH_BypassRaycast,		(U8)b_hit_land );
	gMessageSystem->addU8Fast(_PREHASH_RayEndIsIntersection, (U8)FALSE );
	gMessageSystem->addU8Fast(_PREHASH_State, state);

	// Limit raycast to a single object.  
	// Speeds up server raycast + avoid problems with server ray hitting objects
	// that were clipped by the near plane or culled on the viewer.
	LLUUID ray_target_id;
	if( hit_obj )
	{
		ray_target_id = hit_obj->getID();
	}
	else
	{
		ray_target_id.setNull();
	}
	gMessageSystem->addUUIDFast(_PREHASH_RayTargetID,			ray_target_id );
	
	// Pack in name value pairs
	gMessageSystem->sendReliable(regionp->getHost());
	//lgg set flag to set texture here
	gImportTracker.expectRez();
	// Spawns a message, so must be after above send
	if (create_selected)
	{
		LLSelectMgr::getInstance()->deselectAll();
		gViewerWindow->getWindow()->incBusyCount();
	}

	// VEFFECT: AddObject
	LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE);
	effectp->setSourceObject((LLViewerObject*)gAgent.getAvatarObject());
	effectp->setPositionGlobal(regionp->getPosGlobalFromRegion(ray_end_region));
	effectp->setDuration(LL_HUD_DUR_SHORT);
	effectp->setColor(LLColor4U(gAgent.getEffectColor()));

	LLViewerStats::getInstance()->incStat(LLViewerStats::ST_CREATE_COUNT);

	return TRUE;
}
void LLTemplateMessageBuilder::addQuat(const char *varname, const LLQuaternion& quat)
{
	addData(varname, quat.packToVector3().mV, MVT_LLQuaternion, sizeof(LLVector3));
}
BOOL LLEasyMessageSender::addField(e_message_variable_type var_type, const char* var_name, std::string input, BOOL hex)
{
	LLStringUtil::trim(input);
	if(input.length() < 1 && var_type != MVT_VARIABLE)
		return FALSE;
	U8 valueU8;
	U16 valueU16;
	U32 valueU32;
	U64 valueU64;
	S8 valueS8;
	S16 valueS16;
	S32 valueS32;
	// S64 valueS64;
	F32 valueF32;
	F64 valueF64;
	LLVector3 valueVector3;
	LLVector3d valueVector3d;
	LLVector4 valueVector4;
	LLQuaternion valueQuaternion;
	LLUUID valueLLUUID;
	BOOL valueBOOL;
	std::string input_lower = input;
	LLStringUtil::toLower(input_lower);

	if(input_lower == "$agentid")
		input = gAgent.getID().asString();
	else if(input_lower == "$sessionid")
		input = gAgent.getSessionID().asString();
	else if(input_lower == "$uuid")
	{
		LLUUID id;
		id.generate();
		input = id.asString();
	}
	else if(input_lower == "$circuitcode")
	{
		std::stringstream temp_stream;
		temp_stream << gMessageSystem->mOurCircuitCode;
		input = temp_stream.str();
	}
	else if(input_lower == "$regionhandle")
	{
		std::stringstream temp_stream;
		temp_stream << (gAgent.getRegion() ? gAgent.getRegion()->getHandle() : 0);
		input = temp_stream.str();
	}
	else if(input_lower == "$position" || input_lower == "$pos")
	{
		std::stringstream temp_stream;
		valueVector3 = gAgent.getPositionAgent();
		temp_stream << "<" << valueVector3[0] << ", " << valueVector3[1] << ", " << valueVector3[2] << ">";
		input = temp_stream.str();
	}

	//convert from a text representation of hex to binary
	if(hex)
	{
		if(var_type != MVT_VARIABLE && var_type != MVT_FIXED)
			return FALSE;

		int len = input_lower.length();
		const char* cstr = input_lower.c_str();
		std::string new_input("");
		BOOL nibble = FALSE;
		char byte = 0;

		for(int i = 0; i < len; i++)
		{
			char c = cstr[i];
			if(c >= 0x30 && c <= 0x39)
				c -= 0x30;
			else if(c >= 0x61 && c <= 0x66)
				c -= 0x57;
			else if(c != 0x20)
				return FALSE;
			else
				continue;
			if(!nibble)
				byte = c << 4;
			else
				new_input.push_back(byte | c);
			nibble = !nibble;
		}

		if(nibble)
			return FALSE;

		input = new_input;
	}

	std::stringstream stream(input);
	std::vector<std::string> tokens;

	switch(var_type)
	{
	case MVT_U8:
		if(input.substr(0, 1) == "-")
			return FALSE;
		if((stream >> valueU32).fail())
			return FALSE;
		valueU8 = (U8)valueU32;
		gMessageSystem->addU8(var_name, valueU8);
		return TRUE;
		break;
	case MVT_U16:
		if(input.substr(0, 1) == "-")
			return FALSE;
		if((stream >> valueU16).fail())
			return FALSE;
		gMessageSystem->addU16(var_name, valueU16);
		return TRUE;
		break;
	case MVT_U32:
		if(input.substr(0, 1) == "-")
			return FALSE;
		if((stream >> valueU32).fail())
			return FALSE;
		gMessageSystem->addU32(var_name, valueU32);
		return TRUE;
		break;
	case MVT_U64:
		if(input.substr(0, 1) == "-")
			return FALSE;
		if((stream >> valueU64).fail())
			return FALSE;
		gMessageSystem->addU64(var_name, valueU64);
		return TRUE;
		break;
	case MVT_S8:
		if((stream >> valueS8).fail())
			return FALSE;
		gMessageSystem->addS8(var_name, valueS8);
		return TRUE;
		break;
	case MVT_S16:
		if((stream >> valueS16).fail())
			return FALSE;
		gMessageSystem->addS16(var_name, valueS16);
		return TRUE;
		break;
	case MVT_S32:
		if((stream >> valueS32).fail())
			return FALSE;
		gMessageSystem->addS32(var_name, valueS32);
		return TRUE;
		break;
	/*
	case MVT_S64:
		if((stream >> valueS64).fail())
			return FALSE;
		gMessageSystem->addS64(var_name, valueS64);
		return TRUE;
		break;
	*/
	case MVT_F32:
		if((stream >> valueF32).fail())
			return FALSE;
		gMessageSystem->addF32(var_name, valueF32);
		return TRUE;
		break;
	case MVT_F64:
		if((stream >> valueF64).fail())
			return FALSE;
		gMessageSystem->addF64(var_name, valueF64);
		return TRUE;
		break;
	case MVT_LLVector3:
		LLStringUtil::trim(input);
		if(input.substr(0, 1) != "<" || input.substr(input.length() - 1, 1) != ">")
			return FALSE;
		tokens = split(input.substr(1, input.length() - 2), ",");
		if(tokens.size() != 3)
			return FALSE;
		for(int i = 0; i < 3; i++)
		{
			stream.clear();
			stream.str(tokens[i]);
			if((stream >> valueF32).fail())
				return FALSE;
			valueVector3.mV[i] = valueF32;
		}
		gMessageSystem->addVector3(var_name, valueVector3);
		return TRUE;
		break;
	case MVT_LLVector3d:
		LLStringUtil::trim(input);
		if(input.substr(0, 1) != "<" || input.substr(input.length() - 1, 1) != ">")
			return FALSE;
		tokens = split(input.substr(1, input.length() - 2), ",");
		if(tokens.size() != 3)
			return FALSE;
		for(int i = 0; i < 3; i++)
		{
			stream.clear();
			stream.str(tokens[i]);
			if((stream >> valueF64).fail())
				return FALSE;
			valueVector3d.mdV[i] = valueF64;
		}
		gMessageSystem->addVector3d(var_name, valueVector3d);
		return TRUE;
		break;
	case MVT_LLVector4:
		LLStringUtil::trim(input);
		if(input.substr(0, 1) != "<" || input.substr(input.length() - 1, 1) != ">")
			return FALSE;
		tokens = split(input.substr(1, input.length() - 2), ",");
		if(tokens.size() != 4)
			return FALSE;
		for(int i = 0; i < 4; i++)
		{
			stream.clear();
			stream.str(tokens[i]);
			if((stream >> valueF32).fail())
				return FALSE;
			valueVector4.mV[i] = valueF32;
		}
		gMessageSystem->addVector4(var_name, valueVector4);
		return TRUE;
		break;
	case MVT_LLQuaternion:
		LLStringUtil::trim(input);
		if(input.substr(0, 1) != "<" || input.substr(input.length() - 1, 1) != ">")
			return FALSE;
		tokens = split(input.substr(1, input.length() - 2), ",");
		if(tokens.size() == 3)
		{
			for(int i = 0; i < 3; i++)
			{
				stream.clear();
				stream.str(tokens[i]);
				if((stream >> valueF32).fail())
					return FALSE;
				valueVector3.mV[i] = valueF32;
			}
			valueQuaternion.unpackFromVector3(valueVector3);
		}
		else if(tokens.size() == 4)
		{
			for(int i = 0; i < 4; i++)
			{
				stream.clear();
				stream.str(tokens[i]);
				if((stream >> valueF32).fail())
					return FALSE;
				valueQuaternion.mQ[i] = valueF32;
			}
		}
		else
			return FALSE;