Importing an .obj into OptiX

Hello,

I am trying to import an .obj file into OptiX following the MeshViewer sample, but trying to implement it in a more Object Oriented manner than the SDK.

mesh.h

namespace mesh {

	// mediator struct to parse 
	// mesh attributes into OptiX Buffers
	struct mesh_att {
		std::vector<float> positions;
		std::vector<float> normals;
		std::vector<std::uint32_t> tr_idx;
		std::vector<std::uint32_t> mat_ind;
		optix::float3 bbox_min;
		optix::float3 bbox_max;
	};

	// mediator class to parse material paramers to
	// Optix Materials
	class mat_params {
	public:
		explicit mat_params(
			const std::string& Kd_map,
			const optix::float3& Kd,
			const optix::float3& Ks,
			const optix::float3& Kr,
			const optix::float3& Ka,
			const float& shin)
			: m_Kd_map(Kd_map),
			m_Kd(Kd),
			m_Ks(Ks),
			m_Kr(Kr),
			m_Ka(Ka),
			m_shin(shin)
		{ }
		
		const std::string Kd_map() { return m_Kd_map; }
		const optix::float3 Kd() const { return m_Kd; }
		const optix::float3 Ks() const { return m_Ks; }
		const optix::float3 Kr() const { return m_Kr; }
		const optix::float3 Ka() const { return m_Ka; }
		const float shin() const { return m_shin; }

	private:
		std::string m_Kd_map;
		optix::float3 m_Kd;
		optix::float3 m_Ks;
		optix::float3 m_Kr;
		optix::float3 m_Ka;
		float m_shin;
	};


	//---------------------------
	// Optix mesh representation
	//---------------------------
	class mesh {
	public:
		mesh(const optix::Context& ctx) 
		{ 
			m_ctx = ctx;
		}
		
		mesh_att& med() { return m_med; }
		
		// TODO: add all buffers 
		void setup_input_bufs() {
			m_v_pos_buf = m_ctx->createBuffer(RT_BUFFER_INPUT, RT_FORMAT_FLOAT3, m_v_count);
			m_norm_buf = m_ctx->createBuffer(RT_BUFFER_INPUT, RT_FORMAT_FLOAT3, m_norm_count);
			m_tr_idx_buf = m_ctx->createBuffer(RT_BUFFER_INPUT, RT_FORMAT_INT3, m_tr_count);
			m_mat_idx_buf = m_ctx->createBuffer(RT_BUFFER_INPUT, RT_FORMAT_INT, m_tr_count);
			m_tex_buf = m_ctx->createBuffer(RT_BUFFER_INPUT, RT_FORMAT_FLOAT2, m_tex_count);
		}

		void set_vertex_count(const std::size_t& count) { m_v_count = count; }
		void set_norm_count(const std::size_t& count) { m_norm_count = count; }
		void set_tr_count(const std::size_t& count) { m_tr_count = count; }
		void set_color_count(const std::size_t& count) { m_col_count = count; }
		void set_tex_count(const std::size_t& count) { m_tex_count = count; }
		void set_mat_count(const std::size_t& count) { m_mat_count = count; }
		void insert_mat(const mat_params& params) { m_mats_med.emplace_back(params); }

