This commit is contained in:
2023-11-15 13:44:50 +03:00
parent 8a5aa0ad6c
commit 89d0230c80
13 changed files with 1307 additions and 0 deletions

View File

@@ -0,0 +1,179 @@
//////////////////////////////////////////////////////////////////////////////////////////
// CUBE_GRID.cpp
// function definitions for grid of cubes for "marching cubes" algorithm
// Downloaded from: www.paulsprojects.net
// Created: 20th July 2002
//
// Copyright (c) 2006, Paul Baker
// Distributed under the New BSD Licence. (See accompanying file License.txt or copy at
// http://www.paulsprojects.net/NewBSDLicense.txt)
//////////////////////////////////////////////////////////////////////////////////////////
#include "cbase.h"
#include "CUBE_GRID.h"
#include "cbase.h"
ConVar cl_blobs_resolution_max("cl_blobs_resolution_max", "20", FCVAR_CLIENTDLL);
bool CUBE_GRID::CreateMemory()
{
vertices=new CUBE_GRID_VERTEX[(cl_blobs_resolution_max.GetInt() + 1) * (cl_blobs_resolution_max.GetInt() + 1) * (cl_blobs_resolution_max.GetInt() + 1)];
if(!vertices)
{
Msg("Unable to allocate memory for %d Grid Vertices", numVertices);
return false;
}
cubes=new CUBE_GRID_CUBE[cl_blobs_resolution_max.GetInt() * cl_blobs_resolution_max.GetInt() * cl_blobs_resolution_max.GetInt()];
if(!cubes)
{
Msg("Unable to allocate memory for %d Grid Cubes", numCubes);
return false;
}
return true;
}
bool CUBE_GRID::Init(int gridSize, Vector Pos, Vector Bounds)
{
//VERTICES
numVertices=(gridSize+1)*(gridSize+1)*(gridSize+1);
int currentVertex=0;
for(int i=0; i<gridSize+1; i++)
{
for(int j=0; j<gridSize+1; j++)
{
for(int k=0; k<gridSize+1; k++)
{
vertices[currentVertex].position.x = ((Bounds.x / gridSize * i)) + Pos.x;
vertices[currentVertex].position.y = ((Bounds.y / gridSize * j)) + Pos.y;
vertices[currentVertex].position.z = ((Bounds.z / gridSize * k)) + Pos.z;
currentVertex++;
}
}
}
//CUBES
numCubes=(gridSize)*(gridSize)*(gridSize);
int currentCube=0;
for(int i=0; i<gridSize; i++)
{
for(int j=0; j<gridSize; j++)
{
for(int k=0; k<gridSize; k++)
{
cubes[currentCube].vertices[0]=&vertices[(i*(gridSize+1)+j)*(gridSize+1)+k];
cubes[currentCube].vertices[1]=&vertices[(i*(gridSize+1)+j)*(gridSize+1)+k+1];
cubes[currentCube].vertices[2]=&vertices[(i*(gridSize+1)+(j+1))*(gridSize+1)+k+1];
cubes[currentCube].vertices[3]=&vertices[(i*(gridSize+1)+(j+1))*(gridSize+1)+k];
cubes[currentCube].vertices[4]=&vertices[((i+1)*(gridSize+1)+j)*(gridSize+1)+k];
cubes[currentCube].vertices[5]=&vertices[((i+1)*(gridSize+1)+j)*(gridSize+1)+k+1];
cubes[currentCube].vertices[6]=&vertices[((i+1)*(gridSize+1)+(j+1))*(gridSize+1)+k+1];
cubes[currentCube].vertices[7]=&vertices[((i+1)*(gridSize+1)+(j+1))*(gridSize+1)+k];
currentCube++;
}
}
}
return true;
}
void CUBE_GRID::DrawSurface(float threshold)
{
/*
numFacesDrawn=0;
static SURFACE_VERTEX edgeVertices[12];
glBegin(GL_TRIANGLES);
{
//loop through cubes
for(int i=0; i<numCubes; i++)
{
//calculate which vertices are inside the surface
unsigned char cubeIndex=0;
if(cubes[i].vertices[0]->value < threshold)
cubeIndex |= 1;
if(cubes[i].vertices[1]->value < threshold)
cubeIndex |= 2;
if(cubes[i].vertices[2]->value < threshold)
cubeIndex |= 4;
if(cubes[i].vertices[3]->value < threshold)
cubeIndex |= 8;
if(cubes[i].vertices[4]->value < threshold)
cubeIndex |= 16;
if(cubes[i].vertices[5]->value < threshold)
cubeIndex |= 32;
if(cubes[i].vertices[6]->value < threshold)
cubeIndex |= 64;
if(cubes[i].vertices[7]->value < threshold)
cubeIndex |= 128;
//look this value up in the edge table to see which edges to interpolate along
int usedEdges=edgeTable[cubeIndex];
//if the cube is entirely within/outside surface, no faces
if(usedEdges==0 || usedEdges==255)
continue;
//update these edges
for(int currentEdge=0; currentEdge<12; currentEdge++)
{
if(usedEdges & 1<<currentEdge)
{
CUBE_GRID_VERTEX * v1=cubes[i].vertices[verticesAtEndsOfEdges[currentEdge*2 ]];
CUBE_GRID_VERTEX * v2=cubes[i].vertices[verticesAtEndsOfEdges[currentEdge*2+1]];
float delta=(threshold - v1->value)/(v2->value - v1->value);
//edgeVertices[currentEdge].position=v1->position + delta*(v2->position - v1->position);
edgeVertices[currentEdge].position.x=v1->position.x + delta*(v2->position.x - v1->position.x);
edgeVertices[currentEdge].position.y=v1->position.y + delta*(v2->position.y - v1->position.y);
edgeVertices[currentEdge].position.z=v1->position.z + delta*(v2->position.z - v1->position.z);
//edgeVertices[currentEdge].normal=v1->normal + delta*(v2->normal - v1->normal);
edgeVertices[currentEdge].normal.x=v1->normal.x + delta*(v2->normal.x - v1->normal.x);
edgeVertices[currentEdge].normal.y=v1->normal.y + delta*(v2->normal.y - v1->normal.y);
edgeVertices[currentEdge].normal.z=v1->normal.z + delta*(v2->normal.z - v1->normal.z);
}
}
//send the vertices
for(int k=0; triTable[cubeIndex][k]!=-1; k+=3)
{
glNormal3fv(edgeVertices[triTable[cubeIndex][k+0]].normal);
glVertex3fv(edgeVertices[triTable[cubeIndex][k+0]].position);
glNormal3fv(edgeVertices[triTable[cubeIndex][k+2]].normal);
glVertex3fv(edgeVertices[triTable[cubeIndex][k+2]].position);
glNormal3fv(edgeVertices[triTable[cubeIndex][k+1]].normal);
glVertex3fv(edgeVertices[triTable[cubeIndex][k+1]].position);
numFacesDrawn++;
}
}
}
glEnd();
*/
}
void CUBE_GRID::FreeMemory()
{
if(vertices)
delete [] vertices;
vertices=NULL;
numVertices=0;
if(cubes)
delete [] cubes;
cubes=NULL;
numCubes=0;
}

