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