		// parses host mesh data to OptiX INPUT buffers
		void map_buffers() {
			if (m_med.positions.empty()) {
				LOG_ERROR << "Mesh not scanned.";
				throw std::exception();
			}

			// parses mesh's bounding box
			m_bbox.set(m_med.bbox_min, m_med.bbox_max);

			//parse with for loops
			float* const v_data = reinterpret_cast<float*>(m_v_pos_buf->map());
			for (std::size_t v = 0; v < m_v_count; ++v) {
				v_data[v * 3 + 0] = m_med.positions[v * 3 + 0];
				v_data[v * 3 + 1] = m_med.positions[v * 3 + 1];
				v_data[v * 3 + 2] = m_med.positions[v * 3 + 2];
				/*LOG_DEBUG << "V positions: { " << m_med.positions[v * 3 + 0]
					<< ", " << m_med.positions[v * 3 + 1] << ", "
					<< m_med.positions[v * 3 + 2] << " }";*/
			}

			std::uint32_t* const tr_data = reinterpret_cast<std::uint32_t*>(m_tr_idx_buf->map());
			for (std::size_t tr = 0; tr < m_tr_count; ++tr) {
				tr_data[tr * 3 + 0] = m_med.tr_idx[tr * 3 + 0];
				tr_data[tr * 3 + 1] = m_med.tr_idx[tr * 3 + 1];
				tr_data[tr * 3 + 2] = m_med.tr_idx[tr * 3 + 2];
				/*LOG_DEBUG << "T idx: { " << m_med.tr_idx[tr * 3 + 0]
					<< ", " << m_med.tr_idx[tr * 3 + 1] << ", "
					<< m_med.tr_idx[tr * 3 + 2] << " }";*/
			}

			std::uint32_t* const mat_data = reinterpret_cast<std::uint32_t*>(m_mat_idx_buf->map());
			for (std::size_t tr = 0; tr < m_tr_count; ++tr) {
				mat_data[tr] = m_med.mat_ind[tr];
			}
		}

		// creates texture sampler
		optix::TextureSampler create_tex_sampler(const optix::float3& default_color) {
			optix::TextureSampler sampler = m_ctx->createTextureSampler();
			sampler->setWrapMode(0, RT_WRAP_REPEAT);
			sampler->setWrapMode(1, RT_WRAP_REPEAT);
			sampler->setWrapMode(2, RT_WRAP_REPEAT);
			sampler->setIndexingMode(RT_TEXTURE_INDEX_NORMALIZED_COORDINATES);
			sampler->setReadMode(RT_TEXTURE_READ_NORMALIZED_FLOAT);
			sampler->setMaxAnisotropy(1.0f);
			sampler->setMipLevelCount(1u);
			sampler->setArraySize(1u);

			// Create buffer with single texel set to default_color
			optix::Buffer buffer = m_ctx->createBuffer(RT_BUFFER_INPUT, RT_FORMAT_UNSIGNED_BYTE4, 1u, 1u);
			unsigned char* buffer_data = static_cast<unsigned char*>(buffer->map());
			buffer_data[0] = (unsigned char)optix::clamp((int)(default_color.x * 255.0f), 0, 255);
			buffer_data[1] = (unsigned char)optix::clamp((int)(default_color.y * 255.0f), 0, 255);
			buffer_data[2] = (unsigned char)optix::clamp((int)(default_color.z * 255.0f), 0, 255);
			buffer_data[3] = 255;
			buffer->unmap();

			sampler->setBuffer(0u, 0u, buffer);
			// Although it would be possible to use nearest filtering here, we chose linear
			// to be consistent with the textures that have been loaded from a file. This
			// allows OptiX to perform some optimizations.
			sampler->setFilteringModes(RT_FILTER_LINEAR, RT_FILTER_LINEAR, RT_FILTER_NONE);
			return sampler;
		}

		// creates OptiX Geometry 
		// sets mesh attributes buffers
		// creates and sets bbox program
		// creates and sets intersection program
		void create_geometry() {
			m_geom = m_ctx->createGeometry();
			m_geom["vertex_buffer"]->setBuffer(m_v_pos_buf);
			m_geom["normal_buffer"]->setBuffer(m_norm_buf);
			m_geom["texcoord_buffer"]->setBuffer(m_tex_buf);
			m_geom["material_buffer"]->setBuffer(m_mat_idx_buf);
			m_geom["index_buffer"]->setBuffer(m_tr_idx_buf);
			m_geom->setPrimitiveCount(m_tr_count);

			// create bbox_prog
			std::string ptx = core::ptx::ptx_from_cu(bbox_path, prog_path);
			m_bbox_prog = m_ctx->createProgramFromPTXString(ptx, bbox_name);
			// create intersection prog
			ptx = core::ptx::ptx_from_cu(intersect_path, prog_path);
			m_inter_prog = m_ctx->createProgramFromPTXString(ptx, intersect_name);
			
			// set programs to geometry
			m_geom->setBoundingBoxProgram(m_bbox_prog);
			m_geom->setIntersectionProgram(m_inter_prog);
		}