View File

@@ -0,0 +1,372 @@
//////////////////////////////////////////////////////////////////////////////////////////
// CUBE_GRID.h
// Class declaration for grid of cubes for "marching cubes" algorithm
// Downloaded from: www.paulsprojects.net
// Created: 20th July 2002
//
// Copyright (c) 2006, Paul Baker
// Distributed under the New BSD Licence. (See accompanying file License.txt or copy at
// http://www.paulsprojects.net/NewBSDLicense.txt)
//////////////////////////////////////////////////////////////////////////////////////////
#ifndef C_CUBE_GRID_H
#define C_CUBE_GRID_H
//wee need it to calc
#include "cbase.h"
class CUBE_GRID_VERTEX
{
public:
Vector position;
float value; //the value of the scalar field at this point
Vector normal;
};
//vertex from linear interpolation along edge
class SURFACE_VERTEX
{
public:
Vector position;
Vector normal;
};
class CUBE_GRID_CUBE
{
public:
CUBE_GRID_VERTEX * vertices[8]; //pointers to vertices
};
class CUBE_GRID
{
public:
int numVertices;
CUBE_GRID_VERTEX * vertices;
int numCubes;
CUBE_GRID_CUBE * cubes;
int numFacesDrawn;
bool CreateMemory();
bool Init(int gridSize, Vector Pos, Vector Bounds);
void DrawSurface(float threshold);
void FreeMemory();
CUBE_GRID() : numVertices(0), vertices(NULL), numCubes(0), cubes(NULL),
numFacesDrawn(0)
{}
~CUBE_GRID()
{ FreeMemory(); }
};
//gives the vertices at the end of each edge
static const uint8_t verticesAtEndsOfEdges[24]=
{ 0, 1,
1, 2,
2, 3,
3, 0,
4, 5,
5, 6,
6, 7,
7, 4,
0, 4,
1, 5,
2, 6,
3, 7};
//gives the edges to interpolate along given vertex inside/outside
static const int edgeTable[256]={
0x0 , 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c,
0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00,
0x190, 0x99 , 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c,
0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90,
0x230, 0x339, 0x33 , 0x13a, 0x636, 0x73f, 0x435, 0x53c,
0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30,
0x3a0, 0x2a9, 0x1a3, 0xaa , 0x7a6, 0x6af, 0x5a5, 0x4ac,
0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0,
0x460, 0x569, 0x663, 0x76a, 0x66 , 0x16f, 0x265, 0x36c,
0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60,
0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0xff , 0x3f5, 0x2fc,
0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0,
0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x55 , 0x15c,
0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950,
0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0xcc ,
0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0,
0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc,
0xcc , 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0,
0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c,
0x15c, 0x55 , 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650,
0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc,
0x2fc, 0x3f5, 0xff , 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0,
0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c,
0x36c, 0x265, 0x16f, 0x66 , 0x76a, 0x663, 0x569, 0x460,
0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac,
0x4ac, 0x5a5, 0x6af, 0x7a6, 0xaa , 0x1a3, 0x2a9, 0x3a0,
0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c,
0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x33 , 0x339, 0x230,
0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c,
0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x99 , 0x190,
0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c,
0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x0 };
//gives which vertices to join to form triangles for the surface
static const int triTable[256][16] =
{{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{1, 8, 3, 9, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{0, 8, 3, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{9, 2, 10, 0, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{2, 8, 3, 2, 10, 8, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1},
{3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{0, 11, 2, 8, 11, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{1, 9, 0, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{1, 11, 2, 1, 9, 11, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1},
{3, 10, 1, 11, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{0, 10, 1, 0, 8, 10, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1},
{3, 9, 0, 3, 11, 9, 11, 10, 9, -1, -1, -1, -1, -1, -1, -1},
{9, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{4, 3, 0, 7, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{0, 1, 9, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{4, 1, 9, 4, 7, 1, 7, 3, 1, -1, -1, -1, -1, -1, -1, -1},
{1, 2, 10, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{3, 4, 7, 3, 0, 4, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1},
{9, 2, 10, 9, 0, 2, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1},
{2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, -1, -1, -1, -1},
{8, 4, 7, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{11, 4, 7, 11, 2, 4, 2, 0, 4, -1, -1, -1, -1, -1, -1, -1},
{9, 0, 1, 8, 4, 7, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1},
{4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, -1, -1, -1, -1},
{3, 10, 1, 3, 11, 10, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1},
{1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, -1, -1, -1, -1},
{4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, -1, -1, -1, -1},
{4, 7, 11, 4, 11, 9, 9, 11, 10, -1, -1, -1, -1, -1, -1, -1},
{9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{9, 5, 4, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{0, 5, 4, 1, 5, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{8, 5, 4, 8, 3, 5, 3, 1, 5, -1, -1, -1, -1, -1, -1, -1},
{1, 2, 10, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{3, 0, 8, 1, 2, 10, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1},
{5, 2, 10, 5, 4, 2, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1},
{2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, -1, -1, -1, -1},
{9, 5, 4, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{0, 11, 2, 0, 8, 11, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1},
{0, 5, 4, 0, 1, 5, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1},
{2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, -1, -1, -1, -1},
{10, 3, 11, 10, 1, 3, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1},
{4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, -1, -1, -1, -1},
{5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, -1, -1, -1, -1},
{5, 4, 8, 5, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1},
{9, 7, 8, 5, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{9, 3, 0, 9, 5, 3, 5, 7, 3, -1, -1, -1, -1, -1, -1, -1},
{0, 7, 8, 0, 1, 7, 1, 5, 7, -1, -1, -1, -1, -1, -1, -1},
{1, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{9, 7, 8, 9, 5, 7, 10, 1, 2, -1, -1, -1, -1, -1, -1, -1},
{10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, -1, -1, -1, -1},
{8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, -1, -1, -1, -1},
{2, 10, 5, 2, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1},
{7, 9, 5, 7, 8, 9, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1},
{9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, -1, -1, -1, -1},
{2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, -1, -1, -1, -1},
{11, 2, 1, 11, 1, 7, 7, 1, 5, -1, -1, -1, -1, -1, -1, -1},
{9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, -1, -1, -1, -1},
{5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, -1},
{11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, -1},
{11, 10, 5, 7, 11, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{0, 8, 3, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{9, 0, 1, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{1, 8, 3, 1, 9, 8, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1},
{1, 6, 5, 2, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{1, 6, 5, 1, 2, 6, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1},
{9, 6, 5, 9, 0, 6, 0, 2, 6, -1, -1, -1, -1, -1, -1, -1},
{5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, -1, -1, -1, -1},
{2, 3, 11, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{11, 0, 8, 11, 2, 0, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1},
{0, 1, 9, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1},
{5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, -1, -1, -1, -1},
{6, 3, 11, 6, 5, 3, 5, 1, 3, -1, -1, -1, -1, -1, -1, -1},
{0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, -1, -1, -1, -1},
{3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, -1, -1, -1, -1},
{6, 5, 9, 6, 9, 11, 11, 9, 8, -1, -1, -1, -1, -1, -1, -1},
{5, 10, 6, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{4, 3, 0, 4, 7, 3, 6, 5, 10, -1, -1, -1, -1, -1, -1, -1},
{1, 9, 0, 5, 10, 6, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1},
{10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, -1, -1, -1, -1},
{6, 1, 2, 6, 5, 1, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1},
{1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, -1, -1, -1, -1},
{8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, -1, -1, -1, -1},
{7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, -1},
{3, 11, 2, 7, 8, 4, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1},
{5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, -1, -1, -1, -1},
{0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1},
{9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, -1},
{8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, -1, -1, -1, -1},
{5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, -1},
{0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, -1},
{6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, -1, -1, -1, -1},
{10, 4, 9, 6, 4, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{4, 10, 6, 4, 9, 10, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1},
{10, 0, 1, 10, 6, 0, 6, 4, 0, -1, -1, -1, -1, -1, -1, -1},
{8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, -1, -1, -1, -1},
{1, 4, 9, 1, 2, 4, 2, 6, 4, -1, -1, -1, -1, -1, -1, -1},
{3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, -1, -1, -1, -1},
{0, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{8, 3, 2, 8, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1},
{10, 4, 9, 10, 6, 4, 11, 2, 3, -1, -1, -1, -1, -1, -1, -1},
{0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, -1, -1, -1, -1},
{3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, -1, -1, -1, -1},
{6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, -1},
{9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, -1, -1, -1, -1},
{8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, -1},
{3, 11, 6, 3, 6, 0, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1},
{6, 4, 8, 11, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{7, 10, 6, 7, 8, 10, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1},
{0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, -1, -1, -1, -1},
{10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, -1, -1, -1, -1},
{10, 6, 7, 10, 7, 1, 1, 7, 3, -1, -1, -1, -1, -1, -1, -1},
{1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, -1, -1, -1, -1},
{2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, -1},
{7, 8, 0, 7, 0, 6, 6, 0, 2, -1, -1, -1, -1, -1, -1, -1},
{7, 3, 2, 6, 7, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, -1, -1, -1, -1},
{2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, -1},
{1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, -1},
{11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, -1, -1, -1, -1},
{8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, -1},
{0, 9, 1, 11, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, -1, -1, -1, -1},
{7, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{3, 0, 8, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{0, 1, 9, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{8, 1, 9, 8, 3, 1, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1},
{10, 1, 2, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{1, 2, 10, 3, 0, 8, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1},
{2, 9, 0, 2, 10, 9, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1},
{6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, -1, -1, -1, -1},
{7, 2, 3, 6, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{7, 0, 8, 7, 6, 0, 6, 2, 0, -1, -1, -1, -1, -1, -1, -1},
{2, 7, 6, 2, 3, 7, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1},
{1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, -1, -1, -1, -1},
{10, 7, 6, 10, 1, 7, 1, 3, 7, -1, -1, -1, -1, -1, -1, -1},
{10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, -1, -1, -1, -1},
{0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, -1, -1, -1, -1},
{7, 6, 10, 7, 10, 8, 8, 10, 9, -1, -1, -1, -1, -1, -1, -1},
{6, 8, 4, 11, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{3, 6, 11, 3, 0, 6, 0, 4, 6, -1, -1, -1, -1, -1, -1, -1},
{8, 6, 11, 8, 4, 6, 9, 0, 1, -1, -1, -1, -1, -1, -1, -1},
{9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, -1, -1, -1, -1},
{6, 8, 4, 6, 11, 8, 2, 10, 1, -1, -1, -1, -1, -1, -1, -1},
{1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, -1, -1, -1, -1},
{4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, -1, -1, -1, -1},
{10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, -1},
{8, 2, 3, 8, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1},
{0, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, -1, -1, -1, -1},
{1, 9, 4, 1, 4, 2, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1},
{8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, -1, -1, -1, -1},
{10, 1, 0, 10, 0, 6, 6, 0, 4, -1, -1, -1, -1, -1, -1, -1},
{4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, -1},
{10, 9, 4, 6, 10, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{4, 9, 5, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{0, 8, 3, 4, 9, 5, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1},
{5, 0, 1, 5, 4, 0, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1},
{11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, -1, -1, -1, -1},
{9, 5, 4, 10, 1, 2, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1},
{6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, -1, -1, -1, -1},
{7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, -1, -1, -1, -1},
{3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, -1},
{7, 2, 3, 7, 6, 2, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1},
{9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, -1, -1, -1, -1},
{3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, -1, -1, -1, -1},
{6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, -1},
{9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, -1, -1, -1, -1},
{1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, -1},
{4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, -1},
{7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, -1, -1, -1, -1},
{6, 9, 5, 6, 11, 9, 11, 8, 9, -1, -1, -1, -1, -1, -1, -1},
{3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, -1, -1, -1, -1},
{0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, -1, -1, -1, -1},
{6, 11, 3, 6, 3, 5, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1},
{1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, -1, -1, -1, -1},
{0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, -1},
{11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, -1},
{6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, -1, -1, -1, -1},
{5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, -1, -1, -1, -1},
{9, 5, 6, 9, 6, 0, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1},
{1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, -1},
{1, 5, 6, 2, 1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, -1},
{10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, -1, -1, -1, -1},
{0, 3, 8, 5, 6, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{10, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{11, 5, 10, 7, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{11, 5, 10, 11, 7, 5, 8, 3, 0, -1, -1, -1, -1, -1, -1, -1},
{5, 11, 7, 5, 10, 11, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1},
{10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, -1, -1, -1, -1},
{11, 1, 2, 11, 7, 1, 7, 5, 1, -1, -1, -1, -1, -1, -1, -1},
{0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, -1, -1, -1, -1},
{9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, -1, -1, -1, -1},
{7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, -1},
{2, 5, 10, 2, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1},
{8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, -1, -1, -1, -1},
{9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, -1, -1, -1, -1},
{9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, -1},
{1, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{0, 8, 7, 0, 7, 1, 1, 7, 5, -1, -1, -1, -1, -1, -1, -1},
{9, 0, 3, 9, 3, 5, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1},
{9, 8, 7, 5, 9, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{5, 8, 4, 5, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1},
{5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, -1, -1, -1, -1},
{0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, -1, -1, -1, -1},
{10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, -1},
{2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, -1, -1, -1, -1},
{0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, -1},
{0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, -1},
{9, 4, 5, 2, 11, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, -1, -1, -1, -1},
{5, 10, 2, 5, 2, 4, 4, 2, 0, -1, -1, -1, -1, -1, -1, -1},
{3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, -1},
{5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, -1, -1, -1, -1},
{8, 4, 5, 8, 5, 3, 3, 5, 1, -1, -1, -1, -1, -1, -1, -1},
{0, 4, 5, 1, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, -1, -1, -1, -1},
{9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{4, 11, 7, 4, 9, 11, 9, 10, 11, -1, -1, -1, -1, -1, -1, -1},
{0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, -1, -1, -1, -1},
{1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, -1, -1, -1, -1},
{3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, -1},
{4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, -1, -1, -1, -1},
{9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, -1},
{11, 7, 4, 11, 4, 2, 2, 4, 0, -1, -1, -1, -1, -1, -1, -1},
{11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, -1, -1, -1, -1},
{2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, -1, -1, -1, -1},
{9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, -1},
{3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, -1},
{1, 10, 2, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{4, 9, 1, 4, 1, 7, 7, 1, 3, -1, -1, -1, -1, -1, -1, -1},
{4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, -1, -1, -1, -1},
{4, 0, 3, 7, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{9, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{3, 0, 9, 3, 9, 11, 11, 9, 10, -1, -1, -1, -1, -1, -1, -1},
{0, 1, 10, 0, 10, 8, 8, 10, 11, -1, -1, -1, -1, -1, -1, -1},
{3, 1, 10, 11, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{1, 2, 11, 1, 11, 9, 9, 11, 8, -1, -1, -1, -1, -1, -1, -1},
{3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, -1, -1, -1, -1},
{0, 2, 11, 8, 0, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{3, 2, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{2, 3, 8, 2, 8, 10, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1},
{9, 10, 2, 0, 9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, -1, -1, -1, -1},
{1, 10, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{1, 3, 8, 9, 1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}};
#endif

View File

@@ -0,0 +1,30 @@
//////////////////////////////////////////////////////////////////////////////////////////
// METABALL.h
// Class declaration for metaball
// Downloaded from: www.paulsprojects.net
// Created: 20th July 2002
//
// Copyright (c) 2006, Paul Baker
// Distributed under the New BSD Licence. (See accompanying file License.txt or copy at
// http://www.paulsprojects.net/NewBSDLicense.txt)
//////////////////////////////////////////////////////////////////////////////////////////
#ifndef C_METABALL_H
#define C_METABALL_H
#include "cbase.h"
class METABALL
{
public:
Vector position;
float squaredRadius;
void Init(Vector newPosition, float newSquaredRadius)
{
position=newPosition;
squaredRadius=newSquaredRadius;
}
};
#endif

View File

@@ -0,0 +1,344 @@
#include "cbase.h"
#include "c_props.h"
#include "METABALL.h"
#include "CUBE_GRID.h"
#include "debugoverlay_shared.h"
#include "c_point_blob_element.h"
#include "c_point_blob_container.h"
#include "materialsystem/imesh.h"
LINK_ENTITY_TO_CLASS(point_blob_container, C_PointBlobContainer);
IMPLEMENT_NETWORKCLASS_ALIASED(PointBlobContainer, DT_PointBlobContainer)
BEGIN_NETWORK_TABLE(C_PointBlobContainer, DT_PointBlobContainer)
RecvPropInt(RECVINFO(GridSize)),
RecvPropVector(RECVINFO(GridBounds)),
RecvPropInt(RECVINFO(color), 0, RecvProxy_IntToColor32),
RecvPropInt(RECVINFO(Ambcolor), 0, RecvProxy_IntToColor32),
RecvPropFloat(RECVINFO(colorBoost)),
RecvPropString(RECVINFO(BlobMaterialName)),
END_NETWORK_TABLE()
ConVar r_drawblobs("r_drawblobs", "1", FCVAR_CLIENTDLL);
ConVar cl_blobs_updatecontainers("cl_blobs_updatecontainers", "1", FCVAR_CLIENTDLL);
//ConVar cl_blobs_resolution("cl_blobs_resolution", "10", FCVAR_CLIENTDLL);
ConVar cl_blobthreshold("cl_blobthreshold", "1.2", FCVAR_CLIENTDLL);
ConVar cl_blobvaluethreshold("cl_blobvaluethreshold", "0.3", FCVAR_CLIENTDLL);
ConVar cl_blobs_unroll_factor("cl_blobs_unroll_factor", "4", FCVAR_CLIENTDLL);
//why? why not! (it works better then Q_strcmp that redirects to V_strcmp that redirects to strcmp)
int Quake_strcmp (const char* s1, const char* s2)
{
while (1)
{
if (*s1 != *s2)
return -1; // strings not equal
if (!*s1)
return 0; // strings are equal
s1++;
s2++;
}
return -1;
}
void C_PointBlobContainer::Spawn()
{
//get already existed container to save compute resources and just use already existed one.
///////
size_t count = 0;
// Iterate through all the entities in the clientside world
for (int i = 0; i < cl_entitylist->GetHighestEntityIndex() + 1; i++)
{
if(parentedContainer != NULL)
{
C_BaseEntity* entity = cl_entitylist->GetBaseEntity(i);
if (entity && entity->GetClientClass()->m_pNetworkName)
{
// Check if the entity is valid and matches the desired class name
if (Quake_strcmp(entity->GetClientClass()->m_pNetworkName, "CPointBlobContainer") == 0)
{
//add entity into array
parentedContainer = ((C_PointBlobContainer*)(entity));
Msg("%u\n", count);
}
}
}
}
////////
BaseClass::Spawn();
}
int C_PointBlobContainer::DrawModel(int flags)
{
if(r_drawblobs.GetBool())
{
if (metaballs.size() > 0)
{
///Source dont like when you do CMeshBuilder stuff in DrawModel. So sometimes lighting looks like shit. Im making it unlit because i cant feagure out how to fix this
CMatRenderContextPtr pRenderContext(materials);
pRenderContext->Bind(CustomMat, NULL);
pRenderContext->SetLightingOrigin(GetAbsOrigin());
g_pStudioRender->SetAmbientLightColors(white);
//// Disable all the lights..
//pRenderContext->DisableAllLocalLights();
pMesh = pRenderContext->GetDynamicMesh();
CMeshBuilder meshBuilder;
const float threshold = cl_blobthreshold.GetFloat();
meshBuilder.Begin(pMesh, MATERIAL_TRIANGLES, cubeGrid.numVertices);
//loop through cubes
for (int i = 0; i < cubeGrid.numCubes; i++)
{
//calculate which vertices are inside the surface
unsigned char cubeIndex = 0;
if (cubeGrid.cubes[i].vertices[0]->value < threshold)
cubeIndex |= 1;
if (cubeGrid.cubes[i].vertices[1]->value < threshold)
cubeIndex |= 2;
if (cubeGrid.cubes[i].vertices[2]->value < threshold)
cubeIndex |= 4;
if (cubeGrid.cubes[i].vertices[3]->value < threshold)
cubeIndex |= 8;
if (cubeGrid.cubes[i].vertices[4]->value < threshold)
cubeIndex |= 16;
if (cubeGrid.cubes[i].vertices[5]->value < threshold)
cubeIndex |= 32;
if (cubeGrid.cubes[i].vertices[6]->value < threshold)
cubeIndex |= 64;
if (cubeGrid.cubes[i].vertices[7]->value < threshold)
cubeIndex |= 128;
//look this value up in the edge table to see which edges to interpolate along
int usedEdges = edgeTable[cubeIndex];
//if the cube is entirely within/outside surface, no faces
if (usedEdges == 0 || usedEdges == 255)
continue;
//update these edges
for (int currentEdge = 0; currentEdge < 12; currentEdge++)
{
if (usedEdges & 1 << currentEdge)
{
CUBE_GRID_VERTEX* v1 = cubeGrid.cubes[i].vertices[verticesAtEndsOfEdges[currentEdge * 2]];
CUBE_GRID_VERTEX* v2 = cubeGrid.cubes[i].vertices[verticesAtEndsOfEdges[currentEdge * 2 + 1]];
float delta = (threshold - v1->value) / (v2->value - v1->value);
//edgeVertices[currentEdge].position=v1->position + delta*(v2->position - v1->position);
edgeVertices[currentEdge].position.x = v1->position.x + delta * (v2->position.x - v1->position.x);
edgeVertices[currentEdge].position.y = v1->position.y + delta * (v2->position.y - v1->position.y);
edgeVertices[currentEdge].position.z = v1->position.z + delta * (v2->position.z - v1->position.z);
//edgeVertices[currentEdge].normal=v1->normal + delta*(v2->normal - v1->normal);
edgeVertices[currentEdge].normal.x = v1->normal.x + delta * (v2->normal.x - v1->normal.x);
edgeVertices[currentEdge].normal.y = v1->normal.y + delta * (v2->normal.y - v1->normal.y);
edgeVertices[currentEdge].normal.z = v1->normal.z + delta * (v2->normal.z - v1->normal.z);
}
}
//send the vertices
for (int k = 0; triTable[cubeIndex][k] != -1; k += 3)
{
//Vector pos = Vector(edgeVertices[triTable[cubeIndex][k + 0]].position.x, edgeVertices[triTable[cubeIndex][k + 0]].position.y, edgeVertices[triTable[cubeIndex][k + 0]].position.z);
//Vector vertnormal = Vector(edgeVertices[triTable[cubeIndex][k + 0]].normal.x, edgeVertices[triTable[cubeIndex][k + 0]].normal.y, edgeVertices[triTable[cubeIndex][k + 0]].normal.z);
meshBuilder.Normal3fv(edgeVertices[triTable[cubeIndex][k + 0]].normal.Base());
meshBuilder.Position3fv(edgeVertices[triTable[cubeIndex][k + 0]].position.Base());
meshBuilder.TexCoord2f(0, 1, 1);
meshBuilder.Color3f(1,0,0);
meshBuilder.AdvanceVertex();
//pos = Vector(edgeVertices[triTable[cubeIndex][k + 1]].position.x, edgeVertices[triTable[cubeIndex][k + 1]].position.y, edgeVertices[triTable[cubeIndex][k + 1]].position.z);
//vertnormal = Vector(edgeVertices[triTable[cubeIndex][k + 1]].normal.x, edgeVertices[triTable[cubeIndex][k + 1]].normal.y, edgeVertices[triTable[cubeIndex][k + 1]].normal.z);
meshBuilder.Normal3fv(edgeVertices[triTable[cubeIndex][k + 1]].normal.Base());
meshBuilder.Position3fv(edgeVertices[triTable[cubeIndex][k + 1]].position.Base());
meshBuilder.TexCoord2f(0, 1, 0);
meshBuilder.Color3f(0, 1, 0);
meshBuilder.AdvanceVertex();
//pos = Vector(edgeVertices[triTable[cubeIndex][k + 2]].position.x, edgeVertices[triTable[cubeIndex][k + 2]].position.y, edgeVertices[triTable[cubeIndex][k + 2]].position.z);
//vertnormal = Vector(edgeVertices[triTable[cubeIndex][k + 2]].normal.x, edgeVertices[triTable[cubeIndex][k + 2]].normal.y, edgeVertices[triTable[cubeIndex][k + 2]].normal.z);
meshBuilder.Normal3fv(edgeVertices[triTable[cubeIndex][k + 2]].normal.Base());
meshBuilder.Position3fv(edgeVertices[triTable[cubeIndex][k + 2]].position.Base());
meshBuilder.TexCoord2f(0, 0, 1);
meshBuilder.Color3f(0, 0, 1);
meshBuilder.AdvanceVertex();
}
}
//pRenderContext->SetFlashlightMode(false);
meshBuilder.End();
//modelrender->SuppressEngineLighting(false);
pMesh->Draw();
pRenderContext->Flush();
//delete pMesh;
//pRenderContext->PopMatrix();
//pRenderContext->Flush();
}
}
return 1;
//return BaseClass::DrawModel(flags);
//return InternalDrawModel(STUDIO_RENDER | extraFlags);
}
void C_PointBlobContainer::GetRenderBounds(Vector& theMins, Vector& theMaxs)
{
theMaxs = Vector(GridBounds.x, GridBounds.y, GridBounds.z);
theMins = Vector(0,0,0);
}
void C_PointBlobContainer::UpdateResolution()
{
//GridSize = cl_blobs_resolution.GetInt();
cubeGrid.FreeMemory();
cubeGrid.CreateMemory();
}
void C_PointBlobContainer::UpdateBalls()
{
//cubeGrid->Init(GridSize, GetAbsOrigin(), GridBounds);
if(parentedContainer == NULL)
{
metaballs.clear();
// Iterate through all the entities in the clientside world
for (int i = 0; i < cl_entitylist->GetHighestEntityIndex()+1; i++)
{
C_BaseEntity* entity = cl_entitylist->GetBaseEntity(i);
if (entity && entity->GetClientClass()->m_pNetworkName)
{
// Check if the entity is valid and matches the desired class name
if (Quake_strcmp(entity->GetClientClass()->m_pNetworkName, "CPointBlobElement") == 0)
{
//add entity into array
metaballs.push_back((C_PointBlobElement*)(entity));
}
}
}
}
else
{
metaballs = parentedContainer->metaballs;
}
if (cl_blobs_updatecontainers.GetBool())
{
//clear the field
for (int i = 0; i < cubeGrid.numVertices; i++)
{
cubeGrid.vertices[i].value = 0.0f;
cubeGrid.vertices[i].normal = {0,0,0};
}
Vector ballToPoint;
float squaredRadius;
Vector ballPosition;
float normalScale = 0;
const float ValueThreshold = cl_blobvaluethreshold.GetFloat();
for (unsigned int i = 0; i < metaballs.size(); i++)
{
ballPosition = metaballs[i]->GetAbsOrigin();
squaredRadius = metaballs[i]->radiusSquared;
for (int j = 0; j < cubeGrid.numVertices; j++)
{
ballToPoint = cubeGrid.vertices[j].position - ballPosition;
vec_t squareDistance = ballToPoint.LengthSqr();
if (squareDistance != 0)
{
float valueIncrement = squaredRadius / squareDistance;
cubeGrid.vertices[j].value += (squareDistance > ValueThreshold) ? valueIncrement : 0;
normalScale = squaredRadius / (squareDistance * squareDistance);
cubeGrid.vertices[j].normal += ballToPoint * normalScale;
}
}
}
}
}
void C_PointBlobContainer::Simulate()
{
BaseClass::Simulate();
//if(cl_blobs_updatecontainers.GetBool())
UpdateBalls();
//if((cl_blobs_resolution.GetInt() != GridSize) || ((ConVarRef("cl_blobs_resolution_max").GetInt()) != ( cbrtf(cubeGrid->numVertices) - 3 )))
// UpdateResolution();
if(developer.GetInt() > 0)
{
Vector min;
Vector max;
GetRenderBounds(min,max);
NDebugOverlay::Box(GetAbsOrigin(), min, max, 255, 0, 0, 0, 0.0015f);
}
// Why like this?
// When you spawn entity using ent_create, engine spawns entity at 0 0 0, calls Spawn(), transfer all the netvar data and only then he changes position to view point.
// Simulate() called only AFTER changing position, so this shit will work more reliably here.
// (Yes, that means game dont transfer data before Spawn(), but after. Thats why i put BlobMaterialName check here.)
if (!first)
{
cubeGrid.Init(GridSize, GetAbsOrigin(), GridBounds);
for(size_t i=0; i<6; i++)
{
//white[i] = Vector(RemapVal(color.GetR(), 0, 255, 0, 1) * colorBoost, RemapVal(color.GetG(), 0, 255, 0, 1) * colorBoost, RemapVal(color.GetB(), 0, 255, 0, 1) * colorBoost);
white[i] = Vector(((float)Ambcolor.GetR()/255) * colorBoost, ((float)Ambcolor.GetG()/255) * colorBoost, ((float)Ambcolor.GetB()/255) * colorBoost);
//white[i] = Vector((Ambcolor.GetR()/0xFF) * colorBoost, (Ambcolor.GetG()/0xFF) * colorBoost, (Ambcolor.GetB()/0xFF) * colorBoost);
//white[i] = Vector(1 * colorBoost,1 * colorBoost,1 * colorBoost);
}
if (BlobMaterialName == 0x00000000)
{
char* buff = new char[20];
V_snprintf(buff, 20, "{ %i %i %i }", color.GetR(), color.GetG(), color.GetB());
kval = new KeyValues("UnlitGeneric");
kval->SetString("$color", buff);
//kval->SetString("$vertexcolor", "1");
//kval->SetString("$vertexalpha", "1");
//kval->SetString("$envmap", "editor/cubemap");
CustomMat = materials->CreateMaterial("blobik.vmt", kval);
}
else{
PrecacheMaterial(BlobMaterialName);
CustomMat = materials->FindMaterial(BlobMaterialName, TEXTURE_GROUP_OTHER);
}
first = true;
}
//if (GridSize != cl_blobs_resolution.GetInt())
//{
// GridSize = cl_blobs_resolution.GetInt();
//}
}

View File

@@ -0,0 +1,86 @@
#ifndef C_BLOBCONTAINER_H
#define C_BLOBCONTAINER_H
#include "cbase.h"
#include "c_props.h"
#include "METABALL.h"
#include "CUBE_GRID.h"
#include "c_point_blob_element.h"
#include "model_types.h"
#include "studio_stats.h"
#include <vector>
class C_PointBlobContainer : public C_BreakableProp
{
DECLARE_CLASS(C_PointBlobContainer, C_BreakableProp);
public:
DECLARE_NETWORKCLASS();
C_PointBlobContainer()
{
GridSize = 10;
cubeGrid = CUBE_GRID();
GridBounds = {50,50,50};
colorBoost = 1;
Ambcolor.SetR(88);
Ambcolor.SetG(88);
Ambcolor.SetB(88);
Ambcolor.SetA(255);
color.SetR(100);
color.SetG(100);
color.SetB(100);
color.SetA(255);
cubeGrid.CreateMemory();
}
~C_PointBlobContainer()
{
cubeGrid.FreeMemory();
//delete cubeGrid;
metaballs.clear();
}
void UpdateBalls();
void UpdateResolution();
virtual int DrawModel(int flags);
virtual void GetRenderBounds(Vector& theMins, Vector& theMaxs);
virtual void Spawn(void);
virtual void ClientThink(){}
//virtual void PostDataUpdate(DataUpdateType_t updateType);
virtual bool ShouldDraw() {return true;}
virtual void Simulate();
virtual void OnDataChanged(DataUpdateType_t type){}
CUBE_GRID cubeGrid;
int GridSize;
float colorBoost;
Vector GridBounds;
CNetworkColor32(Ambcolor);
CNetworkColor32(color);
std::vector<C_PointBlobElement*> metaballs;
IMesh* pMesh;
C_PointBlobContainer* parentedContainer;
Vector white[6];
char BlobMaterialName[MAX_PATH];
KeyValues* kval;
IMaterial* CustomMat;
private:
SURFACE_VERTEX edgeVertices[12];
bool first = false;
};
#endif // !C_BLOBCONTAINER_H

View File

@@ -0,0 +1,62 @@
#include "cbase.h"
//#include "c_props.h"
#include "METABALL.h"
#include "c_point_blob_element.h"
// memdbgon must be the last include file in a .cpp file!!! :apple_advertisement:
//#include "tier0/memdbgon.h"
LINK_ENTITY_TO_CLASS(point_blob_element, C_PointBlobElement);
IMPLEMENT_NETWORKCLASS_ALIASED(PointBlobElement, DT_PointBlobElement)
BEGIN_NETWORK_TABLE(C_PointBlobElement, DT_PointBlobElement)
RecvPropFloat(RECVINFO(radius)),
RecvPropFloat(RECVINFO(radiusSquared)),
END_NETWORK_TABLE()
void C_PointBlobElement::Spawn()
{
BaseClass::Spawn();
}
C_PointBlobElement::C_PointBlobElement()
{
radius = 10;
radiusSquared = radius * radius;
metaball = METABALL();
}
C_PointBlobElement::C_PointBlobElement(int newRadius)
{
radius = newRadius;
radiusSquared = radius * radius;
metaball = METABALL();
}
void C_PointBlobElement::Simulate()
{
BaseClass::Simulate();
//if(!First)
//{
// pos = GetAbsOrigin();
// SpawnTime = gpGlobals->curtime;
// First = true;
//}
//Vector ghgh;
//ghgh.x = pos.x + sin(gpGlobals->curtime - SpawnTime);
//ghgh.y = pos.y + sin(gpGlobals->curtime - SpawnTime);
//ghgh.z = pos.z + sin(gpGlobals->curtime - SpawnTime);
//SetAbsOrigin(ghgh);
//metaball.squaredRadius = radius * radius;
//metaball.position = GetAbsOrigin();
//NDebugOverlay::Sphere(GetAbsOrigin(), sqrt(radius), 255, 0, 0, true, 0.0015f);
//Msg("dkgsfhgkklgsfklgjdfjklbujdfhgu");
}

View File

@@ -0,0 +1,42 @@
#ifndef C_BLOBELEMENT_H
#define C_BLOBELEMENT_H
#include "cbase.h"
#include "c_props.h"
#include "debugoverlay_shared.h"
#include "METABALL.h"
/////////////////////////////////////
///
/// This is a blob element, or single blob if you prefer. He needs to initialise METABALL variable.
/// You have to use this with C_PointBlobContainer to see the blob itself.
///
/////////////////////////////////////
class C_PointBlobElement : public C_BaseEntity
{
DECLARE_CLASS(C_PointBlobElement, C_BaseEntity);
public:
DECLARE_NETWORKCLASS();
C_PointBlobElement();
C_PointBlobElement(int newRadius);
~C_PointBlobElement(){}
virtual void Spawn(void);
virtual void ClientThink(){}
virtual void OnDataChanged(DataUpdateType_t type){}
virtual void Simulate();
float radius;
float radiusSquared;
METABALL metaball;
Vector pos;
float SpawnTime = 0;
bool First = false;
};
#endif // C_BLOBELEMENT_H

View File

@@ -0,0 +1,17 @@
$Project
{
$Folder "Source Files"
{
$Folder "Metaballs"
{
$File "metaballs/c_point_blob_element.cpp"
$File "metaballs/c_point_blob_element.h"
$File "metaballs/c_point_blob_container.cpp"
$File "metaballs/c_point_blob_container.h"
$File "metaballs/CUBE_GRID.cpp"
$File "metaballs/CUBE_GRID.h"
$File "metaballs/METABALL.h"
}
}
}

View File

@@ -0,0 +1,14 @@
$Project
{
$Folder "Source Files"
{
$Folder "Metaballs"
{
$File "metaballs/point_blob_element.cpp"
$File "metaballs/point_blob_element.h"
$File "metaballs/point_blob_container.cpp"
$File "metaballs/point_blob_container.h"
}
}
}

View File

@@ -0,0 +1,34 @@
#include "cbase.h"
#include "point_blob_element.h"
#include "point_blob_container.h"
LINK_ENTITY_TO_CLASS(point_blob_container, CPointBlobContainer);
//i should change the way how i do keyvalue shit later
BEGIN_DATADESC(CPointBlobContainer)
DEFINE_KEYFIELD(GridSize, FIELD_INTEGER, "resolution"),
DEFINE_KEYFIELD(GridBounds, FIELD_VECTOR, "bounds"),
DEFINE_KEYFIELD(color, FIELD_COLOR32, "color"),
DEFINE_KEYFIELD(Ambcolor, FIELD_COLOR32, "ambientcolor"),
DEFINE_KEYFIELD(colorBoost, FIELD_FLOAT, "brightness"),
DEFINE_KEYFIELD(BlobMaterialName, FIELD_STRING, "materialpath"),
END_DATADESC()
IMPLEMENT_SERVERCLASS_ST(CPointBlobContainer, DT_PointBlobContainer)
SendPropInt(SENDINFO(GridSize)),
#if HL2MP //idk how is it different, but it is different
SendPropVector(SENDINFO(GridBounds), -1, SPROP_COORD_MP),
#else
SendPropVector(SENDINFO(GridBounds), -1, SPROP_COORD),
#endif
SendPropInt( SENDINFO(color), 32, SPROP_UNSIGNED, SendProxy_Color32ToInt),
SendPropInt( SENDINFO(Ambcolor), 32, SPROP_UNSIGNED, SendProxy_Color32ToInt),
SendPropFloat(SENDINFO(colorBoost)),
SendPropStringT(SENDINFO(BlobMaterialName)),
END_SEND_TABLE()

View File

@@ -0,0 +1,55 @@
#ifndef C_BLOBCONTAINER_H
#define C_BLOBCONTAINER_H
#include "cbase.h"
#include "props.h"
#include "point_blob_element.h"
//just empty shit to be able to spawn entity using ent_create and use entity for fgd for map
class CPointBlobContainer : public CBreakableProp
{
DECLARE_CLASS(CPointBlobContainer, CBreakableProp);
public:
DECLARE_DATADESC();
DECLARE_SERVERCLASS();
CPointBlobContainer()
{
GridSize = 10;
GridBounds = Vector(50,50,50);
color = {255,255,255};
}
virtual void Spawn()
{
SetTransmitState(FL_EDICT_PVSCHECK);
m_nRenderMode = kRenderNormal;
m_nRenderFX = kRenderFxNone;
SetLightingOrigin(this);
//PrecacheModel("models/error.mdl");
//SetModel("models/error.mdl");
//BaseClass::Spawn();
// to shut up everything
SetMoveType(MOVETYPE_NONE);
m_takedamage = DAMAGE_NO;
SetNextThink(TICK_NEVER_THINK);
m_flAnimTime = gpGlobals->curtime;
m_flPlaybackRate = 0.0;
SetCycle(0);
}
CNetworkVar(int, GridSize);
CNetworkVar(float, colorBoost);
CNetworkVar(Vector, GridBounds);
CNetworkVar(string_t, BlobMaterialName);
CNetworkColor32(color);
CNetworkColor32(Ambcolor);
};
#endif // !C_BLOBCONTAINER_H

View File

@@ -0,0 +1,23 @@
#include "cbase.h"
//#include "c_props.h"
#include "point_blob_element.h"
// memdbgon must be the last include file in a .cpp file!!! :apple_advertisement:
//#include "tier0/memdbgon.h"
LINK_ENTITY_TO_CLASS(point_blob_element, CPointBlobElement);
BEGIN_DATADESC(CPointBlobElement)
//DEFINE_KEYFIELD(radius, FIELD_FLOAT, "radius"),
END_DATADESC()
IMPLEMENT_SERVERCLASS_ST(CPointBlobElement, DT_PointBlobElement)
SendPropFloat(SENDINFO(radius)),
SendPropFloat(SENDINFO(radiusSquared)),
END_SEND_TABLE()

View File

@@ -0,0 +1,49 @@
#ifndef C_BLOBELEMENT_H
#define C_BLOBELEMENT_H
#include "cbase.h"
#include "props.h"
#include "props_shared.h"
/////////////////////////////////////
///
/// This is a blob element, or single blob if you prefer. He needs to initialise METABALL variable.
/// You have to use this with C_PointBlobContainer to see the blob itself.
///
/////////////////////////////////////
class CPointBlobElement : public CBaseEntity
{
DECLARE_CLASS(CPointBlobElement, CBaseEntity);
public:
DECLARE_SERVERCLASS();
DECLARE_DATADESC();
CPointBlobElement(){}
virtual void Spawn()
{
SetTransmitState(FL_EDICT_ALWAYS);
m_nRenderMode = kRenderNormal;
m_nRenderFX = kRenderFxNone;
}
bool KeyValue(const char* szKeyName, const char* szValue)
{
if (FStrEq(szKeyName, "radius"))
{
radius = atof(szValue);
radiusSquared = radius * radius;
}
return BaseClass::KeyValue(szKeyName, szValue);
}
CNetworkVar(float, radius);
CNetworkVar(float, radiusSquared);
};
#endif // C_BLOBELEMENT_H