+ int i, j, k, index[3];
+ float transformed[3], blend1, blend2, blend, yaw, pitch, sinpitch;
+ q3dlightgrid_t *a, *s;
+ // FIXME: write this
+ if (!model->brushq3.num_lightgrid)
+ {
+ ambientcolor[0] += 128;
+ ambientcolor[1] += 128;
+ ambientcolor[2] += 128;
+ return;
+ }
+ Matrix4x4_Transform(&model->brushq3.num_lightgrid_indexfromworld, p, transformed);
+ //Matrix4x4_Print(&model->brushq3.num_lightgrid_indexfromworld);
+ //Con_Printf("%f %f %f transformed %f %f %f clamped ", p[0], p[1], p[2], transformed[0], transformed[1], transformed[2]);
+ transformed[0] = bound(0, transformed[0], model->brushq3.num_lightgrid_isize[0]);
+ transformed[1] = bound(0, transformed[1], model->brushq3.num_lightgrid_isize[1]);
+ transformed[2] = bound(0, transformed[2], model->brushq3.num_lightgrid_isize[2]);
+ index[0] = (int)floor(transformed[0]);
+ index[1] = (int)floor(transformed[1]);
+ index[2] = (int)floor(transformed[2]);
+ //Con_Printf("%f %f %f index %i %i %i:\n", transformed[0], transformed[1], transformed[2], index[0], index[1], index[2]);
+ // now lerp the values
+ VectorClear(diffusenormal);
+ a = &model->brushq3.data_lightgrid[(index[2] * model->brushq3.num_lightgrid_isize[1] + index[1]) * model->brushq3.num_lightgrid_isize[0] + index[0]];
+ for (k = 0;k < 2;k++)
+ {
+ blend1 = (k ? (transformed[2] - index[2]) : (1 - (transformed[2] - index[2])));
+ for (j = 0;j < 2;j++)
+ {
+ blend2 = blend1 * (j ? (transformed[1] - index[1]) : (1 - (transformed[1] - index[1])));
+ for (i = 0;i < 2;i++)
+ {
+ blend = blend2 * (i ? (transformed[0] - index[0]) : (1 - (transformed[0] - index[0])));
+ s = a + (k * model->brushq3.num_lightgrid_isize[1] + j) * model->brushq3.num_lightgrid_isize[0] + i;
+ VectorMA(ambientcolor, blend * (1.0f / 128.0f), s->ambientrgb, ambientcolor);
+ VectorMA(diffusecolor, blend * (1.0f / 128.0f), s->diffusergb, diffusecolor);
+ pitch = s->diffusepitch * M_PI / 128;
+ yaw = s->diffuseyaw * M_PI / 128;
+ sinpitch = sin(pitch);
+ diffusenormal[0] += blend * (cos(yaw) * sinpitch);
+ diffusenormal[1] += blend * (sin(yaw) * sinpitch);
+ diffusenormal[2] += blend * (cos(pitch));
+ //Con_Printf("blend %f: ambient %i %i %i, diffuse %i %i %i, diffusepitch %i diffuseyaw %i (%f %f, normal %f %f %f)\n", blend, s->ambientrgb[0], s->ambientrgb[1], s->ambientrgb[2], s->diffusergb[0], s->diffusergb[1], s->diffusergb[2], s->diffusepitch, s->diffuseyaw, pitch, yaw, (cos(yaw) * cospitch), (sin(yaw) * cospitch), (-sin(pitch)));
+ }
+ }
+ }
+ VectorNormalize(diffusenormal);
+ //Con_Printf("result: ambient %f %f %f diffuse %f %f %f diffusenormal %f %f %f\n", ambientcolor[0], ambientcolor[1], ambientcolor[2], diffusecolor[0], diffusecolor[1], diffusecolor[2], diffusenormal[0], diffusenormal[1], diffusenormal[2]);
+}
+
+static void Mod_Q3BSP_TraceLine_RecursiveBSPNode(trace_t *trace, q3mnode_t *node, const vec3_t start, const vec3_t end, vec_t startfrac, vec_t endfrac, const vec3_t linestart, const vec3_t lineend, int markframe)
+{
+ int i, startside, endside;
+ float dist1, dist2, midfrac, mid[3];
+ q3mleaf_t *leaf;
+ // note: all line fragments past first impact fraction are ignored
+ while (node->isnode)
+ {
+ // recurse down node sides
+ dist1 = PlaneDiff(start, node->plane);
+ dist2 = PlaneDiff(end, node->plane);
+ startside = dist1 < 0;
+ endside = dist2 < 0;
+ if (startside == endside)
+ {
+ // most of the time the line fragment is on one side of the plane
+ node = node->children[startside];
+ }
+ else
+ {
+ // take the near side first
+ if (startfrac < trace->fraction)
+ {
+ // line crosses node plane, split the line
+ midfrac = dist1 / (dist1 - dist2);
+ VectorLerp(linestart, midfrac, lineend, mid);
+ Mod_Q3BSP_TraceLine_RecursiveBSPNode(trace, node->children[startside], start, mid, startfrac, midfrac, linestart, lineend, markframe);
+ if (midfrac < trace->fraction)
+ Mod_Q3BSP_TraceLine_RecursiveBSPNode(trace, node->children[endside], mid, end, midfrac, endfrac, linestart, lineend, markframe);
+ }
+ return;
+ }
+ }
+ // hit a leaf
+ leaf = (q3mleaf_t *)node;
+ for (i = 0;i < leaf->numleafbrushes;i++)
+ {
+ if (endfrac >= trace->fraction)
+ return;
+ if (leaf->firstleafbrush[i]->colbrushf && leaf->firstleafbrush[i]->colbrushf->markframe != markframe)
+ {
+ leaf->firstleafbrush[i]->colbrushf->markframe = markframe;
+ Collision_TraceLineBrushFloat(trace, linestart, lineend, leaf->firstleafbrush[i]->colbrushf, leaf->firstleafbrush[i]->colbrushf);
+ }
+ }
+}
+
+static void Mod_Q3BSP_TraceBrush_RecursiveBSPNode(trace_t *trace, q3mnode_t *node, const colbrushf_t *thisbrush_start, const colbrushf_t *thisbrush_end, int markframe)
+{
+ int i;
+ float dist;
+ colpointf_t *ps, *pe;
+ q3mleaf_t *leaf;