		// creates OptiX Geometry instance from Geometry
		// sets Materials
		// sets closest hit program
		// sets any hit program
		void create_ginstance() {
			m_ginst = m_ctx->createGeometryInstance();
			// create Material/s
			// create material programs
			std::string ptx = core::ptx::ptx_from_cu(closest_prog_path, prog_path);
			m_closest_prog = m_ctx->createProgramFromPTXString(ptx, closest_prog_name);
			
			ptx = core::ptx::ptx_from_cu(any_prog_path, prog_path);
			m_any_prog = m_ctx->createProgramFromPTXString(ptx, any_prog_name);
			
			for (auto mat : m_mats_med) {
				optix::Material optx_mat = m_ctx->createMaterial();
				optx_mat->setClosestHitProgram(0u, m_closest_prog);
				optx_mat->setAnyHitProgram(1u, m_any_prog);

				// see that thing with textures
				//optx_mat["Kd_map"]->set TextreSampler
				optx_mat["Kd_map"]->setTextureSampler(
					create_tex_sampler(mat.Kd()));
				optx_mat["Kd_mapped"]->setInt(0);
				optx_mat["Kd"]->setFloat(mat.Kd());
				optx_mat["Ks"]->setFloat(mat.Ks());
				optx_mat["Kr"]->setFloat(mat.Kr());
				optx_mat["Ka"]->setFloat(mat.Ka());
				optx_mat["phong_exp"]->setFloat(mat.shin());
				m_materials.emplace_back(optx_mat);
			}
			m_ginst = m_ctx->createGeometryInstance(m_geom, m_materials.begin(), m_materials.end());
		}

		// return geometry instance
		optix::GeometryInstance geom_instance() { return m_ginst; }

		void unmap_buffers() {
			m_v_pos_buf->unmap();
			m_tr_idx_buf->unmap();
			if (m_norm_count != 0) {
				m_norm_buf->unmap();
			}
			m_mat_idx_buf->unmap();
		}

		const optix::Aabb bbox() const { return m_bbox; }

	private:
		optix::Context m_ctx;	// valid optix context

		std::size_t m_v_count;		// num of vertices
		std::size_t m_tr_count;		// num of triangles
		std::size_t m_norm_count;	// num of normals
		std::size_t m_tex_count;	// num of texcoords
		std::size_t m_col_count;	// num of colors
		std::size_t m_mat_count;	// num of materials

		// Buffers -> arrays with mesh attribute data
		optix::Buffer m_v_pos_buf;		// vertex position buffer
		optix::Buffer m_tr_idx_buf;		// triangle index buffer
		optix::Buffer m_norm_buf;		// normals buffer
		optix::Buffer m_mat_idx_buf;	// material index buffer
		optix::Buffer m_tex_buf;		// texcoords buffer
		optix::Buffer m_col_buf;		// colors buffer

		// programs
		optix::Program m_inter_prog;	// intersection program
		optix::Program m_bbox_prog;		// bounding box program
		optix::Program m_closest_prog;	// closest hit program
		optix::Program m_any_prog;		// any hit program

		// mesh's bbox
		optix::Aabb m_bbox;				

		optix::Geometry m_geom;				// geometry node
		optix::GeometryInstance m_ginst;	// geometric instance node

		// optional single material override
		optix::Material m_mat;				
		std::vector<optix::Material> m_materials;	// mesh's materials

		mesh_att m_med;
		std::vector<mat_params> m_mats_med;
	};
}	// namespace mesh
#endif // !_INCLUDE_OPTX_MESH_H_

mesh_loader.h

