add support for picking, using point 2 point constraint
allow to remove constraints by unique id added tiny wavefront loader, plan to use this instead of existing slow wavefront loader
This commit is contained in:
@@ -74,6 +74,14 @@ public:
|
|||||||
|
|
||||||
struct GpuDemoInternalData* getInternalData();
|
struct GpuDemoInternalData* getInternalData();
|
||||||
|
|
||||||
|
virtual bool mouseMoveCallback(float x,float y)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
virtual bool mouseButtonCallback(int button, int state, float x, float y)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -187,13 +187,21 @@ void MyButtonCallback(int buttonId, int state)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GpuDemo* sDemo = 0;
|
||||||
|
|
||||||
static void MyMouseMoveCallback( float x, float y)
|
static void MyMouseMoveCallback( float x, float y)
|
||||||
{
|
{
|
||||||
if (gui)
|
if (gui)
|
||||||
{
|
{
|
||||||
bool handled = gui ->mouseMoveCallback(x,y);
|
bool handled = gui ->mouseMoveCallback(x,y);
|
||||||
if (!handled)
|
if (!handled)
|
||||||
b3DefaultMouseMoveCallback(x,y);
|
{
|
||||||
|
if (sDemo)
|
||||||
|
handled = sDemo->mouseMoveCallback(x,y);
|
||||||
|
if (!handled)
|
||||||
|
b3DefaultMouseMoveCallback(x,y);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static void MyMouseButtonCallback(int button, int state, float x, float y)
|
static void MyMouseButtonCallback(int button, int state, float x, float y)
|
||||||
@@ -202,7 +210,14 @@ static void MyMouseButtonCallback(int button, int state, float x, float y)
|
|||||||
{
|
{
|
||||||
bool handled = gui->mouseButtonCallback(button,state,x,y);
|
bool handled = gui->mouseButtonCallback(button,state,x,y);
|
||||||
if (!handled)
|
if (!handled)
|
||||||
b3DefaultMouseButtonCallback(button,state,x,y);
|
{
|
||||||
|
//try picking first
|
||||||
|
if (sDemo)
|
||||||
|
handled = sDemo->mouseButtonCallback(button,state,x,y);
|
||||||
|
|
||||||
|
if (!handled)
|
||||||
|
b3DefaultMouseButtonCallback(button,state,x,y);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -647,6 +662,7 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
{
|
{
|
||||||
GpuDemo* demo = allDemos[selectedDemo]();
|
GpuDemo* demo = allDemos[selectedDemo]();
|
||||||
|
sDemo = demo;
|
||||||
// demo->myinit();
|
// demo->myinit();
|
||||||
bool useGpu = false;
|
bool useGpu = false;
|
||||||
|
|
||||||
@@ -919,6 +935,8 @@ int main(int argc, char* argv[])
|
|||||||
delete ci.m_instancingRenderer;
|
delete ci.m_instancingRenderer;
|
||||||
|
|
||||||
delete demo;
|
delete demo;
|
||||||
|
sDemo = 0;
|
||||||
|
|
||||||
if (detailsFile)
|
if (detailsFile)
|
||||||
{
|
{
|
||||||
fclose(detailsFile);
|
fclose(detailsFile);
|
||||||
|
|||||||
@@ -335,7 +335,7 @@ void GpuRaytraceScene::renderScene2()
|
|||||||
shadowRays[i].m_from = hits[i].m_hitPoint;
|
shadowRays[i].m_from = hits[i].m_hitPoint;
|
||||||
shadowRays[i].m_to = lightPos;
|
shadowRays[i].m_to = lightPos;
|
||||||
shadowHits[i].m_hitFraction=1.f;
|
shadowHits[i].m_hitFraction=1.f;
|
||||||
shadowHits[i].m_hitResult2 = hits[i].m_hitResult0;
|
shadowHits[i].m_hitBody = hits[i].m_hitBody;
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
shadowRays[i].m_from.setValue(0,0,0);
|
shadowRays[i].m_from.setValue(0,0,0);
|
||||||
@@ -377,7 +377,7 @@ void GpuRaytraceScene::renderScene2()
|
|||||||
m_raytraceData->m_texels[(i)*3+1] = 128+128.f*hits[i].m_hitNormal.y;
|
m_raytraceData->m_texels[(i)*3+1] = 128+128.f*hits[i].m_hitNormal.y;
|
||||||
m_raytraceData->m_texels[(i)*3+2] = 128+128.f*hits[i].m_hitNormal.z;
|
m_raytraceData->m_texels[(i)*3+2] = 128+128.f*hits[i].m_hitNormal.z;
|
||||||
|
|
||||||
if (hits[i].m_hitResult0==0)
|
if (hits[i].m_hitBody==0)
|
||||||
{
|
{
|
||||||
m_raytraceData->m_texels[(i)*3+0] = 255;
|
m_raytraceData->m_texels[(i)*3+0] = 255;
|
||||||
m_raytraceData->m_texels[(i)*3+1] = 255;
|
m_raytraceData->m_texels[(i)*3+1] = 255;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
#include "Bullet3OpenCL/RigidBody/b3Config.h"
|
#include "Bullet3OpenCL/RigidBody/b3Config.h"
|
||||||
#include "GpuRigidBodyDemoInternalData.h"
|
#include "GpuRigidBodyDemoInternalData.h"
|
||||||
#include "Bullet3Collision/BroadPhaseCollision/b3DynamicBvhBroadphase.h"
|
#include "Bullet3Collision/BroadPhaseCollision/b3DynamicBvhBroadphase.h"
|
||||||
|
#include "Bullet3Collision/NarrowPhaseCollision/b3RigidBodyCL.h"
|
||||||
|
|
||||||
static b3KeyboardCallback oldCallback = 0;
|
static b3KeyboardCallback oldCallback = 0;
|
||||||
extern bool gReset;
|
extern bool gReset;
|
||||||
@@ -130,6 +131,7 @@ void GpuRigidBodyDemo::initPhysics(const ConstructionInfo& ci)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
m_instancingRenderer->writeTransforms();
|
m_instancingRenderer->writeTransforms();
|
||||||
|
|
||||||
@@ -165,6 +167,7 @@ void GpuRigidBodyDemo::clientMoveAndDisplay()
|
|||||||
{
|
{
|
||||||
bool animate=true;
|
bool animate=true;
|
||||||
int numObjects= m_data->m_rigidBodyPipeline->getNumBodies();
|
int numObjects= m_data->m_rigidBodyPipeline->getNumBodies();
|
||||||
|
//printf("numObjects=%d\n",numObjects);
|
||||||
if (numObjects > m_instancingRenderer->getInstanceCapacity())
|
if (numObjects > m_instancingRenderer->getInstanceCapacity())
|
||||||
{
|
{
|
||||||
static bool once = true;
|
static bool once = true;
|
||||||
@@ -242,3 +245,180 @@ void GpuRigidBodyDemo::clientMoveAndDisplay()
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
b3Vector3 GpuRigidBodyDemo::getRayTo(int x,int y)
|
||||||
|
{
|
||||||
|
if (!m_instancingRenderer)
|
||||||
|
return b3Vector3(0,0,0);
|
||||||
|
|
||||||
|
float top = 1.f;
|
||||||
|
float bottom = -1.f;
|
||||||
|
float nearPlane = 1.f;
|
||||||
|
float tanFov = (top-bottom)*0.5f / nearPlane;
|
||||||
|
float fov = b3Scalar(2.0) * b3Atan(tanFov);
|
||||||
|
|
||||||
|
b3Vector3 camPos,camTarget;
|
||||||
|
m_instancingRenderer->getCameraPosition(camPos);
|
||||||
|
m_instancingRenderer->getCameraTargetPosition(camTarget);
|
||||||
|
|
||||||
|
b3Vector3 rayFrom = camPos;
|
||||||
|
b3Vector3 rayForward = (camTarget-camPos);
|
||||||
|
rayForward.normalize();
|
||||||
|
float farPlane = 10000.f;
|
||||||
|
rayForward*= farPlane;
|
||||||
|
|
||||||
|
b3Vector3 rightOffset;
|
||||||
|
b3Vector3 m_cameraUp(0,1,0);
|
||||||
|
b3Vector3 vertical = m_cameraUp;
|
||||||
|
|
||||||
|
b3Vector3 hor;
|
||||||
|
hor = rayForward.cross(vertical);
|
||||||
|
hor.normalize();
|
||||||
|
vertical = hor.cross(rayForward);
|
||||||
|
vertical.normalize();
|
||||||
|
|
||||||
|
float tanfov = tanf(0.5f*fov);
|
||||||
|
|
||||||
|
|
||||||
|
hor *= 2.f * farPlane * tanfov;
|
||||||
|
vertical *= 2.f * farPlane * tanfov;
|
||||||
|
|
||||||
|
b3Scalar aspect;
|
||||||
|
float width = m_instancingRenderer->getScreenWidth();
|
||||||
|
float height = m_instancingRenderer->getScreenHeight();
|
||||||
|
|
||||||
|
aspect = width / height;
|
||||||
|
|
||||||
|
hor*=aspect;
|
||||||
|
|
||||||
|
|
||||||
|
b3Vector3 rayToCenter = rayFrom + rayForward;
|
||||||
|
b3Vector3 dHor = hor * 1.f/width;
|
||||||
|
b3Vector3 dVert = vertical * 1.f/height;
|
||||||
|
|
||||||
|
|
||||||
|
b3Vector3 rayTo = rayToCenter - 0.5f * hor + 0.5f * vertical;
|
||||||
|
rayTo += b3Scalar(x) * dHor;
|
||||||
|
rayTo -= b3Scalar(y) * dVert;
|
||||||
|
return rayTo;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool GpuRigidBodyDemo::mouseMoveCallback(float x,float y)
|
||||||
|
{
|
||||||
|
if (m_data->m_pickBody>=0 && m_data->m_pickConstraint>=0)
|
||||||
|
{
|
||||||
|
m_data->m_rigidBodyPipeline->removeConstraintByUid(m_data->m_pickConstraint);
|
||||||
|
b3Vector3 newRayTo = getRayTo(x,y);
|
||||||
|
b3Vector3 rayFrom;
|
||||||
|
b3Vector3 oldPivotInB = m_data->m_pickPivotInB;
|
||||||
|
b3Vector3 newPivotB;
|
||||||
|
m_instancingRenderer->getCameraPosition(rayFrom);
|
||||||
|
b3Vector3 dir = newRayTo-rayFrom;
|
||||||
|
dir.normalize();
|
||||||
|
dir *= m_data->m_pickDistance;
|
||||||
|
newPivotB = rayFrom + dir;
|
||||||
|
m_data->m_pickPivotInB = newPivotB;
|
||||||
|
m_data->m_pickConstraint = m_data->m_rigidBodyPipeline->createPoint2PointConstraint(m_data->m_pickBody,m_data->m_pickFixedBody,m_data->m_pickPivotInA,m_data->m_pickPivotInB);
|
||||||
|
m_data->m_rigidBodyPipeline->writeAllInstancesToGpu();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool GpuRigidBodyDemo::mouseButtonCallback(int button, int state, float x, float y)
|
||||||
|
{
|
||||||
|
if (state==1)
|
||||||
|
{
|
||||||
|
if (button==0)
|
||||||
|
{
|
||||||
|
b3AlignedObjectArray<b3RayInfo> rays;
|
||||||
|
b3AlignedObjectArray<b3RayHit> hitResults;
|
||||||
|
b3Vector3 camPos;
|
||||||
|
m_instancingRenderer->getCameraPosition(camPos);
|
||||||
|
|
||||||
|
b3RayInfo ray;
|
||||||
|
ray.m_from = camPos;
|
||||||
|
ray.m_to = getRayTo(x,y);
|
||||||
|
rays.push_back(ray);
|
||||||
|
b3RayHit hit;
|
||||||
|
hit.m_hitFraction = 1.f;
|
||||||
|
hitResults.push_back(hit);
|
||||||
|
m_data->m_rigidBodyPipeline->castRays(rays,hitResults);
|
||||||
|
if (hitResults[0].m_hitFraction<1.f)
|
||||||
|
{
|
||||||
|
|
||||||
|
int hitBodyA = hitResults[0].m_hitBody;
|
||||||
|
if (m_data->m_np->getBodiesCpu()[hitBodyA].m_invMass)
|
||||||
|
{
|
||||||
|
//printf("hit!\n");
|
||||||
|
m_data->m_np->readbackAllBodiesToCpu();
|
||||||
|
m_data->m_pickBody = hitBodyA;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//pivotInA
|
||||||
|
b3Vector3 pivotInB;
|
||||||
|
pivotInB.setInterpolate3(ray.m_from,ray.m_to,hitResults[0].m_hitFraction);
|
||||||
|
b3Vector3 posA;
|
||||||
|
b3Quaternion ornA;
|
||||||
|
m_data->m_np->getObjectTransformFromCpu(posA,ornA,hitBodyA);
|
||||||
|
b3Transform tr;
|
||||||
|
tr.setOrigin(posA);
|
||||||
|
tr.setRotation(ornA);
|
||||||
|
b3Vector3 pivotInA = tr.inverse()*pivotInB;
|
||||||
|
if (m_data->m_pickFixedBody<0)
|
||||||
|
{
|
||||||
|
b3Vector3 pos(0,0,0);
|
||||||
|
b3Quaternion orn(0,0,0,1);
|
||||||
|
int fixedSphere = m_data->m_np->registerConvexHullShape(0,0,0,0);//>registerSphereShape(0.1);
|
||||||
|
m_data->m_pickFixedBody = m_data->m_rigidBodyPipeline->registerPhysicsInstance(0,pos,orn,fixedSphere,0,false);
|
||||||
|
|
||||||
|
if (m_data->m_pickGraphicsShapeIndex<0)
|
||||||
|
{
|
||||||
|
int strideInBytes = 9*sizeof(float);
|
||||||
|
int numVertices = sizeof(point_sphere_vertices)/strideInBytes;
|
||||||
|
int numIndices = sizeof(point_sphere_indices)/sizeof(int);
|
||||||
|
m_data->m_pickGraphicsShapeIndex = m_instancingRenderer->registerShape(&point_sphere_vertices[0],numVertices,point_sphere_indices,numIndices,B3_GL_POINTS);
|
||||||
|
float color[4] ={1,0,0,1};
|
||||||
|
float scaling[4]={1,1,1,1};
|
||||||
|
|
||||||
|
m_data->m_pickGraphicsShapeInstance = m_instancingRenderer->registerGraphicsInstance(m_data->m_pickGraphicsShapeIndex,pivotInB,orn,color,scaling);
|
||||||
|
m_instancingRenderer->writeTransforms();
|
||||||
|
delete m_data->m_instancePosOrnColor;
|
||||||
|
m_data->m_instancePosOrnColor=0;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
m_instancingRenderer->writeSingleInstanceTransformToCPU(pivotInB,orn,m_data->m_pickGraphicsShapeInstance);
|
||||||
|
m_instancingRenderer->writeSingleInstanceTransformToGPU(pivotInB,orn,m_data->m_pickGraphicsShapeInstance);
|
||||||
|
m_data->m_np->setObjectTransformCpu(pos,orn,m_data->m_pickFixedBody);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
pivotInB.w = 0.f;
|
||||||
|
m_data->m_pickPivotInA = pivotInA;
|
||||||
|
m_data->m_pickPivotInB = pivotInB;
|
||||||
|
m_data->m_pickConstraint = m_data->m_rigidBodyPipeline->createPoint2PointConstraint(hitBodyA,m_data->m_pickFixedBody,pivotInA,pivotInB);//hitResults[0].m_hitResult0
|
||||||
|
m_data->m_rigidBodyPipeline->writeAllInstancesToGpu();
|
||||||
|
m_data->m_np->writeAllBodiesToGpu();
|
||||||
|
m_data->m_pickDistance = (pivotInB-camPos).length();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
if (button==0)
|
||||||
|
{
|
||||||
|
if (m_data->m_pickConstraint>=0)
|
||||||
|
{
|
||||||
|
m_data->m_rigidBodyPipeline->removeConstraintByUid(m_data->m_pickConstraint);
|
||||||
|
m_data->m_pickConstraint=-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//printf("button=%d, state=%d\n",button,state);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
#define GPU_RIGID_BODY_DEMO_H
|
#define GPU_RIGID_BODY_DEMO_H
|
||||||
|
|
||||||
#include "../GpuDemo.h"
|
#include "../GpuDemo.h"
|
||||||
|
#include "Bullet3Common/b3Vector3.h"
|
||||||
|
|
||||||
class GpuRigidBodyDemo : public GpuDemo
|
class GpuRigidBodyDemo : public GpuDemo
|
||||||
{
|
{
|
||||||
@@ -38,6 +39,10 @@ public:
|
|||||||
|
|
||||||
virtual void clientMoveAndDisplay();
|
virtual void clientMoveAndDisplay();
|
||||||
|
|
||||||
|
//for picking
|
||||||
|
b3Vector3 getRayTo(int x,int y);
|
||||||
|
virtual bool mouseMoveCallback(float x,float y);
|
||||||
|
virtual bool mouseButtonCallback(int button, int state, float x, float y);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -18,12 +18,28 @@ struct GpuRigidBodyDemoInternalData
|
|||||||
class b3GpuSapBroadphase* m_bp;
|
class b3GpuSapBroadphase* m_bp;
|
||||||
class b3DynamicBvhBroadphase* m_broadphaseDbvt;
|
class b3DynamicBvhBroadphase* m_broadphaseDbvt;
|
||||||
|
|
||||||
|
b3Vector3 m_pickPivotInA;
|
||||||
|
b3Vector3 m_pickPivotInB;
|
||||||
|
float m_pickDistance;
|
||||||
|
int m_pickBody;
|
||||||
|
int m_pickConstraint;
|
||||||
|
|
||||||
|
int m_pickFixedBody;
|
||||||
|
int m_pickGraphicsShapeIndex;
|
||||||
|
int m_pickGraphicsShapeInstance;
|
||||||
|
|
||||||
GpuRigidBodyDemoInternalData()
|
GpuRigidBodyDemoInternalData()
|
||||||
:m_instancePosOrnColor(0),
|
:m_instancePosOrnColor(0),
|
||||||
m_copyTransformsToVBOKernel(0), m_rigidBodyPipeline(0),
|
m_copyTransformsToVBOKernel(0), m_rigidBodyPipeline(0),
|
||||||
m_np(0),
|
m_np(0),
|
||||||
m_bp(0),
|
m_bp(0),
|
||||||
m_broadphaseDbvt(0)
|
m_broadphaseDbvt(0),
|
||||||
|
m_pickConstraint(-1),
|
||||||
|
m_pickFixedBody(-1),
|
||||||
|
m_pickGraphicsShapeIndex(-1),
|
||||||
|
m_pickGraphicsShapeInstance(-1),
|
||||||
|
m_pickBody(-1)
|
||||||
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
654
Demos3/Wavefront/tiny_obj_loader.cpp
Normal file
654
Demos3/Wavefront/tiny_obj_loader.cpp
Normal file
@@ -0,0 +1,654 @@
|
|||||||
|
//
|
||||||
|
// Copyright 2012-2013, Syoyo Fujita.
|
||||||
|
//
|
||||||
|
// Licensed under 2-clause BSD liecense.
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
// version 0.9.5: Parse multiple group name.
|
||||||
|
// Add support of specifying the base path to load material file.
|
||||||
|
// version 0.9.4: Initial suupport of group tag(g)
|
||||||
|
// version 0.9.3: Fix parsing triple 'x/y/z'
|
||||||
|
// version 0.9.2: Add more .mtl load support
|
||||||
|
// version 0.9.1: Add initial .mtl load support
|
||||||
|
// version 0.9.0: Initial
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstring>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#include "tiny_obj_loader.h"
|
||||||
|
|
||||||
|
namespace tinyobj {
|
||||||
|
|
||||||
|
struct vertex_index {
|
||||||
|
int v_idx, vt_idx, vn_idx;
|
||||||
|
vertex_index() {};
|
||||||
|
vertex_index(int idx) : v_idx(idx), vt_idx(idx), vn_idx(idx) {};
|
||||||
|
vertex_index(int vidx, int vtidx, int vnidx) : v_idx(vidx), vt_idx(vtidx), vn_idx(vnidx) {};
|
||||||
|
|
||||||
|
};
|
||||||
|
// for std::map
|
||||||
|
static inline bool operator<(const vertex_index& a, const vertex_index& b)
|
||||||
|
{
|
||||||
|
if (a.v_idx != b.v_idx) return (a.v_idx < b.v_idx);
|
||||||
|
if (a.vn_idx != b.vn_idx) return (a.vn_idx < b.vn_idx);
|
||||||
|
if (a.vt_idx != b.vt_idx) return (a.vt_idx < b.vt_idx);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct obj_shape {
|
||||||
|
std::vector<float> v;
|
||||||
|
std::vector<float> vn;
|
||||||
|
std::vector<float> vt;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline bool isSpace(const char c) {
|
||||||
|
return (c == ' ') || (c == '\t');
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool isNewLine(const char c) {
|
||||||
|
return (c == '\r') || (c == '\n') || (c == '\0');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make index zero-base, and also support relative index.
|
||||||
|
static inline int fixIndex(int idx, int n)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (idx > 0) {
|
||||||
|
i = idx - 1;
|
||||||
|
} else if (idx == 0) {
|
||||||
|
i = 0;
|
||||||
|
} else { // negative value = relative
|
||||||
|
i = n + idx;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline std::string parseString(const char*& token)
|
||||||
|
{
|
||||||
|
std::string s;
|
||||||
|
int b = strspn(token, " \t");
|
||||||
|
int e = strcspn(token, " \t\r");
|
||||||
|
s = std::string(&token[b], &token[e]);
|
||||||
|
|
||||||
|
token += (e - b);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline float parseFloat(const char*& token)
|
||||||
|
{
|
||||||
|
token += strspn(token, " \t");
|
||||||
|
float f = (float)atof(token);
|
||||||
|
token += strcspn(token, " \t\r");
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void parseFloat2(
|
||||||
|
float& x, float& y,
|
||||||
|
const char*& token)
|
||||||
|
{
|
||||||
|
x = parseFloat(token);
|
||||||
|
y = parseFloat(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void parseFloat3(
|
||||||
|
float& x, float& y, float& z,
|
||||||
|
const char*& token)
|
||||||
|
{
|
||||||
|
x = parseFloat(token);
|
||||||
|
y = parseFloat(token);
|
||||||
|
z = parseFloat(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Parse triples: i, i/j/k, i//k, i/j
|
||||||
|
static vertex_index parseTriple(
|
||||||
|
const char* &token,
|
||||||
|
int vsize,
|
||||||
|
int vnsize,
|
||||||
|
int vtsize)
|
||||||
|
{
|
||||||
|
vertex_index vi(-1);
|
||||||
|
|
||||||
|
vi.v_idx = fixIndex(atoi(token), vsize);
|
||||||
|
token += strcspn(token, "/ \t\r");
|
||||||
|
if (token[0] != '/') {
|
||||||
|
return vi;
|
||||||
|
}
|
||||||
|
token++;
|
||||||
|
|
||||||
|
// i//k
|
||||||
|
if (token[0] == '/') {
|
||||||
|
token++;
|
||||||
|
vi.vn_idx = fixIndex(atoi(token), vnsize);
|
||||||
|
token += strcspn(token, "/ \t\r");
|
||||||
|
return vi;
|
||||||
|
}
|
||||||
|
|
||||||
|
// i/j/k or i/j
|
||||||
|
vi.vt_idx = fixIndex(atoi(token), vtsize);
|
||||||
|
token += strcspn(token, "/ \t\r");
|
||||||
|
if (token[0] != '/') {
|
||||||
|
return vi;
|
||||||
|
}
|
||||||
|
|
||||||
|
// i/j/k
|
||||||
|
token++; // skip '/'
|
||||||
|
vi.vn_idx = fixIndex(atoi(token), vnsize);
|
||||||
|
token += strcspn(token, "/ \t\r");
|
||||||
|
return vi;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int
|
||||||
|
updateVertex(
|
||||||
|
std::map<vertex_index, unsigned int>& vertexCache,
|
||||||
|
std::vector<float>& positions,
|
||||||
|
std::vector<float>& normals,
|
||||||
|
std::vector<float>& texcoords,
|
||||||
|
const std::vector<float>& in_positions,
|
||||||
|
const std::vector<float>& in_normals,
|
||||||
|
const std::vector<float>& in_texcoords,
|
||||||
|
const vertex_index& i)
|
||||||
|
{
|
||||||
|
const std::map<vertex_index, unsigned int>::iterator it = vertexCache.find(i);
|
||||||
|
|
||||||
|
if (it != vertexCache.end()) {
|
||||||
|
// found cache
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(in_positions.size() > (3*i.v_idx+2));
|
||||||
|
|
||||||
|
positions.push_back(in_positions[3*i.v_idx+0]);
|
||||||
|
positions.push_back(in_positions[3*i.v_idx+1]);
|
||||||
|
positions.push_back(in_positions[3*i.v_idx+2]);
|
||||||
|
|
||||||
|
if (i.vn_idx >= 0) {
|
||||||
|
normals.push_back(in_normals[3*i.vn_idx+0]);
|
||||||
|
normals.push_back(in_normals[3*i.vn_idx+1]);
|
||||||
|
normals.push_back(in_normals[3*i.vn_idx+2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i.vt_idx >= 0) {
|
||||||
|
texcoords.push_back(in_texcoords[2*i.vt_idx+0]);
|
||||||
|
texcoords.push_back(in_texcoords[2*i.vt_idx+1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int idx = positions.size() / 3 - 1;
|
||||||
|
vertexCache[i] = idx;
|
||||||
|
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
exportFaceGroupToShape(
|
||||||
|
shape_t& shape,
|
||||||
|
const std::vector<float> in_positions,
|
||||||
|
const std::vector<float> in_normals,
|
||||||
|
const std::vector<float> in_texcoords,
|
||||||
|
const std::vector<std::vector<vertex_index> >& faceGroup,
|
||||||
|
const material_t material,
|
||||||
|
const std::string name)
|
||||||
|
{
|
||||||
|
if (faceGroup.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flattened version of vertex data
|
||||||
|
std::vector<float> positions;
|
||||||
|
std::vector<float> normals;
|
||||||
|
std::vector<float> texcoords;
|
||||||
|
std::map<vertex_index, unsigned int> vertexCache;
|
||||||
|
std::vector<unsigned int> indices;
|
||||||
|
|
||||||
|
// Flatten vertices and indices
|
||||||
|
for (size_t i = 0; i < faceGroup.size(); i++) {
|
||||||
|
const std::vector<vertex_index>& face = faceGroup[i];
|
||||||
|
|
||||||
|
vertex_index i0 = face[0];
|
||||||
|
vertex_index i1(-1);
|
||||||
|
vertex_index i2 = face[1];
|
||||||
|
|
||||||
|
size_t npolys = face.size();
|
||||||
|
|
||||||
|
// Polygon -> triangle fan conversion
|
||||||
|
for (size_t k = 2; k < npolys; k++) {
|
||||||
|
i1 = i2;
|
||||||
|
i2 = face[k];
|
||||||
|
|
||||||
|
unsigned int v0 = updateVertex(vertexCache, positions, normals, texcoords, in_positions, in_normals, in_texcoords, i0);
|
||||||
|
unsigned int v1 = updateVertex(vertexCache, positions, normals, texcoords, in_positions, in_normals, in_texcoords, i1);
|
||||||
|
unsigned int v2 = updateVertex(vertexCache, positions, normals, texcoords, in_positions, in_normals, in_texcoords, i2);
|
||||||
|
|
||||||
|
indices.push_back(v0);
|
||||||
|
indices.push_back(v1);
|
||||||
|
indices.push_back(v2);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Construct shape.
|
||||||
|
//
|
||||||
|
shape.name = name;
|
||||||
|
shape.mesh.positions.swap(positions);
|
||||||
|
shape.mesh.normals.swap(normals);
|
||||||
|
shape.mesh.texcoords.swap(texcoords);
|
||||||
|
shape.mesh.indices.swap(indices);
|
||||||
|
|
||||||
|
shape.material = material;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void InitMaterial(material_t& material) {
|
||||||
|
material.name = "";
|
||||||
|
material.ambient_texname = "";
|
||||||
|
material.diffuse_texname = "";
|
||||||
|
material.specular_texname = "";
|
||||||
|
material.normal_texname = "";
|
||||||
|
for (int i = 0; i < 3; i ++) {
|
||||||
|
material.ambient[i] = 0.f;
|
||||||
|
material.diffuse[i] = 0.f;
|
||||||
|
material.specular[i] = 0.f;
|
||||||
|
material.transmittance[i] = 0.f;
|
||||||
|
material.emission[i] = 0.f;
|
||||||
|
}
|
||||||
|
material.shininess = 1.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string LoadMtl (
|
||||||
|
std::map<std::string, material_t>& material_map,
|
||||||
|
const char* filename,
|
||||||
|
const char* mtl_basepath)
|
||||||
|
{
|
||||||
|
material_map.clear();
|
||||||
|
std::stringstream err;
|
||||||
|
|
||||||
|
std::string filepath;
|
||||||
|
|
||||||
|
if (mtl_basepath) {
|
||||||
|
filepath = std::string(mtl_basepath) + std::string(filename);
|
||||||
|
} else {
|
||||||
|
filepath = std::string(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ifstream ifs(filepath.c_str());
|
||||||
|
if (!ifs) {
|
||||||
|
err << "Cannot open file [" << filepath << "]" << std::endl;
|
||||||
|
return err.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
material_t material;
|
||||||
|
|
||||||
|
int maxchars = 8192; // Alloc enough size.
|
||||||
|
std::vector<char> buf(maxchars); // Alloc enough size.
|
||||||
|
while (ifs.peek() != -1) {
|
||||||
|
ifs.getline(&buf[0], maxchars);
|
||||||
|
|
||||||
|
std::string linebuf(&buf[0]);
|
||||||
|
|
||||||
|
// Trim newline '\r\n' or '\r'
|
||||||
|
if (linebuf.size() > 0) {
|
||||||
|
if (linebuf[linebuf.size()-1] == '\n') linebuf.erase(linebuf.size()-1);
|
||||||
|
}
|
||||||
|
if (linebuf.size() > 0) {
|
||||||
|
if (linebuf[linebuf.size()-1] == '\n') linebuf.erase(linebuf.size()-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip if empty line.
|
||||||
|
if (linebuf.empty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip leading space.
|
||||||
|
const char* token = linebuf.c_str();
|
||||||
|
token += strspn(token, " \t");
|
||||||
|
|
||||||
|
assert(token);
|
||||||
|
if (token[0] == '\0') continue; // empty line
|
||||||
|
|
||||||
|
if (token[0] == '#') continue; // comment line
|
||||||
|
|
||||||
|
// new mtl
|
||||||
|
if ((0 == strncmp(token, "newmtl", 6)) && isSpace((token[6]))) {
|
||||||
|
// flush previous material.
|
||||||
|
material_map.insert(std::pair<std::string, material_t>(material.name, material));
|
||||||
|
|
||||||
|
// initial temporary material
|
||||||
|
InitMaterial(material);
|
||||||
|
|
||||||
|
// set new mtl name
|
||||||
|
char namebuf[4096];
|
||||||
|
token += 7;
|
||||||
|
sscanf(token, "%s", namebuf);
|
||||||
|
material.name = namebuf;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ambient
|
||||||
|
if (token[0] == 'K' && token[1] == 'a' && isSpace((token[2]))) {
|
||||||
|
token += 2;
|
||||||
|
float r, g, b;
|
||||||
|
parseFloat3(r, g, b, token);
|
||||||
|
material.ambient[0] = r;
|
||||||
|
material.ambient[1] = g;
|
||||||
|
material.ambient[2] = b;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// diffuse
|
||||||
|
if (token[0] == 'K' && token[1] == 'd' && isSpace((token[2]))) {
|
||||||
|
token += 2;
|
||||||
|
float r, g, b;
|
||||||
|
parseFloat3(r, g, b, token);
|
||||||
|
material.diffuse[0] = r;
|
||||||
|
material.diffuse[1] = g;
|
||||||
|
material.diffuse[2] = b;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// specular
|
||||||
|
if (token[0] == 'K' && token[1] == 's' && isSpace((token[2]))) {
|
||||||
|
token += 2;
|
||||||
|
float r, g, b;
|
||||||
|
parseFloat3(r, g, b, token);
|
||||||
|
material.specular[0] = r;
|
||||||
|
material.specular[1] = g;
|
||||||
|
material.specular[2] = b;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// specular
|
||||||
|
if (token[0] == 'K' && token[1] == 't' && isSpace((token[2]))) {
|
||||||
|
token += 2;
|
||||||
|
float r, g, b;
|
||||||
|
parseFloat3(r, g, b, token);
|
||||||
|
material.specular[0] = r;
|
||||||
|
material.specular[1] = g;
|
||||||
|
material.specular[2] = b;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// emission
|
||||||
|
if(token[0] == 'K' && token[1] == 'e' && isSpace(token[2])) {
|
||||||
|
token += 2;
|
||||||
|
float r, g, b;
|
||||||
|
parseFloat3(r, g, b, token);
|
||||||
|
material.emission[0] = r;
|
||||||
|
material.emission[1] = g;
|
||||||
|
material.emission[2] = b;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// shininess
|
||||||
|
if(token[0] == 'N' && token[1] == 's' && isSpace(token[2])) {
|
||||||
|
token += 2;
|
||||||
|
material.shininess = parseFloat(token);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ambient texture
|
||||||
|
if ((0 == strncmp(token, "map_Ka", 6)) && isSpace(token[6])) {
|
||||||
|
token += 7;
|
||||||
|
material.ambient_texname = token;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// diffuse texture
|
||||||
|
if ((0 == strncmp(token, "map_Kd", 6)) && isSpace(token[6])) {
|
||||||
|
token += 7;
|
||||||
|
material.diffuse_texname = token;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// specular texture
|
||||||
|
if ((0 == strncmp(token, "map_Ks", 6)) && isSpace(token[6])) {
|
||||||
|
token += 7;
|
||||||
|
material.specular_texname = token;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// normal texture
|
||||||
|
if ((0 == strncmp(token, "map_Ns", 6)) && isSpace(token[6])) {
|
||||||
|
token += 7;
|
||||||
|
material.normal_texname = token;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// unknown parameter
|
||||||
|
const char* _space = strchr(token, ' ');
|
||||||
|
if(!_space) {
|
||||||
|
_space = strchr(token, '\t');
|
||||||
|
}
|
||||||
|
if(_space) {
|
||||||
|
int len = _space - token;
|
||||||
|
std::string key(token, len);
|
||||||
|
std::string value = _space + 1;
|
||||||
|
material.unknown_parameter.insert(std::pair<std::string, std::string>(key, value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// flush last material.
|
||||||
|
material_map.insert(std::pair<std::string, material_t>(material.name, material));
|
||||||
|
|
||||||
|
return err.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string
|
||||||
|
LoadObj(
|
||||||
|
std::vector<shape_t>& shapes,
|
||||||
|
const char* filename,
|
||||||
|
const char* mtl_basepath)
|
||||||
|
{
|
||||||
|
|
||||||
|
shapes.clear();
|
||||||
|
|
||||||
|
std::stringstream err;
|
||||||
|
|
||||||
|
std::ifstream ifs(filename);
|
||||||
|
if (!ifs) {
|
||||||
|
err << "Cannot open file [" << filename << "]" << std::endl;
|
||||||
|
return err.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<float> v;
|
||||||
|
std::vector<float> vn;
|
||||||
|
std::vector<float> vt;
|
||||||
|
std::vector<std::vector<vertex_index> > faceGroup;
|
||||||
|
std::string name;
|
||||||
|
|
||||||
|
// material
|
||||||
|
std::map<std::string, material_t> material_map;
|
||||||
|
material_t material;
|
||||||
|
|
||||||
|
int maxchars = 8192; // Alloc enough size.
|
||||||
|
std::vector<char> buf(maxchars); // Alloc enough size.
|
||||||
|
while (ifs.peek() != -1) {
|
||||||
|
ifs.getline(&buf[0], maxchars);
|
||||||
|
|
||||||
|
std::string linebuf(&buf[0]);
|
||||||
|
|
||||||
|
// Trim newline '\r\n' or '\r'
|
||||||
|
if (linebuf.size() > 0) {
|
||||||
|
if (linebuf[linebuf.size()-1] == '\n') linebuf.erase(linebuf.size()-1);
|
||||||
|
}
|
||||||
|
if (linebuf.size() > 0) {
|
||||||
|
if (linebuf[linebuf.size()-1] == '\n') linebuf.erase(linebuf.size()-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip if empty line.
|
||||||
|
if (linebuf.empty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip leading space.
|
||||||
|
const char* token = linebuf.c_str();
|
||||||
|
token += strspn(token, " \t");
|
||||||
|
|
||||||
|
assert(token);
|
||||||
|
if (token[0] == '\0') continue; // empty line
|
||||||
|
|
||||||
|
if (token[0] == '#') continue; // comment line
|
||||||
|
|
||||||
|
// vertex
|
||||||
|
if (token[0] == 'v' && isSpace((token[1]))) {
|
||||||
|
token += 2;
|
||||||
|
float x, y, z;
|
||||||
|
parseFloat3(x, y, z, token);
|
||||||
|
v.push_back(x);
|
||||||
|
v.push_back(y);
|
||||||
|
v.push_back(z);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// normal
|
||||||
|
if (token[0] == 'v' && token[1] == 'n' && isSpace((token[2]))) {
|
||||||
|
token += 3;
|
||||||
|
float x, y, z;
|
||||||
|
parseFloat3(x, y, z, token);
|
||||||
|
vn.push_back(x);
|
||||||
|
vn.push_back(y);
|
||||||
|
vn.push_back(z);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// texcoord
|
||||||
|
if (token[0] == 'v' && token[1] == 't' && isSpace((token[2]))) {
|
||||||
|
token += 3;
|
||||||
|
float x, y;
|
||||||
|
parseFloat2(x, y, token);
|
||||||
|
vt.push_back(x);
|
||||||
|
vt.push_back(y);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// face
|
||||||
|
if (token[0] == 'f' && isSpace((token[1]))) {
|
||||||
|
token += 2;
|
||||||
|
token += strspn(token, " \t");
|
||||||
|
|
||||||
|
std::vector<vertex_index> face;
|
||||||
|
while (!isNewLine(token[0])) {
|
||||||
|
vertex_index vi = parseTriple(token, v.size() / 3, vn.size() / 3, vt.size() / 2);
|
||||||
|
face.push_back(vi);
|
||||||
|
int n = strspn(token, " \t\r");
|
||||||
|
token += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
faceGroup.push_back(face);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// use mtl
|
||||||
|
if ((0 == strncmp(token, "usemtl", 6)) && isSpace((token[6]))) {
|
||||||
|
|
||||||
|
char namebuf[4096];
|
||||||
|
token += 7;
|
||||||
|
sscanf(token, "%s", namebuf);
|
||||||
|
|
||||||
|
if (material_map.find(namebuf) != material_map.end()) {
|
||||||
|
material = material_map[namebuf];
|
||||||
|
} else {
|
||||||
|
// { error!! material not found }
|
||||||
|
InitMaterial(material);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// load mtl
|
||||||
|
if ((0 == strncmp(token, "mtllib", 6)) && isSpace((token[6]))) {
|
||||||
|
char namebuf[4096];
|
||||||
|
token += 7;
|
||||||
|
sscanf(token, "%s", namebuf);
|
||||||
|
|
||||||
|
std::string err_mtl = LoadMtl(material_map, namebuf, mtl_basepath);
|
||||||
|
if (!err_mtl.empty()) {
|
||||||
|
faceGroup.clear(); // for safety
|
||||||
|
return err_mtl;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// group name
|
||||||
|
if (token[0] == 'g' && isSpace((token[1]))) {
|
||||||
|
|
||||||
|
// flush previous face group.
|
||||||
|
shape_t shape;
|
||||||
|
bool ret = exportFaceGroupToShape(shape, v, vn, vt, faceGroup, material, name);
|
||||||
|
if (ret) {
|
||||||
|
shapes.push_back(shape);
|
||||||
|
}
|
||||||
|
|
||||||
|
faceGroup.clear();
|
||||||
|
|
||||||
|
std::vector<std::string> names;
|
||||||
|
while (!isNewLine(token[0])) {
|
||||||
|
std::string str = parseString(token);
|
||||||
|
names.push_back(str);
|
||||||
|
token += strspn(token, " \t\r"); // skip tag
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(names.size() > 0);
|
||||||
|
|
||||||
|
// names[0] must be 'g', so skipt 0th element.
|
||||||
|
if (names.size() > 1) {
|
||||||
|
name = names[1];
|
||||||
|
} else {
|
||||||
|
name = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// object name
|
||||||
|
if (token[0] == 'o' && isSpace((token[1]))) {
|
||||||
|
|
||||||
|
// flush previous face group.
|
||||||
|
shape_t shape;
|
||||||
|
bool ret = exportFaceGroupToShape(shape, v, vn, vt, faceGroup, material, name);
|
||||||
|
if (ret) {
|
||||||
|
shapes.push_back(shape);
|
||||||
|
}
|
||||||
|
|
||||||
|
faceGroup.clear();
|
||||||
|
|
||||||
|
// @todo { multiple object name? }
|
||||||
|
char namebuf[4096];
|
||||||
|
token += 2;
|
||||||
|
sscanf(token, "%s", namebuf);
|
||||||
|
name = std::string(namebuf);
|
||||||
|
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ignore unknown command.
|
||||||
|
}
|
||||||
|
|
||||||
|
shape_t shape;
|
||||||
|
bool ret = exportFaceGroupToShape(shape, v, vn, vt, faceGroup, material, name);
|
||||||
|
if (ret) {
|
||||||
|
shapes.push_back(shape);
|
||||||
|
}
|
||||||
|
faceGroup.clear(); // for safety
|
||||||
|
|
||||||
|
return err.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
60
Demos3/Wavefront/tiny_obj_loader.h
Normal file
60
Demos3/Wavefront/tiny_obj_loader.h
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
//
|
||||||
|
// Copyright 2012-2013, Syoyo Fujita.
|
||||||
|
//
|
||||||
|
// Licensed under 2-clause BSD liecense.
|
||||||
|
//
|
||||||
|
#ifndef _TINY_OBJ_LOADER_H
|
||||||
|
#define _TINY_OBJ_LOADER_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
namespace tinyobj {
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
|
||||||
|
float ambient[3];
|
||||||
|
float diffuse[3];
|
||||||
|
float specular[3];
|
||||||
|
float transmittance[3];
|
||||||
|
float emission[3];
|
||||||
|
float shininess;
|
||||||
|
|
||||||
|
std::string ambient_texname;
|
||||||
|
std::string diffuse_texname;
|
||||||
|
std::string specular_texname;
|
||||||
|
std::string normal_texname;
|
||||||
|
std::map<std::string, std::string> unknown_parameter;
|
||||||
|
} material_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
std::vector<float> positions;
|
||||||
|
std::vector<float> normals;
|
||||||
|
std::vector<float> texcoords;
|
||||||
|
std::vector<unsigned int> indices;
|
||||||
|
} mesh_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
material_t material;
|
||||||
|
mesh_t mesh;
|
||||||
|
} shape_t;
|
||||||
|
|
||||||
|
/// Loads .obj from a file.
|
||||||
|
/// 'shapes' will be filled with parsed shape data
|
||||||
|
/// The function returns error string.
|
||||||
|
/// Returns empty string when loading .obj success.
|
||||||
|
/// 'mtl_basepath' is optional, and used for base path for .mtl file.
|
||||||
|
std::string LoadObj(
|
||||||
|
std::vector<shape_t>& shapes, // [output]
|
||||||
|
const char* filename,
|
||||||
|
const char* mtl_basepath = NULL);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _TINY_OBJ_LOADER_H
|
||||||
@@ -1027,6 +1027,15 @@ void GLInstancingRenderer::setCameraPitch(float pitch)
|
|||||||
m_data->m_azi = pitch;
|
m_data->m_azi = pitch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float GLInstancingRenderer::getCameraYaw() const
|
||||||
|
{
|
||||||
|
return m_data->m_ele;
|
||||||
|
}
|
||||||
|
float GLInstancingRenderer::getCameraPitch() const
|
||||||
|
{
|
||||||
|
return m_data->m_azi;
|
||||||
|
}
|
||||||
|
|
||||||
void GLInstancingRenderer::setCameraTargetPosition(float cameraPos[4])
|
void GLInstancingRenderer::setCameraTargetPosition(float cameraPos[4])
|
||||||
{
|
{
|
||||||
m_data->m_cameraTargetPosition = b3Vector3(cameraPos[0],cameraPos[1],cameraPos[2]);
|
m_data->m_cameraTargetPosition = b3Vector3(cameraPos[0],cameraPos[1],cameraPos[2]);
|
||||||
|
|||||||
@@ -100,7 +100,8 @@ public:
|
|||||||
|
|
||||||
void setCameraYaw(float yaw);
|
void setCameraYaw(float yaw);
|
||||||
void setCameraPitch(float pitch);
|
void setCameraPitch(float pitch);
|
||||||
|
float getCameraYaw() const;
|
||||||
|
float getCameraPitch() const;
|
||||||
|
|
||||||
void resize(int width, int height);
|
void resize(int width, int height);
|
||||||
int getScreenWidth()
|
int getScreenWidth()
|
||||||
|
|||||||
@@ -199,12 +199,12 @@ void b3GpuRaycast::castRaysHost(const b3AlignedObjectArray<b3RayInfo>& rays, b3A
|
|||||||
hitResults[r].m_hitFraction = hitFraction;
|
hitResults[r].m_hitFraction = hitFraction;
|
||||||
hitResults[r].m_hitPoint.setInterpolate3(rays[r].m_from, rays[r].m_to,hitFraction);
|
hitResults[r].m_hitPoint.setInterpolate3(rays[r].m_from, rays[r].m_to,hitFraction);
|
||||||
hitResults[r].m_hitNormal = hitNormal;
|
hitResults[r].m_hitNormal = hitNormal;
|
||||||
hitResults[r].m_hitResult0 = hitBodyIndex;
|
hitResults[r].m_hitBody = hitBodyIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
///todo: add some acceleration structure (AABBs, tree etc)
|
||||||
void b3GpuRaycast::castRays(const b3AlignedObjectArray<b3RayInfo>& rays, b3AlignedObjectArray<b3RayHit>& hitResults,
|
void b3GpuRaycast::castRays(const b3AlignedObjectArray<b3RayInfo>& rays, b3AlignedObjectArray<b3RayHit>& hitResults,
|
||||||
int numBodies,const struct b3RigidBodyCL* bodies, int numCollidables, const struct b3Collidable* collidables, const struct b3GpuNarrowPhaseInternalData* narrowphaseData)
|
int numBodies,const struct b3RigidBodyCL* bodies, int numCollidables, const struct b3Collidable* collidables, const struct b3GpuNarrowPhaseInternalData* narrowphaseData)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ B3_ATTRIBUTE_ALIGNED16(struct) b3RayInfo
|
|||||||
B3_ATTRIBUTE_ALIGNED16(struct) b3RayHit
|
B3_ATTRIBUTE_ALIGNED16(struct) b3RayHit
|
||||||
{
|
{
|
||||||
b3Scalar m_hitFraction;
|
b3Scalar m_hitFraction;
|
||||||
int m_hitResult0;
|
int m_hitBody;
|
||||||
int m_hitResult1;
|
int m_hitResult1;
|
||||||
int m_hitResult2;
|
int m_hitResult2;
|
||||||
b3Vector3 m_hitPoint;
|
b3Vector3 m_hitPoint;
|
||||||
|
|||||||
@@ -87,7 +87,8 @@ B3_ATTRIBUTE_ALIGNED16(struct) b3GpuGenericConstraint
|
|||||||
b3Quaternion m_relTargetAB;
|
b3Quaternion m_relTargetAB;
|
||||||
|
|
||||||
int m_flags;
|
int m_flags;
|
||||||
int m_padding[3];
|
int m_uid;
|
||||||
|
int m_padding[2];
|
||||||
|
|
||||||
int getRigidBodyA() const
|
int getRigidBodyA() const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -189,7 +189,10 @@ struct b3BatchConstraint
|
|||||||
static b3AlignedObjectArray<b3BatchConstraint> batchConstraints;
|
static b3AlignedObjectArray<b3BatchConstraint> batchConstraints;
|
||||||
static b3AlignedObjectArray<int> batches;
|
static b3AlignedObjectArray<int> batches;
|
||||||
|
|
||||||
|
void b3GpuPgsJacobiSolver::recomputeBatches()
|
||||||
|
{
|
||||||
|
batches.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -695,7 +698,7 @@ b3Scalar b3GpuPgsJacobiSolver::solveGroupCacheFriendlyIterations(b3OpenCLArray<b
|
|||||||
|
|
||||||
B3_PROFILE("batch joints");
|
B3_PROFILE("batch joints");
|
||||||
b3Assert(batchConstraints.size()==numConstraints);
|
b3Assert(batchConstraints.size()==numConstraints);
|
||||||
int simdWidth =numConstraints;
|
int simdWidth =numConstraints+1;
|
||||||
int numBodies = m_tmpSolverBodyPool.size();
|
int numBodies = m_tmpSolverBodyPool.size();
|
||||||
sortConstraintByBatch3( &batchConstraints[0], numConstraints, simdWidth , m_staticIdx, numBodies);
|
sortConstraintByBatch3( &batchConstraints[0], numConstraints, simdWidth , m_staticIdx, numBodies);
|
||||||
|
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ public:
|
|||||||
int numConstraints, b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints);
|
int numConstraints, b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints);
|
||||||
|
|
||||||
int sortConstraintByBatch3( struct b3BatchConstraint* cs, int numConstraints, int simdWidth , int staticIdx, int numBodies);
|
int sortConstraintByBatch3( struct b3BatchConstraint* cs, int numConstraints, int simdWidth , int staticIdx, int numBodies);
|
||||||
|
void recomputeBatches();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //B3_GPU_PGS_JACOBI_SOLVER_H
|
#endif //B3_GPU_PGS_JACOBI_SOLVER_H
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ bool dumpContactStats = false;
|
|||||||
b3GpuRigidBodyPipeline::b3GpuRigidBodyPipeline(cl_context ctx,cl_device_id device, cl_command_queue q,class b3GpuNarrowPhase* narrowphase, class b3GpuSapBroadphase* broadphaseSap , struct b3DynamicBvhBroadphase* broadphaseDbvt, const b3Config& config)
|
b3GpuRigidBodyPipeline::b3GpuRigidBodyPipeline(cl_context ctx,cl_device_id device, cl_command_queue q,class b3GpuNarrowPhase* narrowphase, class b3GpuSapBroadphase* broadphaseSap , struct b3DynamicBvhBroadphase* broadphaseDbvt, const b3Config& config)
|
||||||
{
|
{
|
||||||
m_data = new b3GpuRigidBodyPipelineInternalData;
|
m_data = new b3GpuRigidBodyPipelineInternalData;
|
||||||
|
m_data->m_constraintUid=0;
|
||||||
m_data->m_config = config;
|
m_data->m_config = config;
|
||||||
m_data->m_context = ctx;
|
m_data->m_context = ctx;
|
||||||
m_data->m_device = device;
|
m_data->m_device = device;
|
||||||
@@ -140,9 +141,41 @@ void b3GpuRigidBodyPipeline::removeConstraint(b3TypedConstraint* constraint)
|
|||||||
m_data->m_joints.remove(constraint);
|
m_data->m_joints.remove(constraint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void b3GpuRigidBodyPipeline::removeConstraintByUid(int uid)
|
||||||
|
{
|
||||||
|
m_data->m_gpuSolver->recomputeBatches();
|
||||||
|
//slow linear search
|
||||||
|
m_data->m_gpuConstraints->copyToHost(m_data->m_cpuConstraints);
|
||||||
|
//remove
|
||||||
|
for (int i=0;i<m_data->m_cpuConstraints.size();i++)
|
||||||
|
{
|
||||||
|
if (m_data->m_cpuConstraints[i].m_uid == uid)
|
||||||
|
{
|
||||||
|
//m_data->m_cpuConstraints.remove(m_data->m_cpuConstraints[i]);
|
||||||
|
m_data->m_cpuConstraints.swap(i,m_data->m_cpuConstraints.size()-1);
|
||||||
|
m_data->m_cpuConstraints.pop_back();
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_data->m_cpuConstraints.size())
|
||||||
|
{
|
||||||
|
m_data->m_gpuConstraints->copyFromHost(m_data->m_cpuConstraints);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
m_data->m_gpuConstraints->resize(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
int b3GpuRigidBodyPipeline::createPoint2PointConstraint(int bodyA, int bodyB, const float* pivotInA, const float* pivotInB)
|
int b3GpuRigidBodyPipeline::createPoint2PointConstraint(int bodyA, int bodyB, const float* pivotInA, const float* pivotInB)
|
||||||
{
|
{
|
||||||
|
m_data->m_gpuSolver->recomputeBatches();
|
||||||
b3GpuGenericConstraint c;
|
b3GpuGenericConstraint c;
|
||||||
|
c.m_uid = m_data->m_constraintUid;
|
||||||
|
m_data->m_constraintUid++;
|
||||||
c.m_flags = B3_CONSTRAINT_FLAG_ENABLED;
|
c.m_flags = B3_CONSTRAINT_FLAG_ENABLED;
|
||||||
c.m_rbA = bodyA;
|
c.m_rbA = bodyA;
|
||||||
c.m_rbB = bodyB;
|
c.m_rbB = bodyB;
|
||||||
@@ -151,10 +184,11 @@ int b3GpuRigidBodyPipeline::createPoint2PointConstraint(int bodyA, int bodyB, co
|
|||||||
c.m_breakingImpulseThreshold = 1e30f;
|
c.m_breakingImpulseThreshold = 1e30f;
|
||||||
c.m_constraintType = B3_GPU_POINT2POINT_CONSTRAINT_TYPE;
|
c.m_constraintType = B3_GPU_POINT2POINT_CONSTRAINT_TYPE;
|
||||||
m_data->m_cpuConstraints.push_back(c);
|
m_data->m_cpuConstraints.push_back(c);
|
||||||
return 0;
|
return c.m_uid;
|
||||||
}
|
}
|
||||||
int b3GpuRigidBodyPipeline::createFixedConstraint(int bodyA, int bodyB, const float* pivotInA, const float* pivotInB, const float* frameOrnA, const float* frameOrnB)
|
int b3GpuRigidBodyPipeline::createFixedConstraint(int bodyA, int bodyB, const float* pivotInA, const float* pivotInB, const float* frameOrnA, const float* frameOrnB)
|
||||||
{
|
{
|
||||||
|
m_data->m_gpuSolver->recomputeBatches();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ public:
|
|||||||
|
|
||||||
int createPoint2PointConstraint(int bodyA, int bodyB, const float* pivotInA, const float* pivotInB);
|
int createPoint2PointConstraint(int bodyA, int bodyB, const float* pivotInA, const float* pivotInB);
|
||||||
int createFixedConstraint(int bodyA, int bodyB, const float* pivotInA, const float* pivotInB, const float* frameOrnA, const float* frameOrnB);
|
int createFixedConstraint(int bodyA, int bodyB, const float* pivotInA, const float* pivotInB, const float* frameOrnA, const float* frameOrnB);
|
||||||
|
void removeConstraintByUid(int uid);
|
||||||
|
|
||||||
void addConstraint(class b3TypedConstraint* constraint);
|
void addConstraint(class b3TypedConstraint* constraint);
|
||||||
void removeConstraint(b3TypedConstraint* constraint);
|
void removeConstraint(b3TypedConstraint* constraint);
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ struct b3GpuRigidBodyPipelineInternalData
|
|||||||
b3AlignedObjectArray<b3GpuGenericConstraint> m_cpuConstraints;
|
b3AlignedObjectArray<b3GpuGenericConstraint> m_cpuConstraints;
|
||||||
|
|
||||||
b3AlignedObjectArray<b3TypedConstraint*> m_joints;
|
b3AlignedObjectArray<b3TypedConstraint*> m_joints;
|
||||||
|
int m_constraintUid;
|
||||||
class b3GpuNarrowPhase* m_narrowphase;
|
class b3GpuNarrowPhase* m_narrowphase;
|
||||||
b3Vector3 m_gravity;
|
b3Vector3 m_gravity;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user