aboutsummaryrefslogtreecommitdiff
path: root/src/shared/lua_api/phys/bphysmodel.cpp
blob: e9fecbf7a9b0805176bf0c46850983d80621801a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <memory>
#include <map>
#include <functional>
#include <list>
extern "C" {
	#include <lua.h>
	#include <lauxlib.h>
	#include <lualib.h>
}
#include <btBulletDynamicsCommon.h>
#include "bphysmodel.hpp"
#include <shared/lua_api/common.hpp>
#include <shared/util/tinyobj.hpp>

extern btDiscreteDynamicsWorld* World;
extern std::list<btRigidBody*> Objects;

//newbphysmodel("graphicfile","physicfile",mass,[,{position}][,{lookat}])
static int newbphysmodel(lua_State* L){
	printf("Creating bphysmodel\n");
	int nargs = lua_gettop(L);
	double lx,ly,lz;
	double x,y,z;
	if(nargs > 4){
		//"graphicsfile","physicsfile",{position},{lookat}
		popvector3d(L,&lx,&ly,&lz);
	}
	if(nargs > 3){
		//"graphicsfile","physicsfile",{position}
		popvector3d(L,&x,&y,&z);
	}
	//"graphicsfile","physicsfile"

	double mass = lua_tonumber(L,-1);
	const char *ppath = lua_tostring(L,-2);
	//const char *gpath = lua_tostring(L,-3);
	lua_pop(L,3);

	//ISceneManager *smgr = device->getSceneManager();
	
	//printf("bphysnode, creating the scene node\n");

	////Create the scene node
	//IMesh *gmesh = smgr->getMesh(gpath);
	//ISceneNode *node = smgr->addMeshSceneNode(gmesh,0,-1,vector3df(x,y,z));

	printf("bphysnode, createing the physics body\n");
	//Create the physics body
	//IMesh *pmesh = smgr->getMesh(ppath);
	//printf("We have %d mesh buffers\n",pmesh->getMeshBufferCount());
	tinyobj_attrib_t attrib;
	tinyobj_shape_t *shapes = NULL;
	size_t meshcount;
	tinyobj_material_t *materials = NULL;
	size_t num_materials;

	size_t data_len = 0;
	FILE *objfile = fopen(ppath,"rb");
	fseek(objfile,0,SEEK_END);
	data_len = ftell(objfile);
	fseek(objfile,0,SEEK_SET);
	char *objdata = (char*)malloc(sizeof(char)*data_len);
	fread(objdata, sizeof(char), data_len, objfile);
	fclose(objfile);
	int err = tinyobj_parse_obj(&attrib, &shapes, &meshcount, &materials, &num_materials, objdata, data_len, 0);
	if(err != TINYOBJ_SUCCESS){
		printf("Tinyobj failed to load model:%s\n",ppath);
	}
	//u32 meshcount = pmesh->getMeshBufferCount();
	btTriangleMesh* trimesh = new btTriangleMesh();
	size_t numverts = attrib.num_face_num_verts;
	//size_t stride = 9; //9 = 3 position floats + 3 normal floats + 3 color floats
	size_t face_offset = 0;
	for(size_t i = 0; i < numverts; i++){
		for(size_t j = 0; j < (size_t)attrib.face_num_verts[i] / 3; j++){
			float v[3][3]; //this tri
			tinyobj_vertex_index_t idx0, idx1, idx2;
			idx0 = attrib.faces[face_offset + 3 * j + 0];
			idx1 = attrib.faces[face_offset + 3 * j + 1];
			idx2 = attrib.faces[face_offset + 3 * j + 2];
			for(short k = 0; k < 3; k++){
				int f0, f1, f2;
				f0 = idx0.v_idx;
				f1 = idx1.v_idx;
				f2 = idx2.v_idx;
				v[0][k] = attrib.vertices[3 * (size_t)f0 + k];
				v[1][k] = attrib.vertices[3 * (size_t)f1 + k];
				v[2][k] = attrib.vertices[3 * (size_t)f2 + k];
			}
			btVector3 b1,b2,b3;
			b1 = btVector3(v[0][0],v[0][1],v[0][2]);
			b2 = btVector3(v[1][0],v[1][1],v[1][2]);
			b3 = btVector3(v[2][0],v[2][1],v[2][2]);
			trimesh->addTriangle(b1,b2,b3);
		}
		face_offset += (size_t)attrib.face_num_verts[i];
	}
	printf("Done building trimesh\n");
	btCollisionShape *shape = new btBvhTriangleMeshShape(trimesh,true);
	btTransform tr;
	tr.setIdentity();
	tr.setOrigin(btVector3(x,y,z));
	printf("Created default motion shape\n");
	btDefaultMotionState *ms = new btDefaultMotionState(btTransform(tr));
	btVector3 li;
	shape->calculateLocalInertia(mass, li);
	btRigidBody *rb = new btRigidBody(mass,ms,shape,li);
	//rb->setUserPointer((void*) node);
	World->addRigidBody(rb);
	Objects.push_back(rb);
	printf("Rigid body finished\n");

	//Create the lua representation
	lua_newtable(L);
	lua_pushlightuserdata(L,rb);
	lua_setfield(L,-2,"rigidbody");
	//lua_pushlightuserdata(L,node);
	//lua_setfield(L,-2,"node");
	luaL_getmetatable(L,"phys.physmodel");
	lua_setmetatable(L,-2);
	printf("finished creating the lua representation\n");

	return 1;
}

static const luaL_reg bphysmodel_f[] = {
	{"newphysmodel",           newbphysmodel},
	{0,0},
};

static const luaL_reg bphysmodel_m[] = {
	{0, 0},
};

int bphysmodel_register(lua_State* L){

	//device = d;

	//printf("bphysmodel registered\n");

	luaL_newmetatable(L, "phys.physmodel");//{}
	luaL_register(L,NULL,bphysmodel_m);
	//luaL_register(L,NULL,igeneric_m); //Inherit all the things to do with scene nodes
	
	lua_getglobal(L,"phys");
	luaL_register(L,NULL,bphysmodel_f);

	return 1;
}