namespace fs = std::experimental::filesystem;

	enum class mesh_file_t : std::size_t {
		Unknown = 0,
		obj
	};

	template<typename mesh_file_t file_t = mesh_file_t::Unknown>
	class mesh_loader;

	template<>
	class mesh_loader<mesh_file_t::obj> {
	public:
		mesh_loader(const std::string& filepath)
		{
			m_path = filepath;
			m_fs_path = fs::path(filepath);
			std::string ext = m_fs_path.extension().generic_string();
			if (ext != ".obj") {
				LOG_ERROR << "Given file is not .obj";
				throw std::exception();
			}

			m_has_normals = true;
			m_has_texcoords = true;
			m_model = new const aiScene;
		}

		// scan_file
		void scan_file() {
			/*const aiScene* */
			m_model = m_importer.ReadFile(
				m_path,
				aiProcess_Triangulate |
				aiProcess_SortByPType |
				aiProcess_ValidateDataStructure |
				aiProcess_SplitLargeMeshes |
				aiProcess_FixInfacingNormals);
			//m_model = _m_model;

			if (!m_model) {
				LOG_ERROR << "Attempted to load file: " << m_path << "but an error occured.";
				throw std::exception();
			}
			LOG_DEBUG << "Loaded file: " << m_path;
			LOG_DEBUG << "Number of meshes: " << m_model->mNumMeshes;
			LOG_DEBUG << "Number of materials: " << m_model->mNumMaterials;

			for (std::size_t i = 0; i < m_model->mNumMeshes; ++i) {
				m_v_count += m_model->mMeshes[i]->mNumVertices;
				m_tr_count += m_model->mMeshes[i]->mNumFaces;
				//m_norm_count += model->mMeshes[i]->mNormals;
			}
			m_mat_count = m_model->mNumMaterials;
			LOG_DEBUG << "Number of vertices: " << m_v_count;
			LOG_DEBUG << "Number of faces (triangles): " << m_tr_count;
			LOG_DEBUG << "Number of materials: " << m_mat_count;
			m_has_normals = false;
			m_has_texcoords = false;
			//std::this_thread::sleep_for(std::chrono::milliseconds(5000));
		}


		void load_mesh(mesh::mesh& mesh) {
			if (m_v_count == 0) {
				LOG_ERROR << "Mesh file not scanned.";
				throw std::exception();
			}
			LOG_DEBUG << "Loading mesh.";
			// set counts
			mesh.set_vertex_count(m_v_count);
			mesh.set_tr_count(m_tr_count);
			mesh.set_mat_count(m_mat_count);

			if (m_has_texcoords) {
				mesh.set_tex_count(m_tex_count);
			}
			else {
				mesh.set_tex_count(0);
			}
			if (m_has_normals) {
				mesh.set_norm_count(m_norm_count);
			}
			else {
				mesh.set_norm_count(0);
			}
			
			LOG_DEBUG << "Filling vertex positions and calculating bounding box...";
			// fill positions

			mesh.med().bbox_min.x = mesh.med().bbox_min.y = mesh.med().bbox_min.z = 1.e16f;
			mesh.med().bbox_max.x = mesh.med().bbox_max.y = mesh.med().bbox_max.z = -1.e16f;
			for (std::size_t m = 0; m < m_model->mNumMeshes; ++m) {
				for (std::size_t v = 0; v < m_model->mMeshes[m]->mNumVertices; ++v) {
					mesh.med().positions.emplace_back(m_model->mMeshes[m]->mVertices[v].x);
					mesh.med().positions.emplace_back(m_model->mMeshes[m]->mVertices[v].y);
					mesh.med().positions.emplace_back(m_model->mMeshes[m]->mVertices[v].z);
					mesh.med().bbox_min.x = std::min<float>(mesh.med().bbox_min.x, m_model->mMeshes[m]->mVertices[v].x);
					mesh.med().bbox_min.y = std::min<float>(mesh.med().bbox_min.y, m_model->mMeshes[m]->mVertices[v].y);
					mesh.med().bbox_min.z = std::min<float>(mesh.med().bbox_min.z, m_model->mMeshes[m]->mVertices[v].x);
					mesh.med().bbox_max.x = std::max<float>(mesh.med().bbox_max.x, m_model->mMeshes[m]->mVertices[v].x);
					mesh.med().bbox_max.y = std::max<float>(mesh.med().bbox_max.y, m_model->mMeshes[m]->mVertices[v].y);
					mesh.med().bbox_max.z = std::max<float>(mesh.med().bbox_max.z, m_model->mMeshes[m]->mVertices[v].z);
					if (m_has_normals) {
						mesh.med().normals.emplace_back(m_model->mMeshes[m]->mNormals[v].x);
						mesh.med().normals.emplace_back(m_model->mMeshes[m]->mNormals[v].y);
						mesh.med().normals.emplace_back(m_model->mMeshes[m]->mNormals[v].z);
					}

				}
			}
			
			LOG_DEBUG << "Filling triangle and material indices...";
			for (std::size_t m = 0; m < m_model->mNumMeshes; ++m) {
				for (std::size_t f = 0; f < m_model->mMeshes[m]->mNumFaces; ++f) {
					aiFace face = m_model->mMeshes[m]->mFaces[f];
					if (face.mNumIndices == 3) {
						mesh.med().tr_idx.emplace_back(face.mIndices[0]);
						mesh.med().tr_idx.emplace_back(face.mIndices[1]);
						mesh.med().tr_idx.emplace_back(face.mIndices[2]);
						//LOG_DEBUG << "Skata: " << face.mIndices[0];
						//LOG_DEBUG << "Skata: " << face.mIndices[1];
						//LOG_DEBUG << "Skata: " << face.mIndices[2];
					}
					else {
						LOG_WARNING << "Face #" << f << " Num Vertices not 3.";
						mesh.med().tr_idx.emplace_back(0);
						mesh.med().tr_idx.emplace_back(0);
						mesh.med().tr_idx.emplace_back(0);
					}
					//for (std::size_t i = 0; i < m_model->mMeshes[m]->mFaces[f].mNumIndices; ++i) {

					//	LOG_DEBUG << "Triangle #" << i << " Index: " << m_model->mMeshes[m]->mFaces->mIndices[i];
					//	mesh.med().tr_idx.emplace_back(m_model->mMeshes[m]->mFaces->mIndices[i]);
					//}
					mesh.med().mat_ind.emplace_back(m_model->mMeshes[m]->mMaterialIndex);
				}
			}


			// TODO: leave tex coords for the time being
			LOG_DEBUG << "Filling materials...";
			for (std::size_t m = 0; m < m_model->mNumMaterials; ++m) {
				//aiMaterial* mat = m_model->mMaterials[m];
				std::string map = "";//mat.diffuse_texname;
				optix::float3 Kd = optix::make_float3(0.7f, 0.7f, 0.7f);
				optix::float3 Ks = optix::make_float3(0.7f, 0.7f, 0.7f);
				optix::float3 Ka = optix::make_float3(1.f, 1.f, 1.f);
				optix::float3 Kr = optix::make_float3(0.0f, 0.0f, 0.0f);
				float shin = 1.0f;
				mesh.insert_mat(mesh::mat_params(map, Kd, Ks, Kr, Ka, shin));
			}
			LOG_DEBUG << "Done.";
		}
	private:
		Assimp::Importer m_importer;
		const aiScene* m_model;
		std::string m_path;
		fs::path m_fs_path;

		tinyobj::attrib_t m_attributes;
		std::vector<tinyobj::shape_t> m_shapes;
		std::vector<tinyobj::material_t> m_materials;
		
		std::size_t m_v_count;
		std::size_t m_tr_count;
		std::size_t m_mat_count;
		std::size_t m_tex_count;
		std::size_t m_col_count;
		std::size_t m_norm_count;

		bool m_has_normals;
		bool m_has_texcoords;
		
	};
}

