r4187 - in trunk/data/qcsrc: client common server

DONOTREPLY at icculus.org DONOTREPLY at icculus.org
Tue Aug 26 06:14:40 EDT 2008


Author: div0
Date: 2008-08-26 06:14:38 -0400 (Tue, 26 Aug 2008)
New Revision: 4187

Modified:
   trunk/data/qcsrc/client/Main.qc
   trunk/data/qcsrc/client/particles.qc
   trunk/data/qcsrc/common/util.qc
   trunk/data/qcsrc/common/util.qh
   trunk/data/qcsrc/server/g_triggers.qc
   trunk/data/qcsrc/server/g_world.qc
Log:
new particle property "movedir"; traces in that direction. Length of the vector is how much of trace_plane_normal to use.


Modified: trunk/data/qcsrc/client/Main.qc
===================================================================
--- trunk/data/qcsrc/client/Main.qc	2008-08-26 08:29:28 UTC (rev 4186)
+++ trunk/data/qcsrc/client/Main.qc	2008-08-26 10:14:38 UTC (rev 4187)
@@ -51,6 +51,7 @@
 	CSQC_CheckEngine();
 
 	configdb = db_create();
+	compressShortVector_init();
 
 	drawfont = 0;
 	menu_visible = FALSE;

Modified: trunk/data/qcsrc/client/particles.qc
===================================================================
--- trunk/data/qcsrc/client/particles.qc	2008-08-26 08:29:28 UTC (rev 4186)
+++ trunk/data/qcsrc/client/particles.qc	2008-08-26 10:14:38 UTC (rev 4187)
@@ -43,6 +43,7 @@
 .float impulse; // density
 .string noise; // sound
 .float absolute;
