+ if (!convex_compatible || !physics_ode_allowconvex.integer)
+ {
+ // trimesh
+ dataID = dGeomTriMeshDataCreate();
+ dGeomTriMeshDataBuildSingle((dTriMeshDataID)dataID, (void*)ed->priv.server->ode_vertex3f, sizeof(float[3]), ed->priv.server->ode_numvertices, ed->priv.server->ode_element3i, ed->priv.server->ode_numtriangles*3, sizeof(int[3]));
+ ed->priv.server->ode_geom = (void *)dCreateTriMesh((dSpaceID)world->physics.ode_space, (dTriMeshDataID)dataID, NULL, NULL, NULL);
+ dMassSetBoxTotal(&mass, massval, geomsize[0], geomsize[1], geomsize[2]);
+ }
+ else
+ {
+ // VorteX: this code is unfinished in two ways
+ // - no duplicate vertex merging are done
+ // - triangles that shares same edge and havee sam plane are not merget into poly
+ // so, currently it only works for geosphere meshes with no UV
+
+ Con_Printf("Build convex hull for model %s...\n", model->name);
+ // build convex geometry from trimesh data
+ // this ensures that trimesh's triangles can form correct convex geometry
+ // not many of error checking is performed
+ // ODE's conve hull data consist of:
+ // planes : an array of planes in the form: normal X, normal Y, normal Z, distance
+ // points : an array of points X,Y,Z
+ // polygons: an array of indices to the points of each polygon,it should be the number of vertices
+ // followed by that amount of indices to "points" in counter clockwise order
+ polygonsData = polygons = (unsigned int *)Mem_Alloc(mempool, numtriangles*sizeof(int)*4);
+ planesData = planes = (dReal *)Mem_Alloc(mempool, numtriangles*sizeof(dReal)*4);
+ mapped = (qboolean *)Mem_Alloc(mempool, numvertices*sizeof(qboolean));
+ used = (qboolean *)Mem_Alloc(mempool, numtriangles*sizeof(qboolean));
+ memset(mapped, 0, numvertices*sizeof(qboolean));
+ memset(used, 0, numtriangles*sizeof(qboolean));
+ numplanes = numpoints = polyvert = 0;
+ // build convex hull
+ // todo: merge duplicated verts here
+ Con_Printf("Building...\n");
+ iv = ed->priv.server->ode_vertex3f;
+ for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
+ {
+ // already formed a polygon?
+ if (used[triangleindex])
+ continue;
+ // init polygon
+ // switch clockwise->counterclockwise
+ ie = &model->brush.collisionmesh->element3i[triangleindex*3];
+ used[triangleindex] = true;
+ TriangleNormal(&iv[ie[0]*3], &iv[ie[1]*3], &iv[ie[2]*3], planes);
+ VectorNormalize(planes);
+ polygons[0] = 3;
+ polygons[3] = (unsigned int)ie[0]; mapped[polygons[3]] = true;
+ polygons[2] = (unsigned int)ie[1]; mapped[polygons[2]] = true;
+ polygons[1] = (unsigned int)ie[2]; mapped[polygons[1]] = true;
+
+ // now find and include concave triangles
+ for (i = triangleindex; i < numtriangles; i++)
+ {
+ if (used[i])
+ continue;
+ // should share at least 2 vertexes
+ for (polyvert = 1; polyvert <= polygons[0]; polyvert++)
+ {
+ // todo: merge in triangles that shares an edge and have same plane here
+ }
+ }
+
+ // add polygon to overall stats
+ planes[3] = DotProduct(&iv[polygons[1]*3], planes);
+ polygons += (polygons[0]+1);
+ planes += 4;
+ numplanes++;
+ }
+ Mem_Free(used);
+ // save points
+ for (vertexindex = 0, numpoints = 0; vertexindex < numvertices; vertexindex++)
+ if (mapped[vertexindex])
+ numpoints++;
+ pointsData = (dReal *)Mem_Alloc(mempool, numpoints*sizeof(dReal)*3 + numplanes*sizeof(dReal)*4); // planes is appended
+ for (vertexindex = 0, numpoints = 0; vertexindex < numvertices; vertexindex++)
+ {
+ if (mapped[vertexindex])
+ {
+ VectorCopy(&iv[vertexindex*3], &pointsData[numpoints*3]);
+ numpoints++;
+ }
+ }
+ Mem_Free(mapped);
+ Con_Printf("Points: \n");
+ for (i = 0; i < (int)numpoints; i++)
+ Con_Printf("%3i: %3.1f %3.1f %3.1f\n", i, pointsData[i*3], pointsData[i*3+1], pointsData[i*3+2]);
+ // save planes
+ planes = planesData;
+ planesData = pointsData + numpoints*3;
+ memcpy(planesData, planes, numplanes*sizeof(dReal)*4);
+ Mem_Free(planes);
+ Con_Printf("planes...\n");
+ for (i = 0; i < numplanes; i++)
+ Con_Printf("%3i: %1.1f %1.1f %1.1f %1.1f\n", i, planesData[i*4], planesData[i*4 + 1], planesData[i*4 + 2], planesData[i*4 + 3]);
+ // save polygons
+ polyvert = polygons - polygonsData;
+ polygons = polygonsData;
+ polygonsData = (unsigned int *)Mem_Alloc(mempool, polyvert*sizeof(int));
+ memcpy(polygonsData, polygons, polyvert*sizeof(int));
+ Mem_Free(polygons);
+ Con_Printf("Polygons: \n");
+ polygons = polygonsData;
+ for (i = 0; i < numplanes; i++)
+ {
+ Con_Printf("%3i : %i ", i, polygons[0]);
+ for (triangleindex = 1; triangleindex <= (int)polygons[0]; triangleindex++)
+ Con_Printf("%3i ", polygons[triangleindex]);
+ polygons += (polygons[0]+1);
+ Con_Printf("\n");
+ }
+ Mem_Free(ed->priv.server->ode_element3i);
+ ed->priv.server->ode_element3i = (int *)polygonsData;
+ Mem_Free(ed->priv.server->ode_vertex3f);
+ ed->priv.server->ode_vertex3f = (float *)pointsData;
+ // check for properly build polygons by calculating the determinant of the 3x3 matrix composed of the first 3 points in the polygon
+ // this code is picked from ODE Source
+ Con_Printf("Check...\n");
+ polygons = polygonsData;
+ for (i = 0; i < numplanes; i++)
+ {
+ if((pointsData[(polygons[1]*3)+0]*pointsData[(polygons[2]*3)+1]*pointsData[(polygons[3]*3)+2] +
+ pointsData[(polygons[1]*3)+1]*pointsData[(polygons[2]*3)+2]*pointsData[(polygons[3]*3)+0] +
+ pointsData[(polygons[1]*3)+2]*pointsData[(polygons[2]*3)+0]*pointsData[(polygons[3]*3)+1] -
+ pointsData[(polygons[1]*3)+2]*pointsData[(polygons[2]*3)+1]*pointsData[(polygons[3]*3)+0] -
+ pointsData[(polygons[1]*3)+1]*pointsData[(polygons[2]*3)+0]*pointsData[(polygons[3]*3)+2] -
+ pointsData[(polygons[1]*3)+0]*pointsData[(polygons[2]*3)+2]*pointsData[(polygons[3]*3)+1]) < 0)
+ Con_Warnf("WARNING: Polygon %d is not defined counterclockwise\n", i);
+ if (planesData[(i*4)+3] < 0)
+ Con_Warnf("WARNING: Plane %d does not contain the origin\n", i);
+ polygons += (*polygons + 1);
+ }
+ // create geom
+ Con_Printf("Create geom...\n");
+ ed->priv.server->ode_geom = (void *)dCreateConvex((dSpaceID)world->physics.ode_space, planesData, numplanes, pointsData, numpoints, polygonsData);
+ dMassSetBoxTotal(&mass, massval, geomsize[0], geomsize[1], geomsize[2]);
+ Con_Printf("Done!\n");
+ }