cam.h
[code]
namespace cam {
	static void calc_cam_params(
		optix::float3 eye,
		optix::float3 lookat,
		optix::float3 up,
		optix::float3& U, 
		optix::float3& V, 
		optix::float3& W,
		float aspect_ratio,
		float fov = 35.f,
		bool fov_is_vert = true) 
	{
		float ulen, vlen, wlen;
		wlen = optix::length(W);
		U = optix::normalize(cross(W, up));
		V = optix::normalize(cross(U, W));

		if (fov_is_vert) {
			vlen = wlen * tanf(0.5f * fov * M_PIf / 180.0f);
			V *= vlen;
			ulen = vlen * aspect_ratio;
			U *= ulen;
		}
		else {
			ulen = wlen * tanf(0.5f * fov * M_PIf / 180.0f);
			U *= ulen;
			vlen = ulen / aspect_ratio;
			V *= vlen;
		}
	}

	static void update_cam(
		optix::Context& context, 
		optix::float3& eye, 
		optix::float3& lookat, 
		optix::float3& up,
		optix::Matrix4x4& rot,
		float aspect) 
	{
		const float vfov = 35.f;
		optix::float3 cam_u, cam_v, cam_w;
		cam::calc_cam_params(eye, lookat, up, cam_u, cam_v, cam_w, aspect);
		const optix::Matrix4x4 frame = optix::Matrix4x4::fromBasis(
			optix::normalize(cam_u),
			optix::normalize(cam_v),
			optix::normalize(-cam_w),
			lookat);

		const optix::Matrix4x4 frame_inv = frame.inverse();
		// Apply camera rotation twice to match old SDK behavior
		const optix::Matrix4x4 trans = frame * rot * rot * frame_inv;

		eye = optix::make_float3(trans * optix::make_float4(eye, 1.0f));
		lookat = optix::make_float3(trans * optix::make_float4(lookat, 1.0f));
		up = optix::make_float3(trans * optix::make_float4(up, 0.0f));

		cam::calc_cam_params(eye, lookat, up, cam_u, cam_v, cam_w, aspect);
		rot = optix::Matrix4x4::identity();
		context["eye"]->setFloat(eye);
		context["U"]->setFloat(cam_u);
		context["V"]->setFloat(cam_v);
		context["W"]->setFloat(cam_w);
	}
}