+.vector movedir; // trace direction
 
 void Draw_PointParticles()
 {
@@ -62,7 +63,14 @@
 		p_z += random() * sz_z;
 		if(PointInBrush(self, p))
 		{
-			pointparticles(self.cnt, p, self.velocity + randomvec() * self.waterlevel, self.count, self.glow_color);
+			if(self.movedir != '0 0 0')
+			{
+				traceline(p, p + normalize(self.movedir) * 4096, 0, world);
+				p = trace_endpos;
+				pointparticles(self.cnt, p, trace_plane_normal * vlen(self.movedir) + self.velocity + randomvec() * self.waterlevel, self.count, self.glow_color);
+			}
+			else
+				pointparticles(self.cnt, p, self.velocity + randomvec() * self.waterlevel, self.count, self.glow_color);
 			if(self.noise != "")
 			{
 				self.origin = p;
@@ -91,9 +99,8 @@
 	self.impulse = ReadCoord(); // density (<0: point, >0: volume)
 	if(self.impulse == 0)
 		self.impulse = 1; // one per sec
-	self.velocity_x = ReadCoord();
-	self.velocity_y = ReadCoord();
-	self.velocity_z = ReadCoord();
+	self.velocity = decompressShortVector(ReadShort());
+	self.movedir = decompressShortVector(ReadShort());
 	self.waterlevel = ReadCoord();
 	self.count = ReadCoord();
 	self.glow_color = ReadByte();

Modified: trunk/data/qcsrc/common/util.qc
===================================================================
--- trunk/data/qcsrc/common/util.qc	2008-08-26 08:29:28 UTC (rev 4186)
+++ trunk/data/qcsrc/common/util.qc	2008-08-26 10:14:38 UTC (rev 4187)
@@ -476,3 +476,139 @@
 	+	'0 1 0' * (a_z * b_x - a_x * b_z)
 	+	'0 0 1' * (a_x * b_y - a_y * b_x);
 }
+
+// compressed vector format:
+// like MD3, just even shorter
+//   4 bit pitch (16 angles), 0 is -90, 8 is 0, 16 would be 90
+//   5 bit yaw (32 angles), 0=0, 8=90, 16=180, 24=270
+//   7 bit length (logarithmic encoding), 1/8 .. about 7844
+//     length = 2^(length_encoded/8) / 8
+// if pitch is 90, yaw does nothing and therefore indicates the sign (yaw is then either 11111 or 11110); 11111 is pointing DOWN
+// thus, valid values are from 0000.11110.0000000 to 1111.11111.1111111
+// the special value 0 indicates the zero vector
+
+float lengthLogTable[128];
+
+float invertLengthLog(float x)
+{
+	float l, r, m, lerr, rerr;
+
+	if(x >= lengthLogTable[127])
+		return 127;
+	if(x <= lengthLogTable[0])
+		return 0;
+
+	l = 0;
+	r = 127;
+
+	while(r - l > 1)
+	{
+		m = floor((l + r) / 2);
+		if(lengthLogTable[m] < x)
+			l = m;
+		else
+			r = m;
+	}
+
+	// now: r is >=, l is <
+	lerr = (x - lengthLogTable[l]);
+	rerr = (lengthLogTable[r] - x);
+	if(lerr < rerr)
+		return l;
+	return r;
+}
+
+vector decompressShortVector(float data)
+{
+	vector out;
+	float pitch, yaw, len;
+	if(data == 0)
+		return '0 0 0';
+	pitch = (data & 0xF000) / 0x1000;
+	yaw =   (data & 0x0F80) / 0x80;
+	len =   (data & 0x007F);
+
+	//print("\ndecompress: pitch ", ftos(pitch)); print("yaw ", ftos(yaw)); print("len ", ftos(len), "\n");
+
+	if(pitch == 0)
+	{
+		out_x = 0;
+		out_y = 0;
+		if(yaw == 31)
+			out_z = -1;
+		else
+			out_z = +1;
+	}
+	else
+	{
+		yaw   = .19634954084936207740 * yaw;
+		pitch = .19634954084936207740 * pitch - 1.57079632679489661922;
+		out_x = cos(yaw) *  cos(pitch);
+		out_y = sin(yaw) *  cos(pitch);
+		out_z =            -sin(pitch);
+	}
+
+	//print("decompressed: ", vtos(out), "\n");
+
+	return out * lengthLogTable[len];
+}
+
+float compressShortVector(vector vec)
+{
+	vector ang;
+	float pitch, yaw, len;
+	if(vlen(vec) == 0)
+		return 0;
+	//print("compress: ", vtos(vec), "\n");
+	ang = vectoangles(vec);
+	ang_x = -ang_x;
+	if(ang_x < -90)
+		ang_x += 360;
+	if(ang_x < -90 && ang_x > +90)
+		error("BOGUS vectoangles");
+	//print("angles: ", vtos(ang), "\n");
+
+	pitch = floor(0.5 + (ang_x + 90) * 16 / 180) & 15; // -90..90 to 0..14
+	if(pitch == 0)
+	{
+		if(vec_z < 0)
+			yaw = 31;
+		else
+			yaw = 30;
+	}
+	else
+		yaw = floor(0.5 + ang_y * 32 / 360)          & 31; // 0..360 to 0..32
+	len = invertLengthLog(vlen(vec));
+
+	//print("compressed: pitch ", ftos(pitch)); print("yaw ", ftos(yaw)); print("len ", ftos(len), "\n");
+
+	return (pitch * 0x1000) + (yaw * 0x80) + len;
+}
+
+void compressShortVector_init()
+{
+	float l, f, i;
+	l = 1;
+	f = pow(2, 1/8);
+	for(i = 0; i < 128; ++i)
+	{
+		lengthLogTable[i] = l;
+		l *= f;
+	}
+
+	if(cvar("developer"))
+	{
+		print("Verifying vector compression table...\n");
+		for(i = 0x0F00; i < 0xFFFF; ++i)
+			if(i != compressShortVector(decompressShortVector(i)))
+			{
+				print("BROKEN vector compression: ", ftos(i));
+				print(" -> ", vtos(decompressShortVector(i)));
+				print(" -> ", ftos(compressShortVector(decompressShortVector(i))));
+				print("\n");
+				error("b0rk");
+			}
+		print("Done.\n");
+	}
+}
+

Modified: trunk/data/qcsrc/common/util.qh
===================================================================
--- trunk/data/qcsrc/common/util.qh	2008-08-26 08:29:28 UTC (rev 4186)
+++ trunk/data/qcsrc/common/util.qh	2008-08-26 10:14:38 UTC (rev 4187)
@@ -61,3 +61,7 @@
 string ScoreString(float vflags, float value);
 
 vector cross(vector a, vector b);
+
+void compressShortVector_init();
+vector decompressShortVector(float data);
+float compressShortVector(vector vec);

Modified: trunk/data/qcsrc/server/g_triggers.qc
===================================================================
--- trunk/data/qcsrc/server/g_triggers.qc	2008-08-26 08:29:28 UTC (rev 4186)
+++ trunk/data/qcsrc/server/g_triggers.qc	2008-08-26 10:14:38 UTC (rev 4187)
@@ -501,9 +501,8 @@
 	WriteCoord(MSG_ENTITY, self.maxs_z - self.mins_z);
 	WriteShort(MSG_ENTITY, self.cnt);
 	WriteCoord(MSG_ENTITY, self.impulse);
-	WriteCoord(MSG_ENTITY, self.velocity_x);
-	WriteCoord(MSG_ENTITY, self.velocity_y);
-	WriteCoord(MSG_ENTITY, self.velocity_z);
+	WriteShort(MSG_ENTITY, compressShortVector(self.velocity));
+	WriteShort(MSG_ENTITY, compressShortVector(self.movedir));
 	WriteCoord(MSG_ENTITY, self.waterlevel);
 	WriteCoord(MSG_ENTITY, self.count);
 	WriteByte(MSG_ENTITY, self.glow_color);

Modified: trunk/data/qcsrc/server/g_world.qc
===================================================================
--- trunk/data/qcsrc/server/g_world.qc	2008-08-26 08:29:28 UTC (rev 4186)
+++ trunk/data/qcsrc/server/g_world.qc	2008-08-26 10:14:38 UTC (rev 4187)
@@ -175,6 +175,8 @@
 		error("world already spawned - you may have EXACTLY ONE worldspawn!");
 	world_already_spawned = TRUE;
 
+	compressShortVector_init();
+
 	local entity head;
 	head = nextent(world);
 	maxclients = 0;




More information about the nexuiz-commits mailing list