improved particle emitters

This commit is contained in:
devZoGok
2021-10-19 19:06:40 +03:00
parent d9f9b0c282
commit 7e1575d690
17 changed files with 295 additions and 51 deletions
+2 -1
View File
@@ -14,8 +14,9 @@ set(gui text.cpp rectangle.cpp)
set(utils util.cpp)
set(math quaternion.cpp vector.cpp ray.cpp)
set(render waterPlane.cpp particleEmitter.cpp camera.cpp light.cpp material.cpp mesh.cpp model.cpp node.cpp quad.cpp box.cpp root.cpp shader.cpp texture.cpp)
set(armature skeleton.cpp bone.cpp)
add_library(vb01 SHARED main.cpp ${render} ${math} ${utils} ${gui})
add_library(vb01 SHARED main.cpp ${render} ${math} ${utils} ${gui} ${armature})
target_link_libraries(vb01 glfw)
target_link_libraries(vb01 glad)
target_link_libraries(vb01 assimp)
+5
View File
@@ -0,0 +1,5 @@
#include"bone.h"
namespace vb01{
Bone::Bone() : Node(){}
}
+14
View File
@@ -0,0 +1,14 @@
#ifndef BONE_H
#define BONE_H
#include"node.h"
namespace vb01{
class Bone : public Node{
public:
Bone();
private:
};
}
#endif
+4 -4
View File
@@ -9,9 +9,9 @@ uniform vec2 screen;
uniform vec3 pos;
void main(){
float x,y;
x=(aVert.x+pos.x-screen.x*.5)/(screen.x*.5);
y=(screen.y*.5-(aVert.y+pos.y))/(screen.y*.5);
gl_Position=vec4(x,y,pos.z+aVert.z,1);
float x,y;
x=(aVert.x+pos.x-screen.x*.5)/(screen.x*.5);
y=(screen.y*.5-(aVert.y+pos.y))/(screen.y*.5);
gl_Position=vec4(x,y,pos.z+aVert.z,1);
texCoords=aTexCoords;
}
+5 -1
View File
@@ -1,6 +1,7 @@
#include"root.h"
#include"node.h"
#include"mesh.h"
#include"skeleton.h"
#include<glad.h>
#include<glfw3.h>
#include<glm.hpp>
@@ -90,7 +91,8 @@ namespace vb01{
}
Vector3 rotAxis=orient.norm().getAxis();
if(rotAxis==Vector3::VEC_ZERO)rotAxis=Vector3::VEC_I;
if(rotAxis==Vector3::VEC_ZERO)
rotAxis=Vector3::VEC_I;
mat4 model=translate(mat4(1.),vec3(pos.x,pos.y,pos.z));
model=rotate(model,orient.norm().getAngle(),vec3(rotAxis.x,rotAxis.y,rotAxis.z));
model=glm::scale(model,vec3(scale.x,scale.y,scale.z));
@@ -104,6 +106,8 @@ namespace vb01{
shader->setMat4(proj,"proj");
shader->setVec3(camPos,"camPos");
shader->setMat4(model,"model");
if(skeleton){
}
if(material->getType()==Material::MATERIAL_GUI){
shader->setVec2(Vector2((float)width,(float)height),"screen");
if(node)
+9
View File
@@ -9,6 +9,7 @@
namespace vb01{
class Node;
class Skeleton;
class Mesh{
public:
@@ -16,6 +17,12 @@ namespace vb01{
Vector3 pos,norm;
Vector2 texCoords;
};
struct VertexGroup{
int numVertices=0;
Vertex **vertices=nullptr;
float *weights;
std::string name;
};
Mesh(Vertex*,unsigned int*,int);
~Mesh();
@@ -36,12 +43,14 @@ namespace vb01{
Node *node=nullptr;
std::vector<Mesh*> meshes;
std::string name="";
Skeleton *skeleton=nullptr;
protected:
Mesh();
void construct();
bool staticVerts=true,castShadow=false;
Vertex *vertices;
VertexGroup groups;
unsigned int *indices,VAO,VBO,EBO;
int numTris;
};
+133 -3
View File
@@ -8,6 +8,7 @@
#include<Importer.hpp>
#include<scene.h>
#include<postprocess.h>
#include<fstream>
using namespace std;
using namespace Assimp;
@@ -59,7 +60,8 @@ namespace vb01{
currentNode->attachMesh(new Mesh(vertices,indices,numTris));
}
Model::Model(string path) : Node(){
Model::Model(string path,bool b) : Node(){
if(b){
Importer importer;
const aiScene *scene=importer.ReadFile(path,aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_GenNormals);
if(!scene||scene->mFlags&AI_SCENE_FLAGS_INCOMPLETE||!scene->mRootNode){
@@ -67,6 +69,133 @@ namespace vb01{
exit(-1);
}
processNode(scene->mRootNode,scene,this);
}
else{
int numTris,numVerts,numGroups,v=0,u=0,vg=0,b=0;
Mesh::Vertex *vertices;
Mesh::VertexGroup *groups=new Mesh::VertexGroup[5];
unsigned int *indices;
Vector3 *pos,*norm;
ifstream in(path);
string l;
bool verts=false,uv=false,vertexGroups=false,bones=false;
while(getline(in,l)){
if(l.substr(0,8)=="numFaces"){
numTris=atoi(l.substr(9,string::npos).c_str());
vertices=new Mesh::Vertex[numTris*3];
indices=new unsigned int[numTris*3];
}
else if(l.substr(0,11)=="numVertices"){
numVerts=atoi(l.substr(12,string::npos).c_str());
pos=new Vector3[numVerts];
norm=new Vector3[numVerts];
}
else if(l.substr(0,9)=="numGroups"){
numGroups=atoi(l.substr(10,string::npos).c_str());
groups=new Mesh::VertexGroup[numGroups];
}
if(l=="vertices:"){
verts=true;
continue;
}
else if(l=="uv:"){
verts=false;
uv=true;
continue;
}
else if(l=="groups:"){
uv=false;
vertexGroups=true;
continue;
}
else if(l=="bones:"){
vertexGroups=false;
bones=true;
continue;
}
if(verts||uv||vertexGroups||bones){
int numCoords=1;
if(verts)numCoords=6;
else if(uv)numCoords=3;
else if(vg)numCoords=3;
else if(groups)numCoords=1;
int nextSpace=0;
int *spaceIds=new int[numCoords-1];
for(int i=0;i<l.length();i++)
if(l.c_str()[i]==' '){
spaceIds[nextSpace]=i;
nextSpace++;
}
float *coords=new float[numCoords];
for(int i=0;i<numCoords;i++){
int firstChar,lastChar;
if(i==0)
firstChar=0,lastChar=spaceIds[i];
else if(i==numCoords-1)
firstChar=spaceIds[i-1],lastChar=string::npos;
else
firstChar=spaceIds[i-1],lastChar=spaceIds[i]-spaceIds[i-1];
coords[i]=atof(l.substr(firstChar,lastChar).c_str());
}
if(verts){
pos[v]=Vector3(coords[0],coords[1],coords[2]);
norm[v]=Vector3(coords[3],coords[4],coords[5]);
//Vector2 uv=Vector2(coords[6],coords[7]);
//vertices[v].pos=pos;
//vertices[v].norm=norm;
//vertices[v].texCoords=uv;
v++;
}
else if(uv){
int id=(int)coords[0];
Vector2 uv=Vector2(coords[1],coords[2]);
vertices[u].pos=pos[id];
vertices[u].norm=norm[id];
vertices[u].texCoords=uv;
indices[u]=u;
u++;
}
else if(vertexGroups){
if(l.c_str()[l.length()-1]==':'){
numCoords=1;
groups[vg].vertices=new Mesh::Vertex*;
groups[vg].weights=new float;
groups[vg].name=l.c_str()[l.length()-1];
vg++;
}
else{
numCoords=2;
int *ids=new int,numVerts=0;
for(int i=0;i<3*numTris;i++){
if(vertices[i].pos==pos[(int)coords[0]]){
ids[numVerts]=i;
numVerts++;
}
}
for(int i=0;i<3*numTris;i++)
for(int j=0;j<numVerts;j++){
groups[vg].vertices[groups[vg].numVertices]=&(vertices[ids[j]]);
groups[vg].weights[ids[j]]=coords[1];
}
groups[vg].numVertices++;
delete[] ids;
}
}
else if(bones){
b++;
}
delete[] coords;
}
}
delete[] pos;
delete[] norm;
attachChild(new Node());
children[0]->attachMesh(new Mesh(vertices,indices,numTris));
}
}
Model::~Model(){}
@@ -76,10 +205,11 @@ namespace vb01{
}
void Model::setMaterial(Material *mat){
for(Node *node : children)
vector<Node*> descendants;
getDescendants(this,descendants);
for(Node *node : descendants)
for(Mesh *mesh : node->getMeshes())
mesh->setMaterial(mat);
this->material=mat;
}
void Model::setCastShadow(bool castShadow){
+1 -1
View File
@@ -17,7 +17,7 @@ namespace vb01{
class Model : public Node{
public:
Model(std::string);
Model(std::string,bool=true);
~Model();
void update();
void setMaterial(Material*);
+1
View File
@@ -12,5 +12,6 @@ uniform vec4 color[100];
void main(){
float alpha=texture(tex,texCoords).x;
vec4 c=color[id];
//FragColor=vec4(1,0,0,1);
FragColor=vec4(c.x,c.y,c.z,c.w*alpha);
}
+6 -3
View File
@@ -13,10 +13,13 @@ uniform mat4 model[100];
uniform vec2 size[100];
void main(){
vec3 camLeft=-vec3(view[0][0],view[1][0],view[2][0]);
vec3 camUp=vec3(view[1][0],view[2][0],view[3][0]);
vec3 camLeft=vec3(view[0][0],view[1][0],view[2][0]);
vec3 camUp=vec3(view[0][1],view[1][1],view[2][1]);
id=gl_InstanceID;
vec2 s=size[gl_InstanceID];
gl_Position=proj*view*model[gl_InstanceID]*vec4(camLeft*s.x*aPos.x+camUp*s.y*aPos.y+camDir*aPos.z,1);
vec3 v=camLeft*s.x*aPos.x+camUp*s.y*aPos.y;
gl_Position=proj*view*model[gl_InstanceID]*vec4(v,1);
//gl_Position=proj*view*model[gl_InstanceID]*vec4(s.x*aPos.x,s.y*aPos.y,aPos.z,1);
texCoords=aTexCoords;
}
+13 -5
View File
@@ -79,7 +79,7 @@ namespace vb01{
float fov=cam->getFov(),width=root->getWidth(),height=root->getHeight();
float nearPlane=cam->getNearPlane(),farPlane=cam->getFarPlane();
Vector3 pos=node->getPosition();
Vector3 camDir=cam->getDirection(),up=cam->getUp(),camPos=cam->getPosition();
Vector3 camDir=cam->getDirection(),up=cam->getUp(),left=cam->getLeft(),camPos=cam->getPosition();
mat4 view=lookAt(vec3(camPos.x,camPos.y,camPos.z),vec3(camPos.x+camDir.x,camPos.y+camDir.y,camPos.z+camDir.z),vec3(up.x,up.y,up.z));
mat4 proj=perspective(radians(fov),width/height,nearPlane,farPlane);
@@ -94,12 +94,14 @@ namespace vb01{
if(getTime()-particles[i].time>=particles[i].timeToLive){
particles[i].time=getTime();
float factor=(float)(rand()%100)/100;
float spreadX=(float)(rand()%360)/180*PI,spreadY=(float)(rand()%360)/180*PI;
dir=Vector3(cos(abs(spreadX)>spread?spread:spreadX),sin(abs(spreadY)>spread?spread:spreadY),0);
float s1=float(rand()%(int)spread)/180*PI,s2=float(rand()%360)/180*PI;
Vector3 ra1=(Vector3(0,1,0).cross(dir)).norm(),ra2=dir.norm();
dir=Quaternion(s1,ra1)*dir;
dir=Quaternion(s2,ra2)*dir;
particles[i].timeToLive=s64(1000*((highLife-lowLife)*factor+lowLife));
particles[i].mat=translate(mat4(1.f),vec3(dir.x,dir.y,dir.z));
particles[i].mat=mat4(1.f);
}
dir=dir.norm()*direction.getLengthSq();
particles[i].dir=dir.norm()*direction.getLengthSq();
float lifePercentage=(float)(getTime()-particles[i].time)/particles[i].timeToLive;
particles[i].color=startColor+(endColor-startColor)*lifePercentage;
particles[i].size=startSize+(endSize-startSize)*lifePercentage;
@@ -127,4 +129,10 @@ namespace vb01{
glBindVertexArray(VAO);
glDrawElementsInstanced(GL_TRIANGLES,6,GL_UNSIGNED_INT,0,numParticles);
}
void ParticleEmitter::setDirection(Vector3 dir){
this->direction=dir;
for(int i=0;i<numParticles;i++)
particles[i].dir=dir;
}
}
+3 -1
View File
@@ -21,6 +21,8 @@ namespace vb01{
inline void setEndSize(Vector2 size){this->endSize=size;}
inline void setStartColor(Vector4 color){this->startColor=color;}
inline void setEndColor(Vector4 color){this->endColor=color;}
inline void setSpread(float s){this->spread=s;}
void setDirection(Vector3 dir);
private:
struct Vertex{
Vector3 pos;
@@ -42,7 +44,7 @@ namespace vb01{
Vector2 startSize=Vector2::VEC_IJ,endSize=Vector2::VEC_IJ;
Vector3 direction=Vector3(0,.1,0);
Vector4 startColor,endColor;
float spread=0,lowLife=1,highLife=2;
float spread=1,lowLife=1,highLife=2;
};
}
+6 -5
View File
@@ -54,10 +54,11 @@ namespace vb01{
}
void sortResults(std::vector<CollisionResult> &results){
for(int i=0;i<results.size();i++){
for(int i2=i;i2<results.size();i2++)
if(results[i].distance>results[i2].distance)
swap(results[i],results[i2]);
}
if(!results.empty())
for(int i=0;i<results.size();i++){
for(int i2=i;i2<results.size();i2++)
if(results[i].distance>results[i2].distance)
swap(results[i],results[i2]);
}
}
}
+28 -27
View File
@@ -52,8 +52,9 @@ namespace vb01{
}
glEnable(GL_DEPTH_TEST);
glEnable(GL_STENCIL_TEST);
glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);
//glEnable(GL_CULL_FACE);
//glCullFace(GL_BACK);
glDepthMask(GL_TRUE);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
@@ -68,11 +69,11 @@ namespace vb01{
glRenderbufferStorage(GL_RENDERBUFFER,GL_DEPTH24_STENCIL8,width,height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_DEPTH_STENCIL_ATTACHMENT,GL_RENDERBUFFER,RBO);
*/
glBindFramebuffer(GL_FRAMEBUFFER,0);
if(glCheckFramebufferStatus(GL_FRAMEBUFFER)!=GL_FRAMEBUFFER_COMPLETE)
cout<<"Not complete\n";
else
cout<<"Complete\n";
glBindFramebuffer(GL_FRAMEBUFFER,0);
guiPlane=new Quad(Vector3(width,height,-1),false);
Material *mat=new Material(Material::MATERIAL_GUI);
@@ -81,42 +82,42 @@ namespace vb01{
}
void Root::update(){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glBindFramebuffer(GL_FRAMEBUFFER,FBO);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
//glBindFramebuffer(GL_FRAMEBUFFER,FBO);
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
//glEnable(GL_CULL_FACE);
if(skybox){
glDepthMask(GL_FALSE);
glCullFace(GL_BACK);
skybox->update();
glDepthMask(GL_TRUE);
glCullFace(GL_FRONT);
}
if(skybox){
glDepthMask(GL_FALSE);
//glCullFace(GL_BACK);
skybox->update();
glDepthMask(GL_TRUE);
//glCullFace(GL_FRONT);
}
rootNode->update();
rootNode->update();
glBindFramebuffer(GL_FRAMEBUFFER,0);
//glBindFramebuffer(GL_FRAMEBUFFER,0);
glDisable(GL_CULL_FACE);
//glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
glDisable(GL_DEPTH_TEST);
guiPlane->update();
/*
*/
glEnable(GL_DEPTH_TEST);
guiNode->update();
//guiPlane->update();
/*
*/
glEnable(GL_DEPTH_TEST);
guiNode->update();
glfwSwapBuffers(window);
glfwPollEvents();
glfwSwapBuffers(window);
glfwPollEvents();
}
void Root::createSkybox(string textures[6]){
skybox = new Box(Vector3(10,10,10));
Material *skyboxMat=new Material(Material::Type::MATERIAL_SKYBOX);
Material *skyboxMat=new Material(Material::MATERIAL_SKYBOX);
skyboxMat->addDiffuseMap(textures);
skybox->setMaterial(skyboxMat);
}
+48
View File
@@ -0,0 +1,48 @@
import sys
ob=bpy.data.objects['awp']
mesh=bpy.data.meshes['Cylinder']
fl="/home/dominykas/c++/vb01/kek.vb";
file=open(fl,"w")
file.write("numFaces:"+str(len(ob.data.polygons))+"\n")
file.write("numVertices:"+str(len(ob.data.vertices))+"\n")
file.write("vertices:\n")
for vert in ob.data.vertices:
pos=vert.co
norm=vert.normal
file.write(str(pos.x)+" "+str(pos.z)+" "+str(pos.y)+" "+str(norm.x)+" "+str(norm.z)+" "+str(norm.y)+"\n")
file.write("uv:\n")
for face in ob.data.polygons:
for vert,loop in zip(face.vertices,face.loop_indices):
uv=mesh.uv_layers[0].data[loop].uv
file.write(str(vert)+" "+str(uv.x)+" "+str(uv.y)+"\n")
file.write("numGroups:"+str(len(ob.vertex_groups))+"\n")
file.write("groups:\n")
for group in ob.vertex_groups:
file.write(group.name+":\n")
for vert in ob.data.vertices:
for g in vert.groups:
if g.group==group.index:
file.write(str(vert.index)+" "+str(g.weight)+"\n")
if ob.parent.name=="AWP":
file.write("bones:\n")
armature=ob.parent
for bone in armature.data.bones:
tail=bone.tail
head=bone.head
file.write(bone.name+":\n"+str(head.x)+" "+str(head.y)+" "+str(head.z)+" "+str(tail.x)+" "+str(tail.y)+" "+str(tail.z)+"\n")
file.write("boneHierarchy:\n")
for bone in armature.data.bones:
file.write(str(len(bone.children))+" ")
for ch in bone.children:
file.write(ch.name+" ")
file.write("\n")
file.close()
+5
View File
@@ -0,0 +1,5 @@
#include"skeleton.h"
namespace vb01{
Skeleton::Skeleton(){}
}
+12
View File
@@ -0,0 +1,12 @@
#ifndef SKELETON_H
#define SKELETON_H
namespace vb01{
class Skeleton{
public:
Skeleton();
private:
};
}
#endif