cam.h

namespace cam {
	static void calc_cam_params(
		optix::float3 eye,
		optix::float3 lookat,
		optix::float3 up,
		optix::float3& U, 
		optix::float3& V, 
		optix::float3& W,
		float aspect_ratio,
		float fov = 35.f,
		bool fov_is_vert = true) 
	{
		float ulen, vlen, wlen;
		wlen = optix::length(W);
		U = optix::normalize(cross(W, up));
		V = optix::normalize(cross(U, W));

		if (fov_is_vert) {
			vlen = wlen * tanf(0.5f * fov * M_PIf / 180.0f);
			V *= vlen;
			ulen = vlen * aspect_ratio;
			U *= ulen;
		}
		else {
			ulen = wlen * tanf(0.5f * fov * M_PIf / 180.0f);
			U *= ulen;
			vlen = ulen / aspect_ratio;
			V *= vlen;
		}
	}

	static void update_cam(
		optix::Context& context, 
		optix::float3& eye, 
		optix::float3& lookat, 
		optix::float3& up,
		optix::Matrix4x4& rot,
		float aspect) 
	{
		const float vfov = 35.f;
		optix::float3 cam_u, cam_v, cam_w;
		cam::calc_cam_params(eye, lookat, up, cam_u, cam_v, cam_w, aspect);
		const optix::Matrix4x4 frame = optix::Matrix4x4::fromBasis(
			optix::normalize(cam_u),
			optix::normalize(cam_v),
			optix::normalize(-cam_w),
			lookat);

		const optix::Matrix4x4 frame_inv = frame.inverse();
		// Apply camera rotation twice to match old SDK behavior
		const optix::Matrix4x4 trans = frame * rot * rot * frame_inv;

		eye = optix::make_float3(trans * optix::make_float4(eye, 1.0f));
		lookat = optix::make_float3(trans * optix::make_float4(lookat, 1.0f));
		up = optix::make_float3(trans * optix::make_float4(up, 0.0f));

		cam::calc_cam_params(eye, lookat, up, cam_u, cam_v, cam_w, aspect);
		rot = optix::Matrix4x4::identity();
		context["eye"]->setFloat(eye);
		context["U"]->setFloat(cam_u);
		context["V"]->setFloat(cam_v);
		context["W"]->setFloat(cam_w);
	}
}

and my main.cpp

static const std::size_t  AppWidth = 1024;
static const std::size_t AppHeight = 768;

