diff options
Diffstat (limited to 'indra')
| -rw-r--r-- | indra/llmessage/llpartdata.cpp | 293 | ||||
| -rw-r--r-- | indra/llmessage/llpartdata.h | 58 | ||||
| -rw-r--r-- | indra/llrender/llvertexbuffer.cpp | 9 | ||||
| -rw-r--r-- | indra/lscript/lscript_compile/indra.l | 14 | ||||
| -rw-r--r-- | indra/newview/lldrawpoolalpha.cpp | 38 | ||||
| -rw-r--r-- | indra/newview/llspatialpartition.cpp | 4 | ||||
| -rw-r--r-- | indra/newview/llspatialpartition.h | 2 | ||||
| -rw-r--r-- | indra/newview/llviewerobject.cpp | 21 | ||||
| -rw-r--r-- | indra/newview/llviewerobject.h | 8 | ||||
| -rw-r--r-- | indra/newview/llviewerpartsim.cpp | 27 | ||||
| -rw-r--r-- | indra/newview/llviewerpartsim.h | 9 | ||||
| -rw-r--r-- | indra/newview/llviewerpartsource.cpp | 75 | ||||
| -rw-r--r-- | indra/newview/llviewerpartsource.h | 4 | ||||
| -rw-r--r-- | indra/newview/llvograss.cpp | 7 | ||||
| -rw-r--r-- | indra/newview/llvograss.h | 1 | ||||
| -rw-r--r-- | indra/newview/llvopartgroup.cpp | 305 | ||||
| -rw-r--r-- | indra/newview/llvopartgroup.h | 6 | ||||
| -rw-r--r-- | indra/newview/llvovolume.cpp | 6 | 
18 files changed, 669 insertions, 218 deletions
| diff --git a/indra/llmessage/llpartdata.cpp b/indra/llmessage/llpartdata.cpp index 26cafa025f..0f33a94295 100644 --- a/indra/llmessage/llpartdata.cpp +++ b/indra/llmessage/llpartdata.cpp @@ -37,26 +37,33 @@ -const S32 PS_PART_DATA_BLOCK_SIZE = 4 + 2 + 4 + 4 + 2 + 2; // 18 -const S32 PS_DATA_BLOCK_SIZE = 68 + PS_PART_DATA_BLOCK_SIZE; // 68 + 18 = 86 +const S32 PS_PART_DATA_GLOW_SIZE = 2; +const S32 PS_PART_DATA_BLEND_SIZE = 2; +const S32 PS_LEGACY_PART_DATA_BLOCK_SIZE = 4 + 2 + 4 + 4 + 2 + 2; //18 +const S32 PS_SYS_DATA_BLOCK_SIZE = 68; +const S32 PS_MAX_DATA_BLOCK_SIZE = PS_SYS_DATA_BLOCK_SIZE+ +									PS_LEGACY_PART_DATA_BLOCK_SIZE + +									PS_PART_DATA_BLEND_SIZE + +									PS_PART_DATA_GLOW_SIZE+ +									8; //two S32 size fields + +const S32 PS_LEGACY_DATA_BLOCK_SIZE = PS_SYS_DATA_BLOCK_SIZE + PS_LEGACY_PART_DATA_BLOCK_SIZE; + + +const U32 PART_DATA_MASK = LLPartData::LL_PART_DATA_GLOW | LLPartData::LL_PART_DATA_BLEND; +  const F32 MAX_PART_SCALE = 4.f; -BOOL LLPartData::pack(LLDataPacker &dp) +bool LLPartData::hasGlow() const  { -	LLColor4U coloru; -	dp.packU32(mFlags, "pdflags"); -	dp.packFixed(mMaxAge, "pdmaxage", FALSE, 8, 8); -	coloru.setVec(mStartColor); -	dp.packColor4U(coloru, "pdstartcolor"); -	coloru.setVec(mEndColor); -	dp.packColor4U(coloru, "pdendcolor"); -	dp.packFixed(mStartScale.mV[0], "pdstartscalex", FALSE, 3, 5); -	dp.packFixed(mStartScale.mV[1], "pdstartscaley", FALSE, 3, 5); -	dp.packFixed(mEndScale.mV[0], "pdendscalex", FALSE, 3, 5); -	dp.packFixed(mEndScale.mV[1], "pdendscaley", FALSE, 3, 5); -	return TRUE; +	return mStartGlow > 0.f || mEndGlow > 0.f; +} + +bool LLPartData::hasBlendFunc() const +{ +	return mBlendFuncSource != LLPartData::LL_PART_BF_SOURCE_ALPHA || mBlendFuncDest != LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_ALPHA;  }  LLSD LLPartData::asLLSD() const @@ -68,6 +75,11 @@ LLSD LLPartData::asLLSD() const  	sd["pdendcolor"] = ll_sd_from_color4(mEndColor);  	sd["pdstartscale"] = ll_sd_from_vector2(mStartScale);  	sd["pdendscale"] = ll_sd_from_vector2(mEndScale); +	sd["pdstartglow"] =	mStartGlow; +	sd["pdendglow"] = mEndGlow; +	sd["pdblendsource"] = (S32)mBlendFuncSource; +	sd["pdblenddest"] = (S32)mBlendFuncDest; +  	return sd;  } @@ -79,11 +91,26 @@ bool LLPartData::fromLLSD(LLSD& sd)  	mEndColor = ll_color4_from_sd(sd["pdendcolor"]);  	mStartScale = ll_vector2_from_sd(sd["pdstartscale"]);  	mEndScale = ll_vector2_from_sd(sd["pdendscale"]); + +	mStartGlow = sd.has("pdstartglow") ? sd["pdstartglow"].asReal() : 0.f; +	mEndGlow = sd.has("pdendglow") ? sd["pdendglow"].asReal() : 0.f; +	mBlendFuncSource = sd.has("pdblendsource") ? (U8)sd["pdblendsource"].asInteger() : LL_PART_BF_SOURCE_ALPHA; +	mBlendFuncDest = sd.has("pdblenddest") ? (U8)sd["pdblenddest"].asInteger() : LL_PART_BF_ONE_MINUS_SOURCE_ALPHA; +  	return true;  } +S32 LLPartData::getSize() const +{ +	S32 size = PS_LEGACY_PART_DATA_BLOCK_SIZE; +	if (hasGlow()) size += PS_PART_DATA_GLOW_SIZE; +	if (hasBlendFunc()) size += PS_PART_DATA_BLEND_SIZE; -BOOL LLPartData::unpack(LLDataPacker &dp) +	return size; +} + + +BOOL LLPartData::unpackLegacy(LLDataPacker &dp)  {  	LLColor4U coloru; @@ -98,9 +125,81 @@ BOOL LLPartData::unpack(LLDataPacker &dp)  	dp.unpackFixed(mStartScale.mV[1], "pdstartscaley", FALSE, 3, 5);  	dp.unpackFixed(mEndScale.mV[0], "pdendscalex", FALSE, 3, 5);  	dp.unpackFixed(mEndScale.mV[1], "pdendscaley", FALSE, 3, 5); + +	/*if (dp.hasNext()) +	{ +		U8 tmp_glow = 0; +		dp.unpackU8(tmp_glow,"pdstartglow"); +		mStartGlow = tmp_glow / 255.f; +		dp.unpackU8(tmp_glow,"pdendglow"); +		mEndGlow = tmp_glow / 255.f; +		dp.unpackU8(mBlendFuncSource,"pdblendsource"); +		dp.unpackU8(mBlendFuncDest,"pdblenddest"); +	}*/ +	 +	mStartGlow = 0.f; +	mEndGlow = 0.f; +	mBlendFuncSource = LLPartData::LL_PART_BF_SOURCE_ALPHA; +	mBlendFuncDest = LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_ALPHA; +  	return TRUE;  } +BOOL LLPartData::unpack(LLDataPacker &dp) +{ +	S32 size = 0; +	dp.unpackS32(size, "partsize"); + +	unpackLegacy(dp); +	size -= PS_LEGACY_PART_DATA_BLOCK_SIZE; + +	if (mFlags & LL_PART_DATA_GLOW) +	{ +		if (size < PS_PART_DATA_GLOW_SIZE) return FALSE; + +		U8 tmp_glow = 0; +		dp.unpackU8(tmp_glow,"pdstartglow"); +		mStartGlow = tmp_glow / 255.f; +		dp.unpackU8(tmp_glow,"pdendglow"); +		mEndGlow = tmp_glow / 255.f; + +		size -= PS_PART_DATA_GLOW_SIZE; +	} +	else +	{ +		mStartGlow = 0.f; +		mEndGlow = 0.f; +	} + +	if (mFlags & LL_PART_DATA_BLEND) +	{ +		if (size < PS_PART_DATA_BLEND_SIZE) return FALSE; +		dp.unpackU8(mBlendFuncSource,"pdblendsource"); +		dp.unpackU8(mBlendFuncDest,"pdblenddest"); +		size -= PS_PART_DATA_BLEND_SIZE; +	} +	else +	{ +		mBlendFuncSource = LLPartData::LL_PART_BF_SOURCE_ALPHA; +		mBlendFuncDest = LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_ALPHA; +	} + +	if (size > 0) +	{ //leftover bytes, unrecognized parameters +		U8 feh = 0; +		while (size > 0) +		{ //read remaining bytes in block +			dp.unpackU8(feh, "whippang"); +			size--; +		} + +		//this particle system won't display properly, better to not show anything +		return FALSE; +	} + + +	return TRUE; +}  void LLPartData::setFlags(const U32 flags)  { @@ -148,6 +247,18 @@ void LLPartData::setEndAlpha(const F32 alpha)  	mEndColor.mV[3] = alpha;  } +// static +bool LLPartData::validBlendFunc(S32 func) +{ +	if (func >= 0 +		&& func < LL_PART_BF_COUNT +		&& func != UNSUPPORTED_DEST_ALPHA +		&& func != UNSUPPORTED_ONE_MINUS_DEST_ALPHA) +	{ +		return true; +	} +	return false; +}  LLPartSysData::LLPartSysData()  { @@ -160,6 +271,10 @@ LLPartSysData::LLPartSysData()  	mPartData.mStartScale = LLVector2(1.f, 1.f);  	mPartData.mEndScale = LLVector2(1.f, 1.f);  	mPartData.mMaxAge = 10.0; +	mPartData.mBlendFuncSource = LLPartData::LL_PART_BF_SOURCE_ALPHA; +	mPartData.mBlendFuncDest = LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_ALPHA; +	mPartData.mStartGlow = 0.f; +	mPartData.mEndGlow = 0.f;  	mMaxAge = 0.0;  	mStartAge = 0.0; @@ -175,38 +290,7 @@ LLPartSysData::LLPartSysData()  	mNumParticles = 0;  } - -BOOL LLPartSysData::pack(LLDataPacker &dp) -{ -	dp.packU32(mCRC, "pscrc"); -	dp.packU32(mFlags, "psflags"); -	dp.packU8(mPattern, "pspattern"); -	dp.packFixed(mMaxAge, "psmaxage", FALSE, 8, 8); -	dp.packFixed(mStartAge, "psstartage", FALSE, 8, 8); -	dp.packFixed(mInnerAngle, "psinnerangle", FALSE, 3, 5); -	dp.packFixed(mOuterAngle, "psouterangle", FALSE, 3, 5); -	dp.packFixed(mBurstRate, "psburstrate", FALSE, 8, 8); -	dp.packFixed(mBurstRadius, "psburstradius", FALSE, 8, 8); -	dp.packFixed(mBurstSpeedMin, "psburstspeedmin", FALSE, 8, 8); -	dp.packFixed(mBurstSpeedMax, "psburstspeedmax", FALSE, 8, 8); -	dp.packU8(mBurstPartCount, "psburstpartcount"); - -	dp.packFixed(mAngularVelocity.mV[0], "psangvelx", TRUE, 8, 7); -	dp.packFixed(mAngularVelocity.mV[1], "psangvely", TRUE, 8, 7); -	dp.packFixed(mAngularVelocity.mV[2], "psangvelz", TRUE, 8, 7); - -	dp.packFixed(mPartAccel.mV[0], "psaccelx", TRUE, 8, 7); -	dp.packFixed(mPartAccel.mV[1], "psaccely", TRUE, 8, 7); -	dp.packFixed(mPartAccel.mV[2], "psaccelz", TRUE, 8, 7); - -	dp.packUUID(mPartImageID, "psuuid"); -	dp.packUUID(mTargetUUID, "pstargetuuid"); -	mPartData.pack(dp); -	return TRUE; -} - - -BOOL LLPartSysData::unpack(LLDataPacker &dp) +BOOL LLPartSysData::unpackSystem(LLDataPacker &dp)  {  	dp.unpackU32(mCRC, "pscrc");  	dp.unpackU32(mFlags, "psflags"); @@ -232,10 +316,48 @@ BOOL LLPartSysData::unpack(LLDataPacker &dp)  	dp.unpackUUID(mPartImageID, "psuuid");  	dp.unpackUUID(mTargetUUID, "pstargetuuid"); -	mPartData.unpack(dp);  	return TRUE;  } +BOOL LLPartSysData::unpackLegacy(LLDataPacker &dp) +{ +	unpackSystem(dp); +	mPartData.unpackLegacy(dp); + +	return TRUE; +} + +BOOL LLPartSysData::unpack(LLDataPacker &dp) +{ +	// syssize is currently unused.  Adding now when modifying the 'version to make extensible in the future +	S32 size = 0; +	dp.unpackS32(size, "syssize"); +	 +	if (size != PS_SYS_DATA_BLOCK_SIZE) +	{ //unexpected size, this viewer doesn't know how to parse this particle system +		 +		//skip to LLPartData block +		U8 feh = 0; +		 +		for (U32 i = 0; i < size; ++i) +		{ +			dp.unpackU8(feh, "whippang"); +		} +				 +		dp.unpackS32(size, "partsize"); +		//skip LLPartData block +		for (U32 i = 0; i < size; ++i) +		{ +			dp.unpackU8(feh, "whippang"); +		} +		return FALSE; +	} + +	unpackSystem(dp); +	 +	return mPartData.unpack(dp); +} +  std::ostream& operator<<(std::ostream& s, const LLPartSysData &data)  {  	s << "Flags: " << std::hex << data.mFlags; @@ -253,7 +375,7 @@ std::ostream& operator<<(std::ostream& s, const LLPartSysData &data)  BOOL LLPartSysData::isNullPS(const S32 block_num)  { -	U8 ps_data_block[PS_DATA_BLOCK_SIZE]; +	U8 ps_data_block[PS_MAX_DATA_BLOCK_SIZE];  	U32 crc;  	S32 size; @@ -264,14 +386,28 @@ BOOL LLPartSysData::isNullPS(const S32 block_num)  	{  		return TRUE;  	} -	else if (size != PS_DATA_BLOCK_SIZE) +	 +	if (size > PS_MAX_DATA_BLOCK_SIZE)  	{ -		llwarns << "PSBlock is wrong size for particle system data - got " << size << ", expecting " << PS_DATA_BLOCK_SIZE << llendl; +		//size is too big, newer particle version unsupported  		return TRUE;  	} -	gMessageSystem->getBinaryData("ObjectData", "PSBlock", ps_data_block, PS_DATA_BLOCK_SIZE, block_num, PS_DATA_BLOCK_SIZE); -	LLDataPackerBinaryBuffer dp(ps_data_block, PS_DATA_BLOCK_SIZE); +	gMessageSystem->getBinaryData("ObjectData", "PSBlock", ps_data_block, size, block_num, PS_MAX_DATA_BLOCK_SIZE); + +	LLDataPackerBinaryBuffer dp(ps_data_block, size); +	if (size > PS_LEGACY_DATA_BLOCK_SIZE) +	{ +		// non legacy systems pack a size before the CRC +		S32 tmp = 0; +		dp.unpackS32(tmp, "syssize"); + +		if (tmp > PS_SYS_DATA_BLOCK_SIZE) +		{ //unknown system data block size, don't know how to parse it, treat as NULL +			return TRUE; +		} +	} +  	dp.unpackU32(crc, "crc");  	if (crc == 0) @@ -281,50 +417,37 @@ BOOL LLPartSysData::isNullPS(const S32 block_num)  	return FALSE;  } - -//static -BOOL LLPartSysData::packNull() -{ -	U8 ps_data_block[PS_DATA_BLOCK_SIZE]; -	gMessageSystem->addBinaryData("PSBlock", ps_data_block, 0); -	return TRUE; -} - - -BOOL LLPartSysData::packBlock() -{ -	U8 ps_data_block[PS_DATA_BLOCK_SIZE]; - -	LLDataPackerBinaryBuffer dp(ps_data_block, PS_DATA_BLOCK_SIZE); -	pack(dp); - -	// Add to message -	gMessageSystem->addBinaryData("PSBlock", ps_data_block, PS_DATA_BLOCK_SIZE); - -	return TRUE; -}                                          - -  BOOL LLPartSysData::unpackBlock(const S32 block_num)  { -	U8 ps_data_block[PS_DATA_BLOCK_SIZE]; +	U8 ps_data_block[PS_MAX_DATA_BLOCK_SIZE];  	// Check size of block  	S32 size = gMessageSystem->getSize("ObjectData", block_num, "PSBlock"); -	if (size != PS_DATA_BLOCK_SIZE) +	if (size > PS_MAX_DATA_BLOCK_SIZE)  	{ -		llwarns << "PSBlock is wrong size for particle system data - got " << size << ", expecting " << PS_DATA_BLOCK_SIZE << llendl; +		// Larger packets are newer and unsupported  		return FALSE;  	}  	// Get from message -	gMessageSystem->getBinaryData("ObjectData", "PSBlock", ps_data_block, PS_DATA_BLOCK_SIZE, block_num, PS_DATA_BLOCK_SIZE); +	gMessageSystem->getBinaryData("ObjectData", "PSBlock", ps_data_block, size, block_num, PS_MAX_DATA_BLOCK_SIZE); -	LLDataPackerBinaryBuffer dp(ps_data_block, PS_DATA_BLOCK_SIZE); -	unpack(dp); +	LLDataPackerBinaryBuffer dp(ps_data_block, size); -	return TRUE; +	if (size == PS_LEGACY_DATA_BLOCK_SIZE) +	{ +		return unpackLegacy(dp); +	} +	else +	{ +		return unpack(dp); +	} +} + +bool LLPartSysData::isLegacyCompatible() const +{ +	return !mPartData.hasGlow() && !mPartData.hasBlendFunc();  }  void LLPartSysData::clampSourceParticleRate() diff --git a/indra/llmessage/llpartdata.h b/indra/llmessage/llpartdata.h index a4ef058b30..80a52b79dd 100644 --- a/indra/llmessage/llpartdata.h +++ b/indra/llmessage/llpartdata.h @@ -70,7 +70,12 @@ enum LLPSScriptFlags  	LLPS_SRC_TARGET_UUID,  	LLPS_SRC_OMEGA,  	LLPS_SRC_ANGLE_BEGIN, -	LLPS_SRC_ANGLE_END +	LLPS_SRC_ANGLE_END, + +	LLPS_PART_BLEND_FUNC_SOURCE, +	LLPS_PART_BLEND_FUNC_DEST, +	LLPS_PART_START_GLOW, +	LLPS_PART_END_GLOW  }; @@ -83,12 +88,17 @@ public:  		mParameter(0.f)  	{  	} +	BOOL unpackLegacy(LLDataPacker &dp);  	BOOL unpack(LLDataPacker &dp); +  	BOOL pack(LLDataPacker &dp);  	LLSD asLLSD() const;  	operator LLSD() const {return asLLSD(); }  	bool fromLLSD(LLSD& sd); +	bool hasGlow() const; +	bool hasBlendFunc() const; +  	// Masks for the different particle flags  	enum  	{ @@ -102,17 +112,39 @@ public:  		LL_PART_TARGET_LINEAR_MASK =	0x80,		// Particle uses a direct linear interpolation  		LL_PART_EMISSIVE_MASK =			0x100,		// Particle is "emissive", instead of being lit  		LL_PART_BEAM_MASK =				0x200,		// Particle is a "beam" connecting source and target +		LL_PART_RIBBON_MASK =			0x400,		// Particles are joined together into one continuous triangle strip  		// Not implemented yet!  		//LL_PART_RANDOM_ACCEL_MASK =		0x100,		// Particles have random acceleration  		//LL_PART_RANDOM_VEL_MASK =		0x200,		// Particles have random velocity shifts"  		//LL_PART_TRAIL_MASK =			0x400,		// Particles have historical "trails" +		//sYSTEM SET FLAGS +		LL_PART_DATA_GLOW =				0x10000, +		LL_PART_DATA_BLEND =			0x20000, +  		// Viewer side use only!  		LL_PART_HUD =					0x40000000,  		LL_PART_DEAD_MASK =				0x80000000,  	}; +	enum +	{ +		LL_PART_BF_ONE = 0, +		LL_PART_BF_ZERO = 1, +		LL_PART_BF_DEST_COLOR = 2, +		LL_PART_BF_SOURCE_COLOR = 3, +		LL_PART_BF_ONE_MINUS_DEST_COLOR = 4, +		LL_PART_BF_ONE_MINUS_SOURCE_COLOR = 5, +		UNSUPPORTED_DEST_ALPHA = 6, +		LL_PART_BF_SOURCE_ALPHA = 7, +		UNSUPPORTED_ONE_MINUS_DEST_ALPHA = 8, +		LL_PART_BF_ONE_MINUS_SOURCE_ALPHA = 9, +		LL_PART_BF_COUNT = 10 +	}; + +	static bool validBlendFunc(S32 func); +  	void setFlags(const U32 flags);  	void setMaxAge(const F32 max_age);  	void setStartScale(const F32 xs, F32 ys); @@ -126,6 +158,9 @@ public:  	friend class LLPartSysData;  	friend class LLViewerPartSourceScript; +private: +	S32 getSize() const; +  	// These are public because I'm really lazy...  public:  	U32					mFlags;						// Particle state/interpolators in effect @@ -137,6 +172,12 @@ public:  	LLVector3			mPosOffset;					// Offset from source if using FOLLOW_SOURCE  	F32					mParameter;					// A single floating point parameter + +	F32					mStartGlow; +	F32					mEndGlow; +	 +	U8					mBlendFuncSource; +	U8					mBlendFuncDest;  }; @@ -146,15 +187,13 @@ public:  	LLPartSysData();  	BOOL unpack(LLDataPacker &dp); -	BOOL pack(LLDataPacker &dp); - -	 +	BOOL unpackLegacy(LLDataPacker &dp);  	BOOL unpackBlock(const S32 block_num); -	BOOL packBlock(); - -	static BOOL packNull(); +		  	static BOOL isNullPS(const S32 block_num); // Returns FALSE if this is a "NULL" particle system (i.e. no system) +	bool isLegacyCompatible() const; +  	// Different masks for effects on the source  	enum  	{ @@ -187,7 +226,12 @@ public:  	void clampSourceParticleRate();  	friend std::ostream&	 operator<<(std::ostream& s, const LLPartSysData &data);		// Stream a + +	S32 getdataBlockSize() const; +private: +	BOOL unpackSystem(LLDataPacker &dp); +  public:  	// Public because I'm lazy.... diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index c6f1d76653..f8ab085aac 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -2360,7 +2360,8 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask)  		if (data_mask & MAP_COLOR)  		{  			S32 loc = TYPE_COLOR; -			void* ptr = (void*)(base + mOffsets[TYPE_COLOR]); +			//bind emissive instead of color pointer if emissive is present +			void* ptr = (data_mask & MAP_EMISSIVE) ? (void*)(base + mOffsets[TYPE_EMISSIVE]) : (void*)(base + mOffsets[TYPE_COLOR]);  			glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_COLOR], ptr);  		}  		if (data_mask & MAP_EMISSIVE) @@ -2368,6 +2369,12 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask)  			S32 loc = TYPE_EMISSIVE;  			void* ptr = (void*)(base + mOffsets[TYPE_EMISSIVE]);  			glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_EMISSIVE], ptr); + +			if (!(data_mask & MAP_COLOR)) +			{ //map emissive to color channel when color is not also being bound to avoid unnecessary shader swaps +				loc = TYPE_COLOR; +				glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_EMISSIVE], ptr); +			}  		}  		if (data_mask & MAP_WEIGHT)  		{ diff --git a/indra/lscript/lscript_compile/indra.l b/indra/lscript/lscript_compile/indra.l index 307a5561a0..3f844d0fd1 100644 --- a/indra/lscript/lscript_compile/indra.l +++ b/indra/lscript/lscript_compile/indra.l @@ -355,6 +355,10 @@ extern "C" { int yyerror(const char *fmt, ...); }  "PSYS_PART_END_SCALE"	{ count(); yylval.ival = LLPS_PART_END_SCALE; return (INTEGER_CONSTANT); }  "PSYS_PART_MAX_AGE"		{ count(); yylval.ival = LLPS_PART_MAX_AGE; return (INTEGER_CONSTANT); } +"PSYS_PART_BLEND_FUNC_SOURCE"	{ count(); yylval.ival = LLPS_PART_BLEND_FUNC_SOURCE; return (INTEGER_CONSTANT); } +"PSYS_PART_BLEND_FUNC_DEST"		{ count(); yylval.ival = LLPS_PART_BLEND_FUNC_DEST; return (INTEGER_CONSTANT); } +"PSYS_PART_START_GLOW"	{ count(); yylval.ival = LLPS_PART_START_GLOW; return (INTEGER_CONSTANT); } +"PSYS_PART_END_GLOW"	{ count(); yylval.ival = LLPS_PART_END_GLOW; return (INTEGER_CONSTANT); }  "PSYS_PART_WIND_MASK"				{ count(); yylval.ival = LLPartData::LL_PART_WIND_MASK; return(INTEGER_CONSTANT); }  "PSYS_PART_INTERP_COLOR_MASK"		{ count(); yylval.ival = LLPartData::LL_PART_INTERP_COLOR_MASK; return(INTEGER_CONSTANT); } @@ -365,6 +369,16 @@ extern "C" { int yyerror(const char *fmt, ...); }  "PSYS_PART_TARGET_POS_MASK"			{ count(); yylval.ival = LLPartData::LL_PART_TARGET_POS_MASK; return(INTEGER_CONSTANT); }  "PSYS_PART_EMISSIVE_MASK"			{ count(); yylval.ival = LLPartData::LL_PART_EMISSIVE_MASK; return(INTEGER_CONSTANT); }  "PSYS_PART_TARGET_LINEAR_MASK"		{ count(); yylval.ival = LLPartData::LL_PART_TARGET_LINEAR_MASK; return(INTEGER_CONSTANT); } +"PSYS_PART_RIBBON_MASK"				{ count(); yylval.ival = LLPartData::LL_PART_RIBBON_MASK; return(INTEGER_CONSTANT); } + +"PSYS_PART_BF_ONE"						{ count(); yylval.ival = LLPartData::LL_PART_BF_ONE; return(INTEGER_CONSTANT); } +"PSYS_PART_BF_ZERO"						{ count(); yylval.ival = LLPartData::LL_PART_BF_ZERO; return(INTEGER_CONSTANT); } +"PSYS_PART_BF_DEST_COLOR"				{ count(); yylval.ival = LLPartData::LL_PART_BF_DEST_COLOR; return(INTEGER_CONSTANT); } +"PSYS_PART_BF_SOURCE_COLOR"				{ count(); yylval.ival = LLPartData::LL_PART_BF_SOURCE_COLOR; return(INTEGER_CONSTANT); } +"PSYS_PART_BF_ONE_MINUS_DEST_COLOR"		{ count(); yylval.ival = LLPartData::LL_PART_BF_ONE_MINUS_DEST_COLOR; return(INTEGER_CONSTANT); } +"PSYS_PART_BF_ONE_MINUS_SOURCE_COLOR"	{ count(); yylval.ival = LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_COLOR; return(INTEGER_CONSTANT); } +"PSYS_PART_BF_SOURCE_ALPHA"				{ count(); yylval.ival = LLPartData::LL_PART_BF_SOURCE_ALPHA; return(INTEGER_CONSTANT); } +"PSYS_PART_BF_ONE_MINUS_SOURCE_ALPHA"	{ count(); yylval.ival = LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_ALPHA; return(INTEGER_CONSTANT); }  "PSYS_SRC_MAX_AGE"					{ count(); yylval.ival = LLPS_SRC_MAX_AGE; return(INTEGER_CONSTANT); } diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index 313b310e1e..6fa16825df 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -394,10 +394,15 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask)  		if (group->mSpatialPartition->mRenderByGroup &&  		    !group->isDead())  		{ -			bool draw_glow_for_this_partition = mVertexShaderLevel > 0 && // no shaders = no glow. -				// All particle systems seem to come off the wire with texture entries which claim that they glow.  This is probably a bug in the data.  Suppress. -				group->mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_PARTICLE && -				group->mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_HUD_PARTICLE; +			static LLFastTimer::DeclareTimer FTM_RENDER_ALPHA_GROUP_LOOP("Alpha Group"); +			LLFastTimer t(FTM_RENDER_ALPHA_GROUP_LOOP); + +			bool draw_glow_for_this_partition = mVertexShaderLevel > 0; // no shaders = no glow. + +			bool disable_cull = group->mSpatialPartition->mPartitionType == LLViewerRegion::PARTITION_PARTICLE || +				group->mSpatialPartition->mPartitionType == LLViewerRegion::PARTITION_HUD_PARTICLE; + +			LLGLDisable cull(disable_cull ? GL_CULL_FACE : 0);  			LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[LLRenderPass::PASS_ALPHA]; @@ -498,32 +503,31 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask)  					}  				} -				params.mVertexBuffer->setBuffer(mask); -				params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset); -				gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode); +				static LLFastTimer::DeclareTimer FTM_RENDER_ALPHA_PUSH("Alpha Push Verts"); +				{ +					LLFastTimer t(FTM_RENDER_ALPHA_PUSH); +					gGL.blendFunc((LLRender::eBlendFactor) params.mBlendFuncSrc, (LLRender::eBlendFactor) params.mBlendFuncDst, mAlphaSFactor, mAlphaDFactor); +					params.mVertexBuffer->setBuffer(mask); +					params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset); +					gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode); +				}  				// If this alpha mesh has glow, then draw it a second time to add the destination-alpha (=glow).  Interleaving these state-changing calls could be expensive, but glow must be drawn Z-sorted with alpha.  				if (current_shader &&   					draw_glow_for_this_partition &&  					params.mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_EMISSIVE))  				{ +					static LLFastTimer::DeclareTimer FTM_RENDER_ALPHA_GLOW("Alpha Glow"); +					LLFastTimer t(FTM_RENDER_ALPHA_GLOW);  					// install glow-accumulating blend mode  					gGL.blendFunc(LLRender::BF_ZERO, LLRender::BF_ONE, // don't touch color  						      LLRender::BF_ONE, LLRender::BF_ONE); // add to alpha (glow) -					emissive_shader->bind(); -					 -					// glow doesn't use vertex colors from the mesh data -					params.mVertexBuffer->setBuffer((mask & ~LLVertexBuffer::MAP_COLOR) | LLVertexBuffer::MAP_EMISSIVE); +					params.mVertexBuffer->setBuffer(mask | LLVertexBuffer::MAP_EMISSIVE);  					// do the actual drawing, again  					params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);  					gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode); - -					// restore our alpha blend mode -					gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor); - -					current_shader->bind();  				}  				if (tex_setup) @@ -536,6 +540,8 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask)  		}  	} +	gGL.setSceneBlendType(LLRender::BT_ALPHA); +  	LLVertexBuffer::unbind();	  	if (!light_enabled) diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index dd69172184..1ec56eb5f8 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -4654,7 +4654,9 @@ LLDrawInfo::LLDrawInfo(U16 start, U16 end, U32 count, U32 offset,  	mGroup(NULL),  	mFace(NULL),  	mDistance(0.f), -	mDrawMode(LLRender::TRIANGLES) +	mDrawMode(LLRender::TRIANGLES), +	mBlendFuncSrc(LLRender::BF_SOURCE_ALPHA), +	mBlendFuncDst(LLRender::BF_ONE_MINUS_SOURCE_ALPHA)  {  	mVertexBuffer->validateRange(mStart, mEnd, mCount, mOffset); diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index b5543c4a37..08e77855c4 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -119,6 +119,8 @@ public:  	LL_ALIGN_16(LLFace* mFace); //associated face  	F32 mDistance;  	U32 mDrawMode; +	U32 mBlendFuncSrc; +	U32 mBlendFuncDst;  	struct CompareTexture  	{ diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index b1a60197a2..09cc4a1121 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -1553,6 +1553,8 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,  				dp->setPassFlags(value);  				dp->unpackUUID(owner_id, "Owner"); +				mOwnerID = owner_id; +  				if (value & 0x80)  				{  					dp->unpackVector3(new_angv, "Omega"); @@ -1626,13 +1628,13 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,                  retval |= checkMediaURL(media_url);  				// -				// Unpack particle system data +				// Unpack particle system data (legacy)  				//  				if (value & 0x8)  				{ -					unpackParticleSource(*dp, owner_id); +					unpackParticleSource(*dp, owner_id, true);  				} -				else +				else if (!(value & 0x400))  				{  					deleteParticleSource();  				} @@ -1697,7 +1699,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,  				// keep local flags and overwrite remote-controlled flags  				mFlags = (mFlags & FLAGS_LOCAL) | flags; -					// ...new objects that should come in selected need to be added to the selected list +				// ...new objects that should come in selected need to be added to the selected list  				mCreateSelected = ((flags & FLAGS_CREATE_SELECTED) != 0);  			}  			break; @@ -4604,7 +4606,7 @@ void LLViewerObject::unpackParticleSource(const S32 block_num, const LLUUID& own  	}  } -void LLViewerObject::unpackParticleSource(LLDataPacker &dp, const LLUUID& owner_id) +void LLViewerObject::unpackParticleSource(LLDataPacker &dp, const LLUUID& owner_id, bool legacy)  {  	if (!mPartSourcep.isNull() && mPartSourcep->isDead())  	{ @@ -4613,7 +4615,7 @@ void LLViewerObject::unpackParticleSource(LLDataPacker &dp, const LLUUID& owner_  	if (mPartSourcep)  	{  		// If we've got one already, just update the existing source (or remove it) -		if (!LLViewerPartSourceScript::unpackPSS(this, mPartSourcep, dp)) +		if (!LLViewerPartSourceScript::unpackPSS(this, mPartSourcep, dp, legacy))  		{  			mPartSourcep->setDead();  			mPartSourcep = NULL; @@ -4621,7 +4623,7 @@ void LLViewerObject::unpackParticleSource(LLDataPacker &dp, const LLUUID& owner_  	}  	else  	{ -		LLPointer<LLViewerPartSourceScript> pss = LLViewerPartSourceScript::unpackPSS(this, NULL, dp); +		LLPointer<LLViewerPartSourceScript> pss = LLViewerPartSourceScript::unpackPSS(this, NULL, dp, legacy);  		//If the owner is muted, don't create the system  		if(LLMuteList::getInstance()->isMuted(owner_id, LLMute::flagParticles)) return;  		// We need to be able to deal with a particle source that hasn't changed, but still got an update! @@ -5467,6 +5469,11 @@ F32 LLAlphaObject::getPartSize(S32 idx)  	return 0.f;  } +void LLAlphaObject::getBlendFunc(S32 face, U32& src, U32& dst) +{ + +} +  // virtual  void LLStaticViewerObject::updateDrawable(BOOL force_damped)  { diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 97cf0a4850..cab617b745 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -584,6 +584,7 @@ public:  	} EPhysicsShapeType;  	LLUUID			mID; +	LLUUID			mOwnerID; //null if unknown  	// unique within region, not unique across regions  	// Local ID = 0 is not used @@ -662,7 +663,7 @@ protected:  	BOOL isOnMap();  	void unpackParticleSource(const S32 block_num, const LLUUID& owner_id); -	void unpackParticleSource(LLDataPacker &dp, const LLUUID& owner_id); +	void unpackParticleSource(LLDataPacker &dp, const LLUUID& owner_id, bool legacy);  	void deleteParticleSource();  	void setParticleSource(const LLPartSysData& particle_parameters, const LLUUID& owner_id); @@ -826,9 +827,12 @@ public:  								LLStrider<LLVector4a>& verticesp,  								LLStrider<LLVector3>& normalsp,   								LLStrider<LLVector2>& texcoordsp, -								LLStrider<LLColor4U>& colorsp,  +								LLStrider<LLColor4U>& colorsp, +								LLStrider<LLColor4U>& emissivep,  								LLStrider<U16>& indicesp) = 0; +	virtual void getBlendFunc(S32 face, U32& src, U32& dst); +  	F32 mDepth;  }; diff --git a/indra/newview/llviewerpartsim.cpp b/indra/newview/llviewerpartsim.cpp index 61cdfd7818..21f1d2619c 100644 --- a/indra/newview/llviewerpartsim.cpp +++ b/indra/newview/llviewerpartsim.cpp @@ -80,12 +80,31 @@ LLViewerPart::LLViewerPart() :  	mImagep(NULL)  {  	mPartSourcep = NULL; - +	mParent = NULL; +	mChild = NULL;  	++LLViewerPartSim::sParticleCount2 ;  }  LLViewerPart::~LLViewerPart()  { +	if (mPartSourcep.notNull() && mPartSourcep->mLastPart == this) +	{ +		mPartSourcep->mLastPart = NULL; +	} + +	//patch up holes in the ribbon +	if (mParent) +	{ +		llassert(mParent->mChild == this); +		mParent->mChild = mChild; +	} + +	if (mChild) +	{ +		llassert (mChild->mParent == this); +		mChild->mParent = mParent; +	} +  	mPartSourcep = NULL;  	--LLViewerPartSim::sParticleCount2 ; @@ -367,6 +386,9 @@ void LLViewerPartGroup::updateParticles(const F32 lastdt)  			part->mScale += frac*part->mEndScale;  		} +		// Do glow interpolation +		part->mGlow.mV[3] = (U8) (lerp(part->mStartGlow, part->mEndGlow, frac)*255.f); +  		// Set the last update time to now.  		part->mLastUpdateTime = cur_time; @@ -623,6 +645,9 @@ void LLViewerPartSim::updateSimulation()  {  	static LLFrameTimer update_timer; +	//reset VBO cursor +	LLVOPartGroup::sVBSlotCursor = 0; +  	const F32 dt = llmin(update_timer.getElapsedTimeAndResetF32(), 0.1f);   	if (!(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES))) diff --git a/indra/newview/llviewerpartsim.h b/indra/newview/llviewerpartsim.h index c91fcf0691..095de2060c 100644 --- a/indra/newview/llviewerpartsim.h +++ b/indra/newview/llviewerpartsim.h @@ -65,15 +65,22 @@ public:  	LLVPCallback		mVPCallback;				// Callback function for more complicated behaviors  	LLPointer<LLViewerPartSource> mPartSourcep;		// Particle source used for this object -	 + +	LLViewerPart*		mParent;					// particle to connect to if this is part of a particle ribbon +	LLViewerPart*		mChild;						// child particle for clean reference destruction  	// Current particle state (possibly used for rendering)  	LLPointer<LLViewerTexture>	mImagep;  	LLVector3		mPosAgent;  	LLVector3		mVelocity;  	LLVector3		mAccel; +	LLVector3		mAxis;  	LLColor4		mColor;  	LLVector2		mScale; +	F32				mStartGlow; +	F32				mEndGlow; +	LLColor4U		mGlow; +  	static U32		sNextPartID;  }; diff --git a/indra/newview/llviewerpartsource.cpp b/indra/newview/llviewerpartsource.cpp index b311f659fb..8c49ce646d 100644 --- a/indra/newview/llviewerpartsource.cpp +++ b/indra/newview/llviewerpartsource.cpp @@ -52,6 +52,8 @@ LLViewerPartSource::LLViewerPartSource(const U32 type) :  	static U32 id_seed = 0;  	mID = ++id_seed; +	mLastPart = NULL; +  	mDelay = 0 ;  } @@ -279,6 +281,22 @@ void LLViewerPartSourceScript::update(const F32 dt)  			{  				part->mFlags |= LLPartData::LL_PART_HUD;  			} + +			if (part->mFlags & LLPartData::LL_PART_RIBBON_MASK && mLastPart) +			{ //set previous particle's parent to this particle to chain ribbon together +				mLastPart->mParent = part; +				part->mChild = mLastPart; +				part->mAxis = LLVector3(0,0,1); + +				if (mSourceObjectp.notNull()) +				{ +					LLQuaternion rot = mSourceObjectp->getRenderRotation(); +					part->mAxis *= rot; +				} +			} + +			mLastPart = part; +  			part->mMaxAge = mPartSysData.mPartData.mMaxAge;  			part->mStartColor = mPartSysData.mPartData.mStartColor;  			part->mEndColor = mPartSysData.mPartData.mEndColor; @@ -290,6 +308,13 @@ void LLViewerPartSourceScript::update(const F32 dt)  			part->mAccel = mPartSysData.mPartAccel; +			part->mBlendFuncDest = mPartSysData.mPartData.mBlendFuncDest; +			part->mBlendFuncSource = mPartSysData.mPartData.mBlendFuncSource; + +			part->mStartGlow = mPartSysData.mPartData.mStartGlow; +			part->mEndGlow = mPartSysData.mPartData.mEndGlow; +			part->mGlow = LLColor4U(0, 0, 0, (U8) (part->mStartGlow*255.f)); +			  			if (mPartSysData.mPattern & LLPartSysData::LL_PART_SRC_PATTERN_DROP)  			{  				part->mPosAgent = mPosAgent; @@ -430,28 +455,51 @@ LLPointer<LLViewerPartSourceScript> LLViewerPartSourceScript::unpackPSS(LLViewer  } -LLPointer<LLViewerPartSourceScript> LLViewerPartSourceScript::unpackPSS(LLViewerObject *source_objp, LLPointer<LLViewerPartSourceScript> pssp, LLDataPacker &dp) +LLPointer<LLViewerPartSourceScript> LLViewerPartSourceScript::unpackPSS(LLViewerObject *source_objp, LLPointer<LLViewerPartSourceScript> pssp, LLDataPacker &dp, bool legacy)  {  	if (!pssp)  	{  		LLPointer<LLViewerPartSourceScript> new_pssp = new LLViewerPartSourceScript(source_objp); -		if (!new_pssp->mPartSysData.unpack(dp)) +		if (legacy)  		{ -			return NULL; +			if (!new_pssp->mPartSysData.unpackLegacy(dp)) +			{ +				return NULL; +			} +		} +		else +		{ +			if (!new_pssp->mPartSysData.unpack(dp)) +			{ +				return NULL; +			}  		} +		  		if (new_pssp->mPartSysData.mTargetUUID.notNull())  		{  			LLViewerObject *target_objp = gObjectList.findObject(new_pssp->mPartSysData.mTargetUUID);  			new_pssp->setTargetObject(target_objp);  		} +		  		return new_pssp;  	}  	else  	{ -		if (!pssp->mPartSysData.unpack(dp)) +		if (legacy)  		{ -			return NULL; +			if (!pssp->mPartSysData.unpackLegacy(dp)) +			{ +				return NULL; +			}  		} +		else +		{ +			if (!pssp->mPartSysData.unpack(dp)) +			{ +				return NULL; +			} +		} +  		if (pssp->mPartSysData.mTargetUUID.notNull())  		{  			LLViewerObject *target_objp = gObjectList.findObject(pssp->mPartSysData.mTargetUUID); @@ -569,6 +617,11 @@ void LLViewerPartSourceSpiral::update(const F32 dt)  		part->mScale.mV[0] = 0.25f;  		part->mScale.mV[1] = 0.25f;  		part->mParameter = ll_frand(F_TWO_PI); +		part->mBlendFuncDest = LLRender::BF_ONE_MINUS_SOURCE_ALPHA; +		part->mBlendFuncSource = LLRender::BF_SOURCE_ALPHA; +		part->mStartGlow = 0.f; +		part->mEndGlow = 0.f; +		part->mGlow = LLColor4U(0, 0, 0, 0);  		LLViewerPartSim::getInstance()->addPart(part);  	} @@ -721,6 +774,12 @@ void LLViewerPartSourceBeam::update(const F32 dt)  		part->mPosAgent = mPosAgent;  		part->mVelocity = mTargetPosAgent - mPosAgent; +		part->mBlendFuncDest = LLRender::BF_ONE_MINUS_SOURCE_ALPHA; +		part->mBlendFuncSource = LLRender::BF_SOURCE_ALPHA; +		part->mStartGlow = 0.f; +		part->mEndGlow = 0.f; +		part->mGlow = LLColor4U(0, 0, 0, 0); +  		LLViewerPartSim::getInstance()->addPart(part);  	}  } @@ -825,6 +884,12 @@ void LLViewerPartSourceChat::update(const F32 dt)  		part->mScale.mV[0] = 0.25f;  		part->mScale.mV[1] = 0.25f;  		part->mParameter = ll_frand(F_TWO_PI); +		part->mBlendFuncDest = LLRender::BF_ONE_MINUS_SOURCE_ALPHA; +		part->mBlendFuncSource = LLRender::BF_SOURCE_ALPHA; +		part->mStartGlow = 0.f; +		part->mEndGlow = 0.f; +		part->mGlow = LLColor4U(0, 0, 0, 0); +  		LLViewerPartSim::getInstance()->addPart(part);  	} diff --git a/indra/newview/llviewerpartsource.h b/indra/newview/llviewerpartsource.h index 28702d36a2..12e926173b 100644 --- a/indra/newview/llviewerpartsource.h +++ b/indra/newview/llviewerpartsource.h @@ -76,6 +76,7 @@ public:  	LLVector3	mLastUpdatePosAgent;  	LLPointer<LLViewerObject>	mSourceObjectp;  	U32 mID; +	LLViewerPart* mLastPart; //last particle emitted (for making particle ribbons)  protected:  	U32			mType; @@ -85,7 +86,6 @@ protected:  	F32			mLastPartTime;  	LLUUID		mOwnerUUID;  	LLPointer<LLViewerTexture>	mImagep; -  	// Particle information  	U32			mPartFlags; // Flags for the particle  	U32         mDelay ; //delay to start particles @@ -114,7 +114,7 @@ public:  	// Returns a new particle source to attach to an object...  	static LLPointer<LLViewerPartSourceScript> unpackPSS(LLViewerObject *source_objp, LLPointer<LLViewerPartSourceScript> pssp, const S32 block_num); -	static LLPointer<LLViewerPartSourceScript> unpackPSS(LLViewerObject *source_objp, LLPointer<LLViewerPartSourceScript> pssp, LLDataPacker &dp); +	static LLPointer<LLViewerPartSourceScript> unpackPSS(LLViewerObject *source_objp, LLPointer<LLViewerPartSourceScript> pssp, LLDataPacker &dp, bool legacy);  	static LLPointer<LLViewerPartSourceScript> createPSS(LLViewerObject *source_objp, const LLPartSysData& particle_parameters);  	LLViewerTexture *getImage() const				{ return mImagep; } diff --git a/indra/newview/llvograss.cpp b/indra/newview/llvograss.cpp index 4dca87652d..ed62abe4ef 100644 --- a/indra/newview/llvograss.cpp +++ b/indra/newview/llvograss.cpp @@ -476,6 +476,7 @@ void LLVOGrass::getGeometry(S32 idx,  								LLStrider<LLVector3>& normalsp,   								LLStrider<LLVector2>& texcoordsp,  								LLStrider<LLColor4U>& colorsp,  +								LLStrider<LLColor4U>& emissivep,  								LLStrider<U16>& indicesp)  {  	if(!mNumBlades)//stop rendering grass @@ -708,7 +709,11 @@ void LLGrassPartition::getGeometry(LLSpatialGroup* group)  		facep->setIndicesIndex(index_count);  		facep->setVertexBuffer(buffer);  		facep->setPoolType(LLDrawPool::POOL_ALPHA); -		object->getGeometry(facep->getTEOffset(), verticesp, normalsp, texcoordsp, colorsp, indicesp); + +		//dummy parameter (unused by this implementation) +		LLStrider<LLColor4U> emissivep; + +		object->getGeometry(facep->getTEOffset(), verticesp, normalsp, texcoordsp, colorsp, emissivep, indicesp);  		vertex_count += facep->getGeomCount();  		index_count += facep->getIndicesCount(); diff --git a/indra/newview/llvograss.h b/indra/newview/llvograss.h index b9835b8802..1fe9990cea 100644 --- a/indra/newview/llvograss.h +++ b/indra/newview/llvograss.h @@ -63,6 +63,7 @@ public:  								LLStrider<LLVector3>& normalsp,   								LLStrider<LLVector2>& texcoordsp,  								LLStrider<LLColor4U>& colorsp,  +								LLStrider<LLColor4U>& emissivep,  								LLStrider<U16>& indicesp);  	void updateFaceSize(S32 idx) { } diff --git a/indra/newview/llvopartgroup.cpp b/indra/newview/llvopartgroup.cpp index 1a9769f09d..53d67347d1 100644 --- a/indra/newview/llvopartgroup.cpp +++ b/indra/newview/llvopartgroup.cpp @@ -49,17 +49,11 @@ const F32 MAX_PART_LIFETIME = 120.f;  extern U64 gFrameTime;  LLPointer<LLVertexBuffer> LLVOPartGroup::sVB = NULL; -S32 LLVOPartGroup::sVBSlotFree[]; -S32* LLVOPartGroup::sVBSlotCursor = NULL; +S32 LLVOPartGroup::sVBSlotCursor = 0;  void LLVOPartGroup::initClass()  { -	for (S32 i = 0; i < LL_MAX_PARTICLE_COUNT; ++i) -	{ -		sVBSlotFree[i] = i; -	} - -	sVBSlotCursor = sVBSlotFree; +	  }  //static @@ -122,36 +116,33 @@ void LLVOPartGroup::destroyGL()  //static  S32 LLVOPartGroup::findAvailableVBSlot()  { -	if (sVBSlotCursor >= sVBSlotFree+LL_MAX_PARTICLE_COUNT) +	if (sVBSlotCursor >= LL_MAX_PARTICLE_COUNT)  	{ //no more available slots  		return -1;  	} -	S32 ret = *sVBSlotCursor; -	sVBSlotCursor++; - -	return ret; +	return sVBSlotCursor++;  }  bool ll_is_part_idx_allocated(S32 idx, S32* start, S32* end)  { -	while (start < end) +	/*while (start < end)  	{  		if (*start == idx)  		{ //not allocated (in free list)  			return false;  		}  		++start; -	} +	}*/  	//allocated (not in free list) -	return true; +	return false;  }  //static  void LLVOPartGroup::freeVBSlot(S32 idx)  { -	llassert(idx < LL_MAX_PARTICLE_COUNT && idx >= 0); +	/*llassert(idx < LL_MAX_PARTICLE_COUNT && idx >= 0);  	llassert(sVBSlotCursor > sVBSlotFree);  	llassert(ll_is_part_idx_allocated(idx, sVBSlotCursor, sVBSlotFree+LL_MAX_PARTICLE_COUNT)); @@ -159,7 +150,7 @@ void LLVOPartGroup::freeVBSlot(S32 idx)  	{  		sVBSlotCursor--;  		*sVBSlotCursor = idx; -	} +	}*/  }  LLVOPartGroup::LLVOPartGroup(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) @@ -189,6 +180,7 @@ F32 LLVOPartGroup::getBinRadius()  void LLVOPartGroup::updateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax)  {		  	const LLVector3& pos_agent = getPositionAgent(); +  	newMin.load3( (pos_agent - mScale).mV);  	newMax.load3( (pos_agent + mScale).mV);  	LLVector4a pos; @@ -273,6 +265,16 @@ F32 LLVOPartGroup::getPartSize(S32 idx)  	return 0.f;  } +void LLVOPartGroup::getBlendFunc(S32 idx, U32& src, U32& dst) +{ +	if (idx < (S32) mViewerPartGroupp->mParticles.size()) +	{ +		LLViewerPart* part = mViewerPartGroupp->mParticles[idx]; +		src = part->mBlendFuncSource; +		dst = part->mBlendFuncDest; +	} +} +  LLVector3 LLVOPartGroup::getCameraPosition() const  {  	return gAgentCamera.getCameraPositionAgent(); @@ -332,13 +334,42 @@ BOOL LLVOPartGroup::updateGeometry(LLDrawable *drawable)  	mDepth = 0.f;  	S32 i = 0 ;  	LLVector3 camera_agent = getCameraPosition(); +	 +	F32 max_scale = 0.f; + +  	for (i = 0 ; i < (S32)mViewerPartGroupp->mParticles.size(); i++)  	{  		const LLViewerPart *part = mViewerPartGroupp->mParticles[i]; + +		//remember the largest particle +		max_scale = llmax(max_scale, part->mScale.mV[0], part->mScale.mV[1]); + +		if (part->mFlags & LLPartData::LL_PART_RIBBON_MASK) +		{ //include ribbon segment length in scale +			const LLVector3* pos_agent = NULL; +			if (part->mParent) +			{ +				pos_agent = &(part->mParent->mPosAgent); +			} +			else if (part->mPartSourcep.notNull()) +			{ +				pos_agent = &(part->mPartSourcep->mPosAgent); +			} + +			if (pos_agent) +			{ +				F32 dist = (*pos_agent-part->mPosAgent).length(); + +				max_scale = llmax(max_scale, dist); +			} +		} +  		LLVector3 part_pos_agent(part->mPosAgent);  		LLVector3 at(part_pos_agent - camera_agent); +		  		F32 camera_dist_squared = at.lengthSquared();  		F32 inv_camera_dist_squared;  		if (camera_dist_squared > 1.f) @@ -411,6 +442,9 @@ BOOL LLVOPartGroup::updateGeometry(LLDrawable *drawable)  		facep->setSize(0, 0);  	} +	//record max scale (used to stretch bounding box for visibility culling) +	mScale.set(max_scale, max_scale, max_scale); +  	mDrawable->movePartition();  	LLPipeline::sCompiles++;  	return TRUE; @@ -478,74 +512,129 @@ BOOL LLVOPartGroup::lineSegmentIntersect(const LLVector3& start, const LLVector3  void LLVOPartGroup::getGeometry(const LLViewerPart& part,  								LLStrider<LLVector4a>& verticesp)  { -	LLVector4a part_pos_agent; -	part_pos_agent.load3(part.mPosAgent.mV); -	LLVector4a camera_agent; -	camera_agent.load3(getCameraPosition().mV);  -	LLVector4a at; -	at.setSub(part_pos_agent, camera_agent); -	LLVector4a up(0, 0, 1); -	LLVector4a right; - -	right.setCross3(at, up); -	right.normalize3fast(); -	up.setCross3(right, at); -	up.normalize3fast(); - -	if (part.mFlags & LLPartData::LL_PART_FOLLOW_VELOCITY_MASK) +	if (part.mFlags & LLPartData::LL_PART_RIBBON_MASK)  	{ -		LLVector4a normvel; -		normvel.load3(part.mVelocity.mV); -		normvel.normalize3fast(); -		LLVector2 up_fracs; -		up_fracs.mV[0] = normvel.dot3(right).getF32(); -		up_fracs.mV[1] = normvel.dot3(up).getF32(); -		up_fracs.normalize(); -		LLVector4a new_up; -		LLVector4a new_right; - -		//new_up = up_fracs.mV[0] * right + up_fracs.mV[1]*up; -		LLVector4a t = right; -		t.mul(up_fracs.mV[0]); -		new_up = up; -		new_up.mul(up_fracs.mV[1]); -		new_up.add(t); - -		//new_right = up_fracs.mV[1] * right - up_fracs.mV[0]*up; -		t = right; -		t.mul(up_fracs.mV[1]); -		new_right = up; -		new_right.mul(up_fracs.mV[0]); -		t.sub(new_right); - -		up = new_up; -		right = t; -		up.normalize3fast(); -		right.normalize3fast(); +		LLVector4a axis, pos, paxis, ppos; +		F32 scale, pscale; + +		pos.load3(part.mPosAgent.mV); +		axis.load3(part.mAxis.mV); +		scale = part.mScale.mV[0]; +		 +		if (part.mParent) +		{ +			ppos.load3(part.mParent->mPosAgent.mV); +			paxis.load3(part.mParent->mAxis.mV); +			pscale = part.mParent->mScale.mV[0]; +		} +		else +		{ //use source object as position +			 +			if (part.mPartSourcep->mSourceObjectp.notNull()) +			{ +				LLVector3 v = LLVector3(0,0,1); +				v *= part.mPartSourcep->mSourceObjectp->getRenderRotation(); +				paxis.load3(v.mV); +				ppos.load3(part.mPartSourcep->mPosAgent.mV); +				pscale = part.mStartScale.mV[0]; +			} +			else +			{ //no source object, no parent, nothing to draw +				ppos = pos; +				pscale = scale; +				paxis = axis; +			} +		} + +		LLVector4a p0, p1, p2, p3; + +		scale *= 0.5f; +		pscale *= 0.5f; + +		axis.mul(scale); +		paxis.mul(pscale); + +		p0.setAdd(pos, axis); +		p1.setSub(pos,axis); +		p2.setAdd(ppos, paxis); +		p3.setSub(ppos, paxis); + +		(*verticesp++) = p2; +		(*verticesp++) = p3; +		(*verticesp++) = p0; +		(*verticesp++) = p1;  	} +	else +	{ +		LLVector4a part_pos_agent; +		part_pos_agent.load3(part.mPosAgent.mV); +		LLVector4a camera_agent; +		camera_agent.load3(getCameraPosition().mV);  +		LLVector4a at; +		at.setSub(part_pos_agent, camera_agent); +		LLVector4a up(0, 0, 1); +		LLVector4a right; + +		right.setCross3(at, up); +		right.normalize3fast(); +		up.setCross3(right, at); +		up.normalize3fast(); -	right.mul(0.5f*part.mScale.mV[0]); -	up.mul(0.5f*part.mScale.mV[1]); +		if (part.mFlags & LLPartData::LL_PART_FOLLOW_VELOCITY_MASK) +		{ +			LLVector4a normvel; +			normvel.load3(part.mVelocity.mV); +			normvel.normalize3fast(); +			LLVector2 up_fracs; +			up_fracs.mV[0] = normvel.dot3(right).getF32(); +			up_fracs.mV[1] = normvel.dot3(up).getF32(); +			up_fracs.normalize(); +			LLVector4a new_up; +			LLVector4a new_right; + +			//new_up = up_fracs.mV[0] * right + up_fracs.mV[1]*up; +			LLVector4a t = right; +			t.mul(up_fracs.mV[0]); +			new_up = up; +			new_up.mul(up_fracs.mV[1]); +			new_up.add(t); + +			//new_right = up_fracs.mV[1] * right - up_fracs.mV[0]*up; +			t = right; +			t.mul(up_fracs.mV[1]); +			new_right = up; +			new_right.mul(up_fracs.mV[0]); +			t.sub(new_right); + +			up = new_up; +			right = t; +			up.normalize3fast(); +			right.normalize3fast(); +		} +		right.mul(0.5f*part.mScale.mV[0]); +		up.mul(0.5f*part.mScale.mV[1]); -	//HACK -- the verticesp->mV[3] = 0.f here are to set the texture index to 0 (particles don't use texture batching, maybe they should) -	// this works because there is actually a 4th float stored after the vertex position which is used as a texture index -	// also, somebody please VECTORIZE THIS -	LLVector4a ppapu; -	LLVector4a ppamu; +		//HACK -- the verticesp->mV[3] = 0.f here are to set the texture index to 0 (particles don't use texture batching, maybe they should) +		// this works because there is actually a 4th float stored after the vertex position which is used as a texture index +		// also, somebody please VECTORIZE THIS -	ppapu.setAdd(part_pos_agent, up); -	ppamu.setSub(part_pos_agent, up); +		LLVector4a ppapu; +		LLVector4a ppamu; -	verticesp->setSub(ppapu, right); -	(*verticesp++).getF32ptr()[3] = 0.f; -	verticesp->setSub(ppamu, right); -	(*verticesp++).getF32ptr()[3] = 0.f; -	verticesp->setAdd(ppapu, right); -	(*verticesp++).getF32ptr()[3] = 0.f; -	verticesp->setAdd(ppamu, right); -	(*verticesp++).getF32ptr()[3] = 0.f; +		ppapu.setAdd(part_pos_agent, up); +		ppamu.setSub(part_pos_agent, up); + +		verticesp->setSub(ppapu, right); +		(*verticesp++).getF32ptr()[3] = 0.f; +		verticesp->setSub(ppamu, right); +		(*verticesp++).getF32ptr()[3] = 0.f; +		verticesp->setAdd(ppapu, right); +		(*verticesp++).getF32ptr()[3] = 0.f; +		verticesp->setAdd(ppamu, right); +		(*verticesp++).getF32ptr()[3] = 0.f; +	}  } @@ -555,6 +644,7 @@ void LLVOPartGroup::getGeometry(S32 idx,  								LLStrider<LLVector3>& normalsp,   								LLStrider<LLVector2>& texcoordsp,  								LLStrider<LLColor4U>& colorsp,  +								LLStrider<LLColor4U>& emissivep,  								LLStrider<U16>& indicesp)  {  	if (idx >= (S32) mViewerPartGroupp->mParticles.size()) @@ -566,10 +656,40 @@ void LLVOPartGroup::getGeometry(S32 idx,  	getGeometry(part, verticesp); -	*colorsp++ = part.mColor; -	*colorsp++ = part.mColor; -	*colorsp++ = part.mColor; -	*colorsp++ = part.mColor; +	LLColor4U pcolor; +	LLColor4U color = part.mColor; + +	LLColor4U pglow; + +	if (part.mFlags & LLPartData::LL_PART_RIBBON_MASK) +	{ //make sure color blends properly +		if (part.mParent) +		{ +			pglow = part.mParent->mGlow; +			pcolor = part.mParent->mColor; +		} +		else  +		{ +			pglow = LLColor4U(0, 0, 0, (U8) (255.f*part.mStartGlow)); +			pcolor = part.mStartColor; +		} +	} +	else +	{ +		pglow = part.mGlow; +		pcolor = color; +	} + +	*colorsp++ = pcolor; +	*colorsp++ = pcolor; +	*colorsp++ = color; +	*colorsp++ = color; + +	*emissivep++ = pglow; +	*emissivep++ = pglow; +	*emissivep++ = part.mGlow; +	*emissivep++ = part.mGlow; +  	if (!(part.mFlags & LLPartData::LL_PART_EMISSIVE_MASK))  	{ //not fullbright, needs normal @@ -712,10 +832,13 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group)  	LLStrider<LLVector3> normalsp;  	LLStrider<LLVector2> texcoordsp;  	LLStrider<LLColor4U> colorsp; +	LLStrider<LLColor4U> emissivep;  	buffer->getVertexStrider(verticesp);  	buffer->getNormalStrider(normalsp);  	buffer->getColorStrider(colorsp); +	buffer->getEmissiveStrider(emissivep); +  	LLSpatialGroup::drawmap_elem_t& draw_vec = group->mDrawMap[mRenderPass];	 @@ -724,7 +847,7 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group)  		LLFace* facep = *i;  		LLAlphaObject* object = (LLAlphaObject*) facep->getViewerObject(); -		if (!facep->isState(LLFace::PARTICLE)) +		//if (!facep->isState(LLFace::PARTICLE))  		{ //set the indices of this face  			S32 idx = LLVOPartGroup::findAvailableVBSlot();  			if (idx >= 0) @@ -733,7 +856,7 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group)  				facep->setIndicesIndex(idx*6);  				facep->setVertexBuffer(LLVOPartGroup::sVB);  				facep->setPoolType(LLDrawPool::POOL_ALPHA); -				facep->setState(LLFace::PARTICLE); +				//facep->setState(LLFace::PARTICLE);  			}  			else  			{ @@ -748,8 +871,9 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group)  		LLStrider<LLVector3> cur_norm = normalsp + geom_idx;  		LLStrider<LLVector2> cur_tc = texcoordsp + geom_idx;  		LLStrider<LLColor4U> cur_col = colorsp + geom_idx; +		LLStrider<LLColor4U> cur_glow = emissivep + geom_idx; -		object->getGeometry(facep->getTEOffset(), cur_vert, cur_norm, cur_tc, cur_col, cur_idx); +		object->getGeometry(facep->getTEOffset(), cur_vert, cur_norm, cur_tc, cur_col, cur_glow, cur_idx);  		llassert(facep->getGeomCount() == 4);  		llassert(facep->getIndicesCount() == 6); @@ -765,9 +889,16 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group)  		bool batched = false; +		U32 bf_src = LLRender::BF_SOURCE_ALPHA; +		U32 bf_dst = LLRender::BF_ONE_MINUS_SOURCE_ALPHA; + +		object->getBlendFunc(facep->getTEOffset(), bf_src, bf_dst); +  		if (idx >= 0 &&  			draw_vec[idx]->mTexture == facep->getTexture() && -			draw_vec[idx]->mFullbright == fullbright) +			draw_vec[idx]->mFullbright == fullbright && +			draw_vec[idx]->mBlendFuncDst == bf_dst && +			draw_vec[idx]->mBlendFuncSrc == bf_src)  		{  			if (draw_vec[idx]->mEnd == facep->getGeomIndex()-1)  			{ @@ -799,6 +930,8 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group)  			info->mExtents[0] = group->mObjectExtents[0];  			info->mExtents[1] = group->mObjectExtents[1];  			info->mVSize = vsize; +			info->mBlendFuncDst = bf_dst; +			info->mBlendFuncSrc = bf_src;  			draw_vec.push_back(info);  			//for alpha sorting  			facep->setDrawInfo(info); diff --git a/indra/newview/llvopartgroup.h b/indra/newview/llvopartgroup.h index ce05a0282e..3c2e0344a2 100644 --- a/indra/newview/llvopartgroup.h +++ b/indra/newview/llvopartgroup.h @@ -42,8 +42,7 @@ public:  	//vertex buffer for holding all particles  	static LLPointer<LLVertexBuffer> sVB; -	static S32 sVBSlotFree[LL_MAX_PARTICLE_COUNT]; -	static S32* sVBSlotCursor; +	static S32 sVBSlotCursor;  	static void initClass();  	static void restoreGL(); @@ -57,6 +56,7 @@ public:  							LLVertexBuffer::MAP_NORMAL |  							LLVertexBuffer::MAP_TEXCOORD0 |  							LLVertexBuffer::MAP_COLOR | +							LLVertexBuffer::MAP_EMISSIVE |  							LLVertexBuffer::MAP_TEXTURE_INDEX  	}; @@ -91,10 +91,12 @@ public:  								LLStrider<LLVector3>& normalsp,   								LLStrider<LLVector2>& texcoordsp,  								LLStrider<LLColor4U>& colorsp,  +								LLStrider<LLColor4U>& emissivep,  								LLStrider<U16>& indicesp);  	void updateFaceSize(S32 idx) { }  	F32 getPartSize(S32 idx); +	void getBlendFunc(S32 idx, U32& src, U32& dst);  	LLUUID getPartOwner(S32 idx);  	LLUUID getPartSource(S32 idx); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index e22b4d511b..e39d2862fb 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -384,7 +384,6 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys,  	}  	else  	{ -		// CORY TO DO: Figure out how to get the value here  		if (update_type != OUT_TERSE_IMPROVED)  		{  			LLVolumeParams volume_params; @@ -453,6 +452,11 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys,  				mFaceMappingChanged = TRUE;  				mTexAnimMode = 0;  			} + +			if (value & 0x400) +			{ //particle system (new) +				unpackParticleSource(*dp, mOwnerID, false); +			}  		}  		else  		{ | 
