Mod_FindNonSolidLocation now takes a radius and can output to a different vector...
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Sun, 9 Mar 2003 11:19:57 +0000 (11:19 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Sun, 9 Mar 2003 11:19:57 +0000 (11:19 +0000)
git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@2817 d7cf8633-e32d-0410-b094-e92efae38249

cl_parse.c
model_brush.c
model_brush.h

index fcf885c..9863aa3 100644 (file)
@@ -106,22 +106,22 @@ CL_ParseStartSoundPacket
 */
 void CL_ParseStartSoundPacket(int largesoundindex)
 {
-    vec3_t  pos;
-    int        channel, ent;
-    int        sound_num;
-    int        volume;
-    int        field_mask;
-    float      attenuation;
-       int             i;
+       vec3_t  pos;
+       int     channel, ent;
+       int     sound_num;
+       int     volume;
+       int     field_mask;
+       float   attenuation;
+       int             i;
 
-    field_mask = MSG_ReadByte();
+       field_mask = MSG_ReadByte();
 
-    if (field_mask & SND_VOLUME)
+       if (field_mask & SND_VOLUME)
                volume = MSG_ReadByte ();
        else
                volume = DEFAULT_SOUND_PACKET_VOLUME;
 
-    if (field_mask & SND_ATTENUATION)
+       if (field_mask & SND_ATTENUATION)
                attenuation = MSG_ReadByte () / 64.0;
        else
                attenuation = DEFAULT_SOUND_PACKET_ATTENUATION;
@@ -153,7 +153,7 @@ void CL_ParseStartSoundPacket(int largesoundindex)
        for (i = 0;i < 3;i++)
                pos[i] = MSG_ReadCoord ();
 
-    S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume/255.0, attenuation);
+       S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume/255.0, attenuation);
 }
 
 /*
@@ -1008,7 +1008,8 @@ void CL_ParseTempEntity (void)
        case TE_WIZSPIKE:
                // spike hitting wall
                MSG_ReadVector(pos);
-               Mod_FindNonSolidLocation(pos, cl.worldmodel);
+               Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
+               CL_AllocDlight (NULL, pos, 50, 0.25f, 1.00f, 0.25f, 250, 0.2);
                CL_RunParticleEffect (pos, vec3_origin, 20, 30);
                S_StartSound (-1, 0, cl_sfx_wizhit, pos, 1, 1);
                break;
@@ -1016,7 +1017,8 @@ void CL_ParseTempEntity (void)
        case TE_KNIGHTSPIKE:
                // spike hitting wall
                MSG_ReadVector(pos);
-               Mod_FindNonSolidLocation(pos, cl.worldmodel);
+               Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
+               CL_AllocDlight (NULL, pos, 50, 1.0f, 0.60f, 0.20f, 250, 0.2);
                CL_RunParticleEffect (pos, vec3_origin, 226, 20);
                S_StartSound (-1, 0, cl_sfx_knighthit, pos, 1, 1);
                break;
@@ -1024,7 +1026,7 @@ void CL_ParseTempEntity (void)
        case TE_SPIKE:
                // spike hitting wall
                MSG_ReadVector(pos);
-               Mod_FindNonSolidLocation(pos, cl.worldmodel);
+               Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
                // LordHavoc: changed to spark shower
                CL_SparkShower(pos, vec3_origin, 15);
                if ( rand() % 5 )
@@ -1043,7 +1045,7 @@ void CL_ParseTempEntity (void)
        case TE_SPIKEQUAD:
                // quad spike hitting wall
                MSG_ReadVector(pos);
-               Mod_FindNonSolidLocation(pos, cl.worldmodel);
+               Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
                // LordHavoc: changed to spark shower
                CL_SparkShower(pos, vec3_origin, 15);
                CL_AllocDlight (NULL, pos, 200, 0.1f, 0.1f, 1.0f, 1000, 0.2);
@@ -1064,7 +1066,7 @@ void CL_ParseTempEntity (void)
        case TE_SUPERSPIKE:
                // super spike hitting wall
                MSG_ReadVector(pos);
-               Mod_FindNonSolidLocation(pos, cl.worldmodel);
+               Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
                // LordHavoc: changed to dust shower
                CL_SparkShower(pos, vec3_origin, 30);
                if ( rand() % 5 )
@@ -1083,7 +1085,7 @@ void CL_ParseTempEntity (void)
        case TE_SUPERSPIKEQUAD:
                // quad super spike hitting wall
                MSG_ReadVector(pos);
-               Mod_FindNonSolidLocation(pos, cl.worldmodel);
+               Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
                // LordHavoc: changed to dust shower
                CL_SparkShower(pos, vec3_origin, 30);
                CL_AllocDlight (NULL, pos, 200, 0.1f, 0.1f, 1.0f, 1000, 0.2);
@@ -1104,6 +1106,7 @@ void CL_ParseTempEntity (void)
        case TE_BLOOD:
                // blood puff
                MSG_ReadVector(pos);
+               Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
                dir[0] = MSG_ReadChar ();
                dir[1] = MSG_ReadChar ();
                dir[2] = MSG_ReadChar ();
@@ -1113,21 +1116,22 @@ void CL_ParseTempEntity (void)
        case TE_BLOOD2:
                // blood puff
                MSG_ReadVector(pos);
+               Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
                CL_BloodPuff(pos, vec3_origin, 10);
                break;
        case TE_SPARK:
                // spark shower
                MSG_ReadVector(pos);
+               Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
                dir[0] = MSG_ReadChar ();
                dir[1] = MSG_ReadChar ();
                dir[2] = MSG_ReadChar ();
                count = MSG_ReadByte ();
-               Mod_FindNonSolidLocation(pos, cl.worldmodel);
                CL_SparkShower(pos, dir, count);
                break;
        case TE_PLASMABURN:
                MSG_ReadVector(pos);
-               Mod_FindNonSolidLocation(pos, cl.worldmodel);
+               Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
                CL_AllocDlight (NULL, pos, 200, 1, 1, 1, 1000, 0.2);
                CL_PlasmaBurn(pos);
                break;
@@ -1175,7 +1179,7 @@ void CL_ParseTempEntity (void)
        case TE_GUNSHOT:
                // bullet hitting wall
                MSG_ReadVector(pos);
-               Mod_FindNonSolidLocation(pos, cl.worldmodel);
+               Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
                // LordHavoc: changed to dust shower
                CL_SparkShower(pos, vec3_origin, 15);
                break;
@@ -1183,7 +1187,7 @@ void CL_ParseTempEntity (void)
        case TE_GUNSHOTQUAD:
                // quad bullet hitting wall
                MSG_ReadVector(pos);
-               Mod_FindNonSolidLocation(pos, cl.worldmodel);
+               Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
                CL_SparkShower(pos, vec3_origin, 15);
                CL_AllocDlight (NULL, pos, 200, 0.1f, 0.1f, 1.0f, 1000, 0.2);
                break;
@@ -1191,7 +1195,7 @@ void CL_ParseTempEntity (void)
        case TE_EXPLOSION:
                // rocket explosion
                MSG_ReadVector(pos);
-               Mod_FindNonSolidLocation(pos, cl.worldmodel);
+               Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 10);
                CL_ParticleExplosion (pos);
                // LordHavoc: boosted color from 1.0, 0.8, 0.4 to 1.25, 1.0, 0.5
                CL_AllocDlight (NULL, pos, 350, 1.25f, 1.0f, 0.5f, 700, 0.5);
@@ -1201,7 +1205,7 @@ void CL_ParseTempEntity (void)
        case TE_EXPLOSIONQUAD:
                // quad rocket explosion
                MSG_ReadVector(pos);
-               Mod_FindNonSolidLocation(pos, cl.worldmodel);
+               Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 10);
                CL_ParticleExplosion (pos);
                CL_AllocDlight (NULL, pos, 600, 0.5f, 0.4f, 1.0f, 1200, 0.5);
                S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
@@ -1210,7 +1214,7 @@ void CL_ParseTempEntity (void)
        case TE_EXPLOSION3:
                // Nehahra movie colored lighting explosion
                MSG_ReadVector(pos);
-               Mod_FindNonSolidLocation(pos, cl.worldmodel);
+               Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 10);
                CL_ParticleExplosion (pos);
                CL_AllocDlight (NULL, pos, 350, MSG_ReadCoord(), MSG_ReadCoord(), MSG_ReadCoord(), 700, 0.5);
                S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
@@ -1219,7 +1223,7 @@ void CL_ParseTempEntity (void)
        case TE_EXPLOSIONRGB:
                // colored lighting explosion
                MSG_ReadVector(pos);
-               Mod_FindNonSolidLocation(pos, cl.worldmodel);
+               Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 10);
                CL_ParticleExplosion (pos);
                color[0] = MSG_ReadByte() * (1.0 / 255.0);
                color[1] = MSG_ReadByte() * (1.0 / 255.0);
@@ -1231,7 +1235,7 @@ void CL_ParseTempEntity (void)
        case TE_TAREXPLOSION:
                // tarbaby explosion
                MSG_ReadVector(pos);
-               Mod_FindNonSolidLocation(pos, cl.worldmodel);
+               Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 10);
                CL_BlobExplosion (pos);
 
                S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
@@ -1241,13 +1245,13 @@ void CL_ParseTempEntity (void)
 
        case TE_SMALLFLASH:
                MSG_ReadVector(pos);
-               Mod_FindNonSolidLocation(pos, cl.worldmodel);
+               Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 10);
                CL_AllocDlight (NULL, pos, 200, 1, 1, 1, 1000, 0.2);
                break;
 
        case TE_CUSTOMFLASH:
                MSG_ReadVector(pos);
-               Mod_FindNonSolidLocation(pos, cl.worldmodel);
+               Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
                radius = MSG_ReadByte() * 8;
                velspeed = (MSG_ReadByte() + 1) * (1.0 / 256.0);
                color[0] = MSG_ReadByte() * (1.0 / 255.0);
@@ -1316,7 +1320,7 @@ void CL_ParseTempEntity (void)
        case TE_EXPLOSION2:
                // color mapped explosion
                MSG_ReadVector(pos);
-               Mod_FindNonSolidLocation(pos, cl.worldmodel);
+               Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 10);
                colorStart = MSG_ReadByte ();
                colorLength = MSG_ReadByte ();
                CL_ParticleExplosion2 (pos, colorStart, colorLength);
@@ -1337,13 +1341,13 @@ void CL_ParseTempEntity (void)
                MSG_ReadVector(pos);
                MSG_ReadVector(dir);
                count = MSG_ReadByte ();
-               Mod_FindNonSolidLocation(pos, cl.worldmodel);
+               Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
                CL_Tei_Smoke(pos, dir, count);
                break;
 
        case TE_TEI_BIGEXPLOSION:
                MSG_ReadVector(pos);
-               Mod_FindNonSolidLocation(pos, cl.worldmodel);
+               Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 10);
                CL_ParticleExplosion (pos);
                CL_AllocDlight (NULL, pos, 500, 1.25f, 1.0f, 0.5f, 500, 9999);
                S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
@@ -1353,7 +1357,7 @@ void CL_ParseTempEntity (void)
                MSG_ReadVector(pos);
                MSG_ReadVector(dir);
                count = MSG_ReadByte ();
-               Mod_FindNonSolidLocation(pos, cl.worldmodel);
+               Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 5);
                CL_Tei_PlasmaHit(pos, dir, count);
                CL_AllocDlight (NULL, pos, 500, 0.3, 0.6, 1.0f, 2000, 9999);
                break;
index 766b5fc..5e74ea4 100644 (file)
@@ -92,20 +92,181 @@ int Mod_PointContents (const vec3_t p, model_t *model)
        return ((mleaf_t *)node)->contents;
 }
 
-void Mod_FindNonSolidLocation(vec3_t pos, model_t *mod)
+typedef struct findnonsolidlocationinfo_s
 {
-       if (Mod_PointContents(pos, mod) != CONTENTS_SOLID) return;
-       pos[0]-=1;if (Mod_PointContents(pos, mod) != CONTENTS_SOLID) return;
-       pos[0]+=2;if (Mod_PointContents(pos, mod) != CONTENTS_SOLID) return;
-       pos[0]-=1;
-       pos[1]-=1;if (Mod_PointContents(pos, mod) != CONTENTS_SOLID) return;
-       pos[1]+=2;if (Mod_PointContents(pos, mod) != CONTENTS_SOLID) return;
-       pos[1]-=1;
-       pos[2]-=1;if (Mod_PointContents(pos, mod) != CONTENTS_SOLID) return;
-       pos[2]+=2;if (Mod_PointContents(pos, mod) != CONTENTS_SOLID) return;
-       pos[2]-=1;
+       vec3_t center;
+       vec_t radius;
+       vec3_t nudge;
+       vec_t bestdist;
+       model_t *model;
 }
+findnonsolidlocationinfo_t;
 
+#if 0
+extern cvar_t samelevel;
+#endif
+void Mod_FindNonSolidLocation_r_Leaf(findnonsolidlocationinfo_t *info, mleaf_t *leaf)
+{
+       int i, surfnum, k, *tri, *mark;
+       float dist, f, vert[3][3], edge[3][3], facenormal[3], edgenormal[3][3], point[3];
+#if 0
+       float surfnormal[3];
+#endif
+       msurface_t *surf;
+       surfmesh_t *mesh;
+       for (surfnum = 0, mark = leaf->firstmarksurface;surfnum < leaf->nummarksurfaces;surfnum++, mark++)
+       {
+               surf = info->model->surfaces + *mark;
+               if (surf->flags & SURF_SOLIDCLIP)
+               {
+#if 0
+                       VectorCopy(surf->plane->normal, surfnormal);
+                       if (surf->flags & SURF_PLANEBACK)
+                               VectorNegate(surfnormal, surfnormal);
+#endif
+                       for (mesh = surf->mesh;mesh;mesh = mesh->chain)
+                       {
+                               for (k = 0;k < mesh->numtriangles;k++)
+                               {
+                                       tri = mesh->index + k * 3;
+                                       VectorCopy((mesh->verts + tri[0] * 4), vert[0]);
+                                       VectorCopy((mesh->verts + tri[1] * 4), vert[1]);
+                                       VectorCopy((mesh->verts + tri[2] * 4), vert[2]);
+                                       VectorSubtract(vert[1], vert[0], edge[0]);
+                                       VectorSubtract(vert[2], vert[1], edge[1]);
+                                       CrossProduct(edge[1], edge[0], facenormal);
+                                       if (facenormal[0] || facenormal[1] || facenormal[2])
+                                       {
+                                               VectorNormalize(facenormal);
+#if 0
+                                               if (VectorDistance(facenormal, surfnormal) > 0.01f)
+                                                       Con_Printf("a2! %f %f %f != %f %f %f\n", facenormal[0], facenormal[1], facenormal[2], surfnormal[0], surfnormal[1], surfnormal[2]);
+#endif
+                                               f = DotProduct(info->center, facenormal) - DotProduct(vert[0], facenormal);
+                                               if (f <= info->bestdist && f >= -info->bestdist)
+                                               {
+                                                       VectorSubtract(vert[0], vert[2], edge[2]);
+                                                       VectorNormalize(edge[0]);
+                                                       VectorNormalize(edge[1]);
+                                                       VectorNormalize(edge[2]);
+                                                       CrossProduct(facenormal, edge[0], edgenormal[0]);
+                                                       CrossProduct(facenormal, edge[1], edgenormal[1]);
+                                                       CrossProduct(facenormal, edge[2], edgenormal[2]);
+#if 0
+                                                       if (samelevel.integer & 1)
+                                                               VectorNegate(edgenormal[0], edgenormal[0]);
+                                                       if (samelevel.integer & 2)
+                                                               VectorNegate(edgenormal[1], edgenormal[1]);
+                                                       if (samelevel.integer & 4)
+                                                               VectorNegate(edgenormal[2], edgenormal[2]);
+                                                       for (i = 0;i < 3;i++)
+                                                               if (DotProduct(vert[0], edgenormal[i]) > DotProduct(vert[i], edgenormal[i]) + 0.1f
+                                                                || DotProduct(vert[1], edgenormal[i]) > DotProduct(vert[i], edgenormal[i]) + 0.1f
+                                                                || DotProduct(vert[2], edgenormal[i]) > DotProduct(vert[i], edgenormal[i]) + 0.1f)
+                                                                       Con_Printf("a! %i : %f %f %f (%f %f %f)\n", i, edgenormal[i][0], edgenormal[i][1], edgenormal[i][2], facenormal[0], facenormal[1], facenormal[2]);
+#endif
+                                                       // face distance
+                                                       if (DotProduct(info->center, edgenormal[0]) < DotProduct(vert[0], edgenormal[0])
+                                                        && DotProduct(info->center, edgenormal[1]) < DotProduct(vert[1], edgenormal[1])
+                                                        && DotProduct(info->center, edgenormal[2]) < DotProduct(vert[2], edgenormal[2]))
+                                                       {
+                                                               // we got lucky, the center is within the face
+                                                               dist = DotProduct(info->center, facenormal) - DotProduct(vert[0], facenormal);
+                                                               if (dist < 0)
+                                                               {
+                                                                       dist = -dist;
+                                                                       if (info->bestdist > dist)
+                                                                       {
+                                                                               info->bestdist = dist;
+                                                                               VectorScale(facenormal, (info->radius - -dist), info->nudge);
+                                                                       }
+                                                               }
+                                                               else
+                                                               {
+                                                                       if (info->bestdist > dist)
+                                                                       {
+                                                                               info->bestdist = dist;
+                                                                               VectorScale(facenormal, (info->radius - dist), info->nudge);
+                                                                       }
+                                                               }
+                                                       }
+                                                       else
+                                                       {
+                                                               // check which edge or vertex the center is nearest
+                                                               for (i = 0;i < 3;i++)
+                                                               {
+                                                                       f = DotProduct(info->center, edge[i]);
+                                                                       if (f >= DotProduct(vert[0], edge[i])
+                                                                        && f <= DotProduct(vert[1], edge[i]))
+                                                                       {
+                                                                               // on edge
+                                                                               VectorMA(info->center, -f, edge[i], point);
+                                                                               dist = sqrt(DotProduct(point, point));
+                                                                               if (info->bestdist > dist)
+                                                                               {
+                                                                                       info->bestdist = dist;
+                                                                                       VectorScale(point, (info->radius / dist), info->nudge);
+                                                                               }
+                                                                               // skip both vertex checks
+                                                                               // (both are further away than this edge)
+                                                                               i++;
+                                                                       }
+                                                                       else
+                                                                       {
+                                                                               // not on edge, check first vertex of edge
+                                                                               VectorSubtract(info->center, vert[i], point);
+                                                                               dist = sqrt(DotProduct(point, point));
+                                                                               if (info->bestdist > dist)
+                                                                               {
+                                                                                       info->bestdist = dist;
+                                                                                       VectorScale(point, (info->radius / dist), info->nudge);
+                                                                               }
+                                                                       }
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+}
+
+void Mod_FindNonSolidLocation_r(findnonsolidlocationinfo_t *info, mnode_t *node)
+{
+       if (node->contents)
+       {
+               if (((mleaf_t *)node)->nummarksurfaces)
+                       Mod_FindNonSolidLocation_r_Leaf(info, (mleaf_t *)node);
+       }
+       else
+       {
+               float f = PlaneDiff(info->center, node->plane);
+               if (f >= -info->bestdist)
+                       Mod_FindNonSolidLocation_r(info, node->children[0]);
+               if (f <= info->bestdist)
+                       Mod_FindNonSolidLocation_r(info, node->children[1]);
+       }
+}
+
+void Mod_FindNonSolidLocation(vec3_t in, vec3_t out, model_t *model, float radius)
+{
+       int i;
+       findnonsolidlocationinfo_t info;
+       VectorCopy(in, info.center);
+       info.radius = radius;
+       info.model = model;
+       i = 0;
+       do
+       {
+               VectorClear(info.nudge);
+               info.bestdist = radius;
+               Mod_FindNonSolidLocation_r(&info, model->nodes + model->hulls[0].firstclipnode);
+               VectorAdd(info.center, info.nudge, info.center);
+       }
+       while(info.bestdist < radius && ++i < 10);
+       VectorCopy(info.center, out);
+}
 
 /*
 ===================
index 3ab9703..0f2ee07 100644 (file)
@@ -362,7 +362,7 @@ struct model_s;
 void Mod_LoadBrushModel (struct model_s *mod, void *buffer);
 void Mod_BrushInit(void);
 
-void Mod_FindNonSolidLocation(vec3_t pos, struct model_s *mod);
+void Mod_FindNonSolidLocation(vec3_t in, vec3_t out, struct model_s *mod, vec_t radius);
 mleaf_t *Mod_PointInLeaf (const float *p, struct model_s *model);
 int Mod_PointContents (const float *p, struct model_s *model);
 qbyte *Mod_LeafPVS (mleaf_t *leaf, struct model_s *model);