int main(int argc, char* argv[]) {
	plog::ColorConsoleAppender<plog::TxtFormatter> appender;
	plog::init(plog::debug, &appender);
	LOG_DEBUG << "let's go";

	try {
		optix::Context context = optix::Context::create();
		context->setRayTypeCount(2);
		context->setEntryPointCount(1);
		context->setPrintEnabled(true);
		context->setPrintBufferSize(512);
		context->setExceptionEnabled(RT_EXCEPTION_ALL, true);

		context["radiance_ray_type"]->setUint(0u);
		context["shadow_ray_type"]->setUint(1u);
		context["scene_epsilon"]->setFloat(1.e-4f);

		// output_buffer var declared in pinhole ray gen prog
		optix::Buffer out_buffer =
			context->createBuffer(
				RT_BUFFER_OUTPUT, 
				RT_FORMAT_FLOAT4, 
				AppWidth, AppHeight);
		context["output_buffer"]->setBuffer(out_buffer);

		// Ray generation program
		//std::string pinhole_loc = "E:\_dev\_Projects\360Fuzion\360_fuzion\src\optix\CUDA";
		std::string pinhole_loc = "D:\_dev\_Projects\_Visual_Studio\360Fuzio\360_fuzion\src\optix\CUDA";
		std::string pinhole_file = "pinhole_camera.cu";
		std::string ptx = core::ptx::ptx_from_cu(pinhole_file, pinhole_loc);
		optix::Program ray_gen_prog = context->createProgramFromPTXString(ptx, "pinhole_camera");
		context->setRayGenerationProgram(0u, ray_gen_prog);

		// exception program
		optix::Program except_prog = context->createProgramFromPTXString(ptx, "exception");
		context->setExceptionProgram(0u, except_prog);
		context["bad_color"]->setFloat(1.0f, 0.0f, 1.0f);

		//Miss program
		std::string miss_file = "constantbg.cu";
		optix::Program miss_prog = context->createProgramFromPTXString(
			core::ptx::ptx_from_cu(miss_file, pinhole_loc), "miss");
		context->setMissProgram(0u, miss_prog);
		context["bg_color"]->setFloat(0.3f, 0.2f, 0.2f);

		//io::mesh_loader<io::mesh_file_t::obj> loader("E:\IronMan\IronMan.obj");
		io::mesh_loader<io::mesh_file_t::obj> loader("D:\_Media\3Dmodels\jzb865er6v-IronMan\IronMan\IronMan.obj");
		mesh::mesh mesh(context);
		loader.scan_file();
		loader.load_mesh(mesh);
		mesh.setup_input_bufs();
		mesh.create_geometry();
		mesh.map_buffers();
		mesh.create_ginstance();

		
		optix::GeometryInstance ginstance = mesh.geom_instance();
		
		optix::GeometryGroup g_group = context->createGeometryGroup();
		g_group->addChild(ginstance);
		LOG_DEBUG << "GInstance Materials: " << ginstance->getMaterialCount();
		LOG_DEBUG << "GInstance Variables: " << ginstance->getVariableCount();
		LOG_DEBUG << "Child Geomtery Variables: " << ginstance->getGeometry()->getVariableCount();
		LOG_DEBUG << "Child Geomtery Bbox Variables: " << ginstance->getGeometry()->getBoundingBoxProgram()->getVariableCount();
		LOG_DEBUG << "Child Geomtery Intersect Variables: " << ginstance->getGeometry()->getIntersectionProgram()->getVariableCount();
		LOG_DEBUG << "Child Geomtery Primitives: " << ginstance->getGeometry()->getPrimitiveCount();
		


		optix::Acceleration accel = context->createAcceleration("Bvh");
		g_group->setAcceleration(accel);
		accel->markDirty();
		context["top_object"]->set(g_group);
		context["top_shadower"]->set(g_group);

		// setup camera
		optix::Aabb aabb = mesh.bbox();
		const float max_dim = fmaxf(aabb.extent(0), aabb.extent(1));
		optix::float3 cam_eye = 
			aabb.center() + optix::make_float3(0.0f, 0.0f, max_dim * 1.5f);
		optix::float3 cam_lookat = aabb.center();
		optix::float3 cam_up = optix::make_float3(0.0f, 1.0f, 0.0f);
		optix::Matrix4x4 cam_rot = optix::Matrix4x4::identity();

		light::basic_lights lights[] = {
			{ optix::make_float3(-0.5f,  0.25f, -1.0f), optix::make_float3(0.2f, 0.2f, 0.25f), 0, 0 },
			{ optix::make_float3(-0.5f,  0.0f ,  1.0f), optix::make_float3(0.1f, 0.1f, 0.10f), 0, 0 },
			{ optix::make_float3(0.5f,  0.5f ,  0.5f), optix::make_float3(0.7f, 0.7f, 0.65f), 1, 0 }
		};

		lights[0].pos *= max_dim * 10.0f;
		lights[1].pos *= max_dim * 10.0f;
		lights[2].pos *= max_dim * 10.0f;

		optix::Buffer light_buf = context->createBuffer(RT_BUFFER_INPUT);
		light_buf->setFormat(RT_FORMAT_USER);
		light_buf->setElementSize(sizeof(light::basic_lights));
		light_buf->setSize(sizeof(lights) / sizeof(lights[0]));
		std::memcpy(light_buf->map(), lights, sizeof(lights));
		light_buf->unmap();
		context["lights"]->set(light_buf);
		const float aspect = static_cast<float>(AppWidth) / static_cast<float>(AppHeight);
		cam::update_cam(context, cam_eye, cam_lookat, cam_up, cam_rot, aspect);
		
		LOG_DEBUG << "Validating context...";
		context->validate();
		LOG_DEBUG << "Launching context...";
		mesh.unmap_buffers();
		context->launch(0u, AppWidth, AppHeight);

		std::vector<optix::float4> out_data(AppWidth * AppHeight);
		std::memcpy(out_data.data(), 
			reinterpret_cast<optix::float4*>(out_buffer->map()), 
				4 * AppWidth * AppHeight * sizeof(float));

		cv::Mat image = cv::Mat(cv::Size(AppWidth, AppHeight), CV_32FC4, out_data.data());
		cv::imshow("Skatakia", image);
		cv::waitKey(0);
	}
	catch (optix::Exception ex) {
		LOG_ERROR << "OptiX Error: " << ex.getErrorCode() << " - " << ex.getErrorString();
	}
	return 0;
}

