From: havoc Date: Sun, 9 Mar 2003 11:19:57 +0000 (+0000) Subject: Mod_FindNonSolidLocation now takes a radius and can output to a different vector... X-Git-Tag: xonotic-v0.1.0preview~6731 X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=commitdiff_plain;h=f7c977317897310bddfd6f32e179a79e2c1caa14;ds=sidebyside Mod_FindNonSolidLocation now takes a radius and can output to a different vector than the input (purpose: the sphere is nudged out of any surfaces in the area, this makes realtime lighting look a lot better as the lights aren't too close to the surface) git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@2817 d7cf8633-e32d-0410-b094-e92efae38249 --- diff --git a/cl_parse.c b/cl_parse.c index fcf885ca..9863aa3c 100644 --- a/cl_parse.c +++ b/cl_parse.c @@ -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; diff --git a/model_brush.c b/model_brush.c index 766b5fcb..5e74ea4d 100644 --- a/model_brush.c +++ b/model_brush.c @@ -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); +} /* =================== diff --git a/model_brush.h b/model_brush.h index 3ab97037..0f2ee072 100644 --- a/model_brush.h +++ b/model_brush.h @@ -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);