summary refs log tree commit diff
path: root/src/Decals.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Decals.cpp')
-rw-r--r--src/Decals.cpp469
1 files changed, 126 insertions, 343 deletions
diff --git a/src/Decals.cpp b/src/Decals.cpp
index eb2a90b..510a557 100644
--- a/src/Decals.cpp
+++ b/src/Decals.cpp
@@ -1,363 +1,146 @@
+#include <algorithm>
 #include <cmath>
 
-#include "Camera.h"
-#include "Constants.h"
 #include "Decals.h"
-#include "misc.h"
 
-extern float multiplier;
-extern bool slomo;
-extern bool blood;
-extern float fogcolorr;
-extern float fogcolorg;
-extern float fogcolorb;
-//Functions
-extern float sinefluct;
-extern int environment;
-extern Model gunmodels[10];
-extern Camera camera;
-extern float precipitationhorz;
-extern float precipitationvert;
-extern float precipitationdensity;
-extern float snowdelay;
+#define NORMAL_OFFSET 0.02f
 
-int Decals::MakeDecal(int atype, XYZ location, float size, XYZ normal, int poly, Model *model, XYZ move, float rotation){
-	int major=0;
-	float normalv[3];
-	XYZ right;
-	XYZ up;
-	XYZ nothing;
-	XYZ axis[3];
-	XYZ temp;
-
-	nothing = {};
-
-	axis[0].x=1;
-	axis[1].y=1;
-	axis[2].z=1;
-
-	normalv[0]=abs(normal.x);
-	normalv[1]=abs(normal.y);
-	normalv[2]=abs(normal.z);
-
-	if(normalv[1]>normalv[major])major=1;
-	if(normalv[2]>normalv[major])major=2;
+enum corner { SW, SE, NE, NW };
 
-	if (normalv[0] == 1 || normalv[1] == 1 || normalv[2] == 1) {
-		if ((major == 0 && normal.x > 0) || major == 1)
-			right = {0.0f, 0.0f, -1.0f};
-		else if (major == 0)
-			right = {0.0f, 0.0f, 1.0f};
-		else if (major == 0)
-			right = {normal.z, 0.0f, 0.0f};
-	} else {
-		right = crossProduct(axis[major], normal);
+void bind(struct Decals *d, XYZ location, float size, XYZ normal,
+          int poly, Model *model, XYZ move, float rotation,
+          XYZ right, XYZ up, enum corner direction)
+{
+	float x, y;
+	switch (direction) {
+	case SW:
+		x = -1.0f;
+		y = -1.0f;
+		break;
+	case NW:
+		x = 1.0f;
+		y = -1.0f;
+		break;
+	case NE:
+		x = 1.0f;
+		y = 1.0f;
+		break;
+	case SE:
+		x = -1.0f;
+		y = 1.0f;
+		break;
 	}
 
-	up = normalize(crossProduct(normal, right));
-	right = normalize(right);
+	size_t i = d->len * 8 + d->numpoints[d->len];
+	d->points[i] = location + right * x + up * y;
+	d->texcoordsx[i] = x * 0.5f + 0.5f;
+	d->texcoordsy[i] = y * 0.5f + 0.5f;
 
-	float count;
-	float count2;
-	float countinc=1/size;
-	if(countinc<.01)countinc=.01;
-	if(countinc>.2)countinc=.2;
-	float normaloffset=.02;
-	int good;
-
-	numpoints[howmanydecals]=0;
-    points[howmanydecals*8+numpoints[howmanydecals]] = location + (nothing - right - up) * (size/3) /*+ normal/100*/;
-    texcoordsx[howmanydecals*8+numpoints[howmanydecals]] = 0;
-    texcoordsy[howmanydecals*8+numpoints[howmanydecals]] = 0;
-    if((move.x==0&&move.z==0&&rotation==0)||
-    LineFacetd(points[howmanydecals*8+numpoints[howmanydecals]]+normal/25,points[howmanydecals*8+numpoints[howmanydecals]]-normal/25, model->vertex[model->Triangles[poly].vertex[0]], model->vertex[model->Triangles[poly].vertex[1]], model->vertex[model->Triangles[poly].vertex[2]],normal,&temp)
-    )numpoints[howmanydecals]++;
-    else {
-    	good=-1;
-    	count=1-countinc;
-    	while(good==-1&&count>-1){
-    		texcoordsx[howmanydecals*8+numpoints[howmanydecals]] = 0;
-    		texcoordsy[howmanydecals*8+numpoints[howmanydecals]] = .5-count/2;
-    		points[howmanydecals*8+numpoints[howmanydecals]] = location + (nothing - right - up*count) * (size/3);
-    		count-=countinc;
-    		good=model->LineCheck2(points[howmanydecals*8+numpoints[howmanydecals]]+normal/25,points[howmanydecals*8+numpoints[howmanydecals]]-normal/25,&temp,move,rotation);
-    	}
-    	if(good!=-1)numpoints[howmanydecals]++;
-    	good=-1;
-    	count=1-countinc;
-    	while(good==-1&&count>-1){
-    		texcoordsx[howmanydecals*8+numpoints[howmanydecals]] = .5-count/2;
-    		texcoordsy[howmanydecals*8+numpoints[howmanydecals]] = 0;
-    		points[howmanydecals*8+numpoints[howmanydecals]] = location + (nothing - right*count - up) * (size/3);
-    		count-=countinc;
-    		good=model->LineCheck2(points[howmanydecals*8+numpoints[howmanydecals]]+normal/25,points[howmanydecals*8+numpoints[howmanydecals]]-normal/25,&temp,move,rotation);
-    	}
-    	if(good!=-1)numpoints[howmanydecals]++;
-    	if(good==-1){
-    		good=-1;
-	    	count2=1-countinc;
-	    	while(good==-1&&count2>-1){
-	    		count=1-countinc;
-		    	while(good==-1&&count>-1){
-		    		texcoordsx[howmanydecals*8+numpoints[howmanydecals]] = .5-count2/2;
-		    		texcoordsy[howmanydecals*8+numpoints[howmanydecals]] = .5-count/2;
-		    		points[howmanydecals*8+numpoints[howmanydecals]] = location + (nothing - right*count2 - up*count) * (size/3);
-		    		count-=countinc;
-		    		good=model->LineCheck2(points[howmanydecals*8+numpoints[howmanydecals]]+normal/25,points[howmanydecals*8+numpoints[howmanydecals]]-normal/25,&temp,move,rotation);
-		    	}
-		    	count2-=countinc;
-		    }
-	    	if(good!=-1)numpoints[howmanydecals]++;
-    	}
-    }
-
-    points[howmanydecals*8+numpoints[howmanydecals]] = location + (nothing + right - up) * (size/3) /*+ normal/100*/;
-    texcoordsx[howmanydecals*8+numpoints[howmanydecals]] = 1;
-    texcoordsy[howmanydecals*8+numpoints[howmanydecals]] = 0;
-    if((move.x==0&&move.y==0&&move.z==0&&rotation==0)||
-    LineFacetd(points[howmanydecals*8+numpoints[howmanydecals]]+normal/25,points[howmanydecals*8+numpoints[howmanydecals]]-normal/25, model->vertex[model->Triangles[poly].vertex[0]], model->vertex[model->Triangles[poly].vertex[1]], model->vertex[model->Triangles[poly].vertex[2]],normal,&temp)
-    )numpoints[howmanydecals]++;
-    else {
-    	good=-1;
-    	count=1-countinc;
-    	while(good==-1&&count>-1){
-    		texcoordsx[howmanydecals*8+numpoints[howmanydecals]] = .5+count/2;
-    		texcoordsy[howmanydecals*8+numpoints[howmanydecals]] = 0;
-    		points[howmanydecals*8+numpoints[howmanydecals]] = location + (nothing + right*count - up) * (size/3);
-    		count-=countinc;
-    		good=model->LineCheck2(points[howmanydecals*8+numpoints[howmanydecals]]+normal/25,points[howmanydecals*8+numpoints[howmanydecals]]-normal/25,&temp,move,rotation);
-    	}
-    	if(good!=-1)numpoints[howmanydecals]++;
-    	good=-1;
-    	count=1-countinc;
-    	while(good==-1&&count>-1){
-    		texcoordsx[howmanydecals*8+numpoints[howmanydecals]] = 1;
-    		texcoordsy[howmanydecals*8+numpoints[howmanydecals]] = .5-count/2;
-    		points[howmanydecals*8+numpoints[howmanydecals]] = location + (nothing + right - up*count) * (size/3);
-    		count-=countinc;
-    		good=model->LineCheck2(points[howmanydecals*8+numpoints[howmanydecals]]+normal/25,points[howmanydecals*8+numpoints[howmanydecals]]-normal/25,&temp,move,rotation);
-    	}
-    	if(good!=-1)numpoints[howmanydecals]++;
-    	if(good==-1){
-    		good=-1;
-	    	count2=1-countinc;
-	    	while(good==-1&&count2>-1){
-	    		count=1-countinc;
-		    	while(good==-1&&count>-1){
-		    		texcoordsx[howmanydecals*8+numpoints[howmanydecals]] = .5+count2/2;
-		    		texcoordsy[howmanydecals*8+numpoints[howmanydecals]] = .5-count/2;
-		    		points[howmanydecals*8+numpoints[howmanydecals]] = location + (nothing + right*count2 - up*count) * (size/3);
-		    		count-=countinc;
-		    		good=model->LineCheck2(points[howmanydecals*8+numpoints[howmanydecals]]+normal/25,points[howmanydecals*8+numpoints[howmanydecals]]-normal/25,&temp,move,rotation);
-		    	}
-		    	count2-=countinc;
-		    }
-	    	if(good!=-1)numpoints[howmanydecals]++;
-    	}
-    }
-
-    points[howmanydecals*8+numpoints[howmanydecals]] = location + (nothing + right + up) * (size/3) /*+ normal/100*/;
-    texcoordsx[howmanydecals*8+numpoints[howmanydecals]] = 1;
-    texcoordsy[howmanydecals*8+numpoints[howmanydecals]] = 1;
-    if((move.x==0&&move.y==0&&move.z==0&&rotation==0)||
-    LineFacetd(points[howmanydecals*8+numpoints[howmanydecals]]+normal/25,points[howmanydecals*8+numpoints[howmanydecals]]-normal/25, model->vertex[model->Triangles[poly].vertex[0]], model->vertex[model->Triangles[poly].vertex[1]], model->vertex[model->Triangles[poly].vertex[2]],normal,&temp)
-    )numpoints[howmanydecals]++;
-    else {
-    	good=-1;
-    	count=1-countinc;
-    	while(good==-1&&count>-1){
-    		texcoordsx[howmanydecals*8+numpoints[howmanydecals]] = 1;
-    		texcoordsy[howmanydecals*8+numpoints[howmanydecals]] = .5+count/2;
-    		points[howmanydecals*8+numpoints[howmanydecals]] = location + (nothing + right + up*count) * (size/3);
-    		count-=countinc;
-    		good=model->LineCheck2(points[howmanydecals*8+numpoints[howmanydecals]]+normal/25,points[howmanydecals*8+numpoints[howmanydecals]]-normal/25,&temp,move,rotation);
-    	}
-    	if(good!=-1)numpoints[howmanydecals]++;
-    	good=-1;
-    	count=1-countinc;
-    	while(good==-1&&count>-1){
-    		texcoordsx[howmanydecals*8+numpoints[howmanydecals]] = .5+count/2;
-    		texcoordsy[howmanydecals*8+numpoints[howmanydecals]] = 1;
-    		points[howmanydecals*8+numpoints[howmanydecals]] = location + (nothing + right*count + up) * (size/3);
-    		count-=countinc;
-    		good=model->LineCheck2(points[howmanydecals*8+numpoints[howmanydecals]]+normal/25,points[howmanydecals*8+numpoints[howmanydecals]]-normal/25,&temp,move,rotation);
-    	}
-    	if(good!=-1)numpoints[howmanydecals]++;
-    	if(good==-1){
-    		good=-1;
-	    	count2=1-countinc;
-	    	while(good==-1&&count2>-1){
-	    		count=1-countinc;
-		    	while(good==-1&&count>-1){
-		    		texcoordsx[howmanydecals*8+numpoints[howmanydecals]] = .5+count2/2;
-		    		texcoordsy[howmanydecals*8+numpoints[howmanydecals]] = .5+count/2;
-		    		points[howmanydecals*8+numpoints[howmanydecals]] = location + (nothing + right*count2 + up*count) * (size/3);
-		    		count-=countinc;
-		    		good=model->LineCheck2(points[howmanydecals*8+numpoints[howmanydecals]]+normal/25,points[howmanydecals*8+numpoints[howmanydecals]]-normal/25,&temp,move,rotation);
-		    	}
-		    	count2-=countinc;
-		    }
-	    	if(good!=-1)numpoints[howmanydecals]++;
-    	}
-    }
-
-    points[howmanydecals*8+numpoints[howmanydecals]] = location + (nothing - right + up) * (size/3) /*+ normal/100*/;
-	texcoordsx[howmanydecals*8+numpoints[howmanydecals]] = 0;
-    texcoordsy[howmanydecals*8+numpoints[howmanydecals]] = 1;
-    if((move.x==0&&move.y==0&&move.z==0&&rotation==0)||
-    LineFacetd(points[howmanydecals*8+numpoints[howmanydecals]]+normal/25,points[howmanydecals*8+numpoints[howmanydecals]]-normal/25, model->vertex[model->Triangles[poly].vertex[0]], model->vertex[model->Triangles[poly].vertex[1]], model->vertex[model->Triangles[poly].vertex[2]],normal,&temp)
-    )numpoints[howmanydecals]++;
-    else {
-    	good=-1;
-    	count=1-countinc;
-    	while(good==-1&&count>-1){
-    		texcoordsx[howmanydecals*8+numpoints[howmanydecals]] = .5-count/2;
-    		texcoordsy[howmanydecals*8+numpoints[howmanydecals]] = 1;
-    		points[howmanydecals*8+numpoints[howmanydecals]] = location + (nothing - right*count + up) * (size/3);
-    		count-=countinc;
-    		good=model->LineCheck2(points[howmanydecals*8+numpoints[howmanydecals]]+normal/25,points[howmanydecals*8+numpoints[howmanydecals]]-normal/25,&temp,move,rotation);
-    	}
-    	if(good!=-1)numpoints[howmanydecals]++;
-    	good=-1;
-    	count=1-countinc;
-    	while(good==-1&&count>-1){
-    		texcoordsx[howmanydecals*8+numpoints[howmanydecals]] = 0;
-    		texcoordsy[howmanydecals*8+numpoints[howmanydecals]] = .5+count/2;
-    		points[howmanydecals*8+numpoints[howmanydecals]] = location + (nothing - right + up*count) * (size/3);
-    		count-=countinc;
-    		good=model->LineCheck2(points[howmanydecals*8+numpoints[howmanydecals]]+normal/25,points[howmanydecals*8+numpoints[howmanydecals]]-normal/25,&temp,move,rotation);
-    	}
-    	if(good!=-1)numpoints[howmanydecals]++;
-    	if(good==-1){
-    		good=-1;
-	    	count2=1-countinc;
-	    	while(good==-1&&count2>-1){
-	    		count=1-countinc;
-		    	while(good==-1&&count>-1){
-		    		texcoordsx[howmanydecals*8+numpoints[howmanydecals]] = .5-count2/2;
-		    		texcoordsy[howmanydecals*8+numpoints[howmanydecals]] = .5+count/2;
-		    		points[howmanydecals*8+numpoints[howmanydecals]] = location + (nothing - right*count2 + up*count) * (size/3);
-		    		count-=countinc;
-		    		good=model->LineCheck2(points[howmanydecals*8+numpoints[howmanydecals]]+normal/25,points[howmanydecals*8+numpoints[howmanydecals]]-normal/25,&temp,move,rotation);
-		    	}
-		    	count2-=countinc;
-		    }
-	    	if(good!=-1)numpoints[howmanydecals]++;
-    	}
-    }
-    for(int i=0;i<numpoints[howmanydecals];i++){
-    	 points[howmanydecals*8+i] += normal*normaloffset;
-    }
-
-    type[howmanydecals]=atype;
-	alivetime[howmanydecals]=0;
-	if(howmanydecals<maxdecals){howmanydecals++;}
-
-	return 0;
-}
-
-int Decals::DeleteDecal(int which){
-	if(which>=0){
-		numpoints[which]=numpoints[howmanydecals-1];
-		alivetime[which]=alivetime[howmanydecals-1];
-		type[which]=type[howmanydecals-1];
-		for(int i=0;i<numpoints[which];i++){
-			points[which*8+i] = points[howmanydecals*8-8+i];
-		    texcoordsx[which*8+i] = texcoordsx[howmanydecals*8-8+i];
-		    texcoordsy[which*8+i] = texcoordsy[howmanydecals*8-8+i];
-	    }
-		if(howmanydecals>0){howmanydecals--;}
+	XYZ temp;
+	if ((move.x == 0 && move.y == 0 && move.z == 0 && rotation == 0)
+	    || segCrossTrigon(d->points[i] + normal / 25,
+	                      d->points[i] - normal / 25,
+	                      model->vertex + model->Triangles[poly].vertex[0],
+	                      model->vertex + model->Triangles[poly].vertex[1],
+	                      model->vertex + model->Triangles[poly].vertex[2],
+	                      &normal, &temp)) {
+		d->numpoints[d->len]++;
+		return;
 	}
 
-	return 0;
-}
-
-void Decals::DoStuff()
-{
-	for(int i=0;i<howmanydecals;i++){
-		alivetime[i]+=multiplier;
-		if(alivetime[i]>10&&(type[i]==bullethole||type[i]==crater))DeleteDecal(i);
-		if(alivetime[i]>20&&(type[i]==bloodpool))DeleteDecal(i);
+	const auto n = normal / 25.0f;
+	const float countinc = std::max(0.01f, std::min(1.0f / size, 0.2f));
+	int good = -1;
+	float count = 1.0f - countinc;
+	while (good == -1 && count > -1.0f) {
+		d->texcoordsx[i] = x * 0.5f + 0.5f;
+		d->texcoordsy[i] = y * count * 0.5f + 0.5f;
+		d->points[i] = location + right * x + up * (y * count);
+		count -= countinc;
+		good = model->LineCheck2(d->points[i] + n,
+		                         d->points[i] - n,
+		                         &temp, move, rotation);
+	}
+	if (good > -1) {
+		d->numpoints[d->len]++;
+		i++;
 	}
-}
-
-void Decals::draw()
-{
-	glAlphaFunc(GL_GREATER, 0.01);
-
-	float bloodpoolspeed=1;
-
-	glDepthFunc(GL_LEQUAL);
-	glEnable(GL_BLEND);
-	glEnable(GL_CULL_FACE);
-	glEnable(GL_TEXTURE_2D);
-	glEnable(GL_LIGHTING);
-	glDepthMask(0);
-	glAlphaFunc(GL_GREATER, 0.01);
-	glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
-	glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
-	glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
-	glEnable(GL_POLYGON_OFFSET_FILL);
-	for(int i=0;i<howmanydecals;i++){
-		if(type[i]==bullethole)glBindTexture(GL_TEXTURE_2D, bulletholetextureptr);
-		if(type[i]==crater)glBindTexture(GL_TEXTURE_2D, cratertextureptr);
-		if(type[i]!=bloodpool)glColor4f(1,1,1,10-alivetime[i]);
-
-		if(type[i]==bloodpool&&alivetime[i]<bloodpoolspeed*.2)glBindTexture(GL_TEXTURE_2D, bloodtextureptr[0]);
-		if(type[i]==bloodpool&&alivetime[i]>=bloodpoolspeed*.2&&alivetime[i]<bloodpoolspeed*.4)glBindTexture(GL_TEXTURE_2D, bloodtextureptr[1]);
-		if(type[i]==bloodpool&&alivetime[i]>=bloodpoolspeed*.4&&alivetime[i]<bloodpoolspeed*.6)glBindTexture(GL_TEXTURE_2D, bloodtextureptr[2]);
-		if(type[i]==bloodpool&&alivetime[i]>=bloodpoolspeed*.6&&alivetime[i]<bloodpoolspeed*.8)glBindTexture(GL_TEXTURE_2D, bloodtextureptr[3]);
-		if(type[i]==bloodpool&&alivetime[i]>=bloodpoolspeed*.8&&alivetime[i]<bloodpoolspeed*1)glBindTexture(GL_TEXTURE_2D, bloodtextureptr[4]);
-		if(type[i]==bloodpool&&alivetime[i]>=bloodpoolspeed*1&&alivetime[i]<bloodpoolspeed*1.2)glBindTexture(GL_TEXTURE_2D, bloodtextureptr[5]);
-		if(type[i]==bloodpool&&alivetime[i]>=bloodpoolspeed*1.2&&alivetime[i]<bloodpoolspeed*1.4)glBindTexture(GL_TEXTURE_2D, bloodtextureptr[6]);
-		if(type[i]==bloodpool&&alivetime[i]>=bloodpoolspeed*1.4&&alivetime[i]<bloodpoolspeed*1.6)glBindTexture(GL_TEXTURE_2D, bloodtextureptr[7]);
-		if(type[i]==bloodpool&&alivetime[i]>=bloodpoolspeed*1.6&&alivetime[i]<bloodpoolspeed*1.8)glBindTexture(GL_TEXTURE_2D, bloodtextureptr[8]);
-		if(type[i]==bloodpool&&alivetime[i]>=bloodpoolspeed*1.8&&alivetime[i]<bloodpoolspeed*2.0)glBindTexture(GL_TEXTURE_2D, bloodtextureptr[9]);
-		if(type[i]==bloodpool&&alivetime[i]>=bloodpoolspeed*2.0)glBindTexture(GL_TEXTURE_2D, bloodtextureptr[10]);
-		if(type[i]==bloodpool&&alivetime[i]<bloodpoolspeed*2.0)glColor4f(1,1,1,1.5-(alivetime[i]*5/bloodpoolspeed-(int)(alivetime[i]*5/bloodpoolspeed)));
-		if(type[i]==bloodpool&&alivetime[i]>=bloodpoolspeed*2.0)glColor4f(1,1,1,20-alivetime[i]);
-
-		glPushMatrix();
-		glBegin(GL_TRIANGLE_FAN);
-			for(int j=0;j<numpoints[i];j++){
-			 glTexCoord2f(texcoordsx[i*8+j], texcoordsy[i*8+j]); glVertex3f(points[i*8+j].x,points[i*8+j].y,points[i*8+j].z);
-			}
-		glEnd();
-		glPopMatrix();
 
-		if(type[i]==bloodpool&&alivetime[i]<bloodpoolspeed*2.0){
-			if(type[i]==bloodpool&&alivetime[i]<bloodpoolspeed*.2)glBindTexture(GL_TEXTURE_2D, bloodtextureptr[1]);
-		if(type[i]==bloodpool&&alivetime[i]>=bloodpoolspeed*.2&&alivetime[i]<bloodpoolspeed*.4)glBindTexture(GL_TEXTURE_2D, bloodtextureptr[2]);
-		if(type[i]==bloodpool&&alivetime[i]>=bloodpoolspeed*.4&&alivetime[i]<bloodpoolspeed*.6)glBindTexture(GL_TEXTURE_2D, bloodtextureptr[3]);
-		if(type[i]==bloodpool&&alivetime[i]>=bloodpoolspeed*.6&&alivetime[i]<bloodpoolspeed*.8)glBindTexture(GL_TEXTURE_2D, bloodtextureptr[4]);
-		if(type[i]==bloodpool&&alivetime[i]>=bloodpoolspeed*.8&&alivetime[i]<bloodpoolspeed*1)glBindTexture(GL_TEXTURE_2D, bloodtextureptr[5]);
-		if(type[i]==bloodpool&&alivetime[i]>=bloodpoolspeed*1&&alivetime[i]<bloodpoolspeed*1.2)glBindTexture(GL_TEXTURE_2D, bloodtextureptr[6]);
-		if(type[i]==bloodpool&&alivetime[i]>=bloodpoolspeed*1.2&&alivetime[i]<bloodpoolspeed*1.4)glBindTexture(GL_TEXTURE_2D, bloodtextureptr[7]);
-		if(type[i]==bloodpool&&alivetime[i]>=bloodpoolspeed*1.4&&alivetime[i]<bloodpoolspeed*1.6)glBindTexture(GL_TEXTURE_2D, bloodtextureptr[8]);
-		if(type[i]==bloodpool&&alivetime[i]>=bloodpoolspeed*1.6&&alivetime[i]<bloodpoolspeed*1.8)glBindTexture(GL_TEXTURE_2D, bloodtextureptr[9]);
-		if(type[i]==bloodpool&&alivetime[i]>=bloodpoolspeed*1.8&&alivetime[i]<bloodpoolspeed*2.0)glBindTexture(GL_TEXTURE_2D, bloodtextureptr[10]);
-		if(type[i]==bloodpool)glColor4f(1,1,1,alivetime[i]*5/bloodpoolspeed-(int)(alivetime[i]*5/bloodpoolspeed));
+	good = -1;
+	count = 1.0f - countinc;
+	while (good == -1 && count > -1.0f) {
+		d->texcoordsx[i] = x * count * 0.5f + 0.5f;
+		d->texcoordsy[i] = y * 0.5f + 0.5f;
+		d->points[i] = location + right * (x * count) + up * y;
+		count -= countinc;
+		good = model->LineCheck2(d->points[i] + n,
+		                         d->points[i] - n,
+		                         &temp, move, rotation);
+	}
+	if (good > -1) {
+		d->numpoints[d->len]++;
+		return;
+	}
 
-			glPushMatrix();
-			glBegin(GL_TRIANGLE_FAN);
-				for(int j=0;j<numpoints[i];j++){
-				 glTexCoord2f(texcoordsx[i*8+j], texcoordsy[i*8+j]); glVertex3f(points[i*8+j].x,points[i*8+j].y,points[i*8+j].z);
-				}
-			glEnd();
-			glPopMatrix();
+	float count2 = 1.0f - countinc;
+	while (good == -1 && count2 > -1.0f){
+		count = 1.0f - countinc;
+		while (good == -1 && count > -1.0f) {
+			d->texcoordsx[i] = x * count2 * 0.5f + 0.5f;
+			d->texcoordsy[i] = y * count * 0.5f + 0.5f;
+			d->points[i] = location + right * (x * count2) + up * (y * count);
+			count -= countinc;
+			good = model->LineCheck2(d->points[i] + n,
+			                         d->points[i] - n,
+			                         &temp, move, rotation);
 		}
+		count2 -= countinc;
 	}
-	glDepthMask(1);
-	glDisable(GL_TEXTURE_2D);
-	glColor4f(1,1,1,1);
-	glEnable(GL_CULL_FACE);
-	glDisable(GL_POLYGON_OFFSET_FILL);
-	glDepthFunc(GL_LEQUAL);
+	if (good > -1)
+		d->numpoints[d->len]++;
 }
 
-Decals::~Decals()
+void addDecal(struct Decals *d, enum decal kind, XYZ location, float size,
+              XYZ normal, int poly, Model *model, XYZ move, float rotation)
 {
-	const GLuint holes[] {bulletholetextureptr, cratertextureptr};
-	glDeleteTextures(2, holes);
-	glDeleteTextures(11, bloodtextureptr);
+	if (d->len >= MAX_DECALS)
+		return;
+	d->kind[d->len] = kind;
+	d->alive[d->len] = 0;
+
+	float normalv[] = {abs(normal.x), abs(normal.y), abs(normal.z)};
+	unsigned char major = 0;
+	if (normalv[1] > normalv[major])
+		major = 1;
+	if (normalv[2] > normalv[major])
+		major = 2;
+
+	XYZ right = {0.0f};
+	if (normalv[0] == 1.0f || normalv[1] == 1.0f || normalv[2] == 1.0f) {
+		if ((major == 0 && normal.x > 0) || major == 1)
+			right.z = -1.0f;
+		else if (major == 0)
+			right.z = 1.0f;
+		else
+			right.x = normal.z;
+	} else {
+		XYZ axis = {0.0f};
+		((float *) &axis)[major] = 1.0f;
+		right = crossProduct(axis, normal);
+	}
+
+	d->numpoints[d->len] = 0;
+	XYZ up = normalize(crossProduct(normal, right)) * (size / 3);
+	right = normalize(right) * (size / 3);
+	bind(d, location, size, normal, poly, model,
+	     move, rotation, right, up, SW);
+	bind(d, location, size, normal, poly, model,
+	     move, rotation, right, up, NW);
+	bind(d, location, size, normal, poly, model,
+	     move, rotation, right, up, NE);
+	bind(d, location, size, normal, poly, model,
+	     move, rotation, right, up, SE);
+	for (int i = 0; i < d->numpoints[d->len]; ++i)
+		d->points[d->len * 8 + i] += normal * NORMAL_OFFSET;
+	d->len++;
 }