The optix::Programs are compiled from the same cuda files as the examples. And I try to show the output buffer with OpenCV.
When using Accelerations “Bvh”, “Sbvh” or “Trbvh” only the Miss program is invoked. However, when using “NoAccel” the closest_hit and any_hit are invoked but I get an exception, so I feel that there may be a memory leak (propably when filling the mesh related buffers?) but I cannot seem to find it.
I know that this is a lot of code, but any help would really be appreciated.

Setup

Windows 10 Pro
Cuda 9.2
OptiX 5.1
Geforce 1070
MSVisual Studio 2015

PS: regarding optix::Context or any other cpp Handle: Does the operator= make a copy, or a reference?

Thanks in advance

So, I started rotating the camera a little and something started to show. However, I must not parse the mesh attributes into Optix the right way.

Anyhow, if someone has the time and is kind enough to peek through my code, again it would be really appreciated.

You use bbox_name and intersect_name, but you did not provide the decleration+initialization of them. The same for m_model->mNumMaterials Maybe this data is not initialized as expected.
Try CUDA 9.0, cause 9.2 is not officially supported by OptiX 5.1.0; see:
https://devtalk.nvidia.com/default/topic/1036496/optix/compile-error-with-optix-advanced-samples/post/5265544/#5265544

Maybe some of the CU programs were not loaded.
Check all OptiX API call return values against NULL, which return a POINTER.
Insert hr return codes (for example of type HRESULT) into your functions and set them to a negative value error code, if something failed.
Use zero, when succeeded. Then display each function’s return value with your LOG_ERROR code

Only continue to next step when SUCCEEDED(hr) https://docs.microsoft.com/en-us/windows/desktop/api/winerror/nf-winerror-succeeded returns true; Or exit on errors, if FAILED(hr) returns true. So if any function fails you can directly checkout which function fails and why.

You also call mesh.unmap_buffers(); after the validation; I would do this before the validation.

Please post some debug outputs.

PS: regarding optix::Context or any other cpp Handle: Does the operator= make a copy, or a reference?
Context is defined this way: typedef Handle Context;
So look at the class Handle how reference count is affected. see Handle& operator=(const Handle& copy)… in the optix header files

m1,

First of all thank you for your reply. You are right about the fact that I should check the return results.
Regrading buffer initialization, it’s true that I forgot to post that part of code.
The “unmap_buffers()” function was there just for debugging reasons.

Anyways, I changed completely the code design, and now everything seems to work fine.

Thanks again for your reply