gpuray_glsl

changeset 4:2ed3da7dc0bc

broken
author John Tsiombikas <nuclear@member.fsf.org>
date Mon, 10 Nov 2014 01:26:00 +0200
parents 297dbc5080c4
children 000017955721
files gpuray_glsl.vcxproj gpuray_glsl.vcxproj.filters sdr/rt.glsl src/cone.cc src/gpuscene.cc src/gpuscene.h src/rend.cc src/scene_load.cc
diffstat 8 files changed, 249 insertions(+), 6 deletions(-) [+]
line diff
     1.1 --- a/gpuray_glsl.vcxproj	Sun Nov 09 20:13:33 2014 +0200
     1.2 +++ b/gpuray_glsl.vcxproj	Mon Nov 10 01:26:00 2014 +0200
     1.3 @@ -96,6 +96,7 @@
     1.4      <ClCompile Include="imago\modules.c" />
     1.5      <ClCompile Include="src\box.cc" />
     1.6      <ClCompile Include="src\camera.cc" />
     1.7 +    <ClCompile Include="src\cone.cc" />
     1.8      <ClCompile Include="src\glsdr.c" />
     1.9      <ClCompile Include="src\gpuscene.cc" />
    1.10      <ClCompile Include="src\image.cc" />
    1.11 @@ -127,6 +128,7 @@
    1.12      <ClInclude Include="imago\imago2.h" />
    1.13      <ClInclude Include="src\box.h" />
    1.14      <ClInclude Include="src\camera.h" />
    1.15 +    <ClInclude Include="src\cone.h" />
    1.16      <ClInclude Include="src\glsdr.h" />
    1.17      <ClInclude Include="src\gpuscene.h" />
    1.18      <ClInclude Include="src\image.h" />
     2.1 --- a/gpuray_glsl.vcxproj.filters	Sun Nov 09 20:13:33 2014 +0200
     2.2 +++ b/gpuray_glsl.vcxproj.filters	Mon Nov 10 01:26:00 2014 +0200
     2.3 @@ -124,6 +124,9 @@
     2.4      <ClCompile Include="imago\modules.c">
     2.5        <Filter>imago</Filter>
     2.6      </ClCompile>
     2.7 +    <ClCompile Include="src\cone.cc">
     2.8 +      <Filter>src</Filter>
     2.9 +    </ClCompile>
    2.10    </ItemGroup>
    2.11    <ItemGroup>
    2.12      <ClInclude Include="src\box.h">
    2.13 @@ -210,6 +213,9 @@
    2.14      <ClInclude Include="imago\imago2.h">
    2.15        <Filter>imago</Filter>
    2.16      </ClInclude>
    2.17 +    <ClInclude Include="src\cone.h">
    2.18 +      <Filter>src</Filter>
    2.19 +    </ClInclude>
    2.20    </ItemGroup>
    2.21    <ItemGroup>
    2.22      <None Include="vmath\matrix.inl">
     3.1 --- a/sdr/rt.glsl	Sun Nov 09 20:13:33 2014 +0200
     3.2 +++ b/sdr/rt.glsl	Mon Nov 10 01:26:00 2014 +0200
     3.3 @@ -46,6 +46,13 @@
     3.4  	struct Material mat;
     3.5  };
     3.6  
     3.7 +struct Cone {
     3.8 +	float index;
     3.9 +	float angle;
    3.10 +	float start, end;
    3.11 +	struct Material mat;
    3.12 +};
    3.13 +
    3.14  struct Light {
    3.15  	vec3 pos, color;
    3.16  };
    3.17 @@ -55,6 +62,7 @@
    3.18  bool sphere_intersect(in Sphere sph, in Ray ray, out HitPoint pt);
    3.19  bool plane_intersect(in Plane plane, in Ray ray, out HitPoint pt);
    3.20  bool box_intersect(in Box box, in Ray ray, out HitPoint pt);
    3.21 +bool cone_intersect(in Cone cone, in Ray ray, out HitPoint pt);
    3.22  vec3 transform(in vec3 v, in mat4 inv_xform);
    3.23  Ray transform(in Ray ray, in mat4 xform, in mat4 inv_xform);
    3.24  Ray get_primary_ray();
    3.25 @@ -62,11 +70,12 @@
    3.26  Sphere read_sphere(in float idx);
    3.27  Plane read_plane(in float idx);
    3.28  Box read_box(in float idx);
    3.29 +Cone read_cone(in float idx);
    3.30  Material read_material(in sampler2D tex, in float ty);
    3.31  void read_xform(in float idx, out mat4 xform, out mat4 inv_xform);
    3.32  
    3.33  uniform sampler2D tex_raydir;
    3.34 -uniform sampler2D tex_spheres, tex_planes, tex_boxes;
    3.35 +uniform sampler2D tex_spheres, tex_planes, tex_boxes, tex_cones;
    3.36  uniform sampler2D tex_megatex;
    3.37  uniform sampler2D tex_xforms;
    3.38  uniform samplerCube tex_env;
    3.39 @@ -75,8 +84,8 @@
    3.40  uniform Light lights[8];
    3.41  uniform int num_lights;
    3.42  
    3.43 -int num_spheres, num_planes, num_boxes;
    3.44 -float sph_tex_sz, plane_tex_sz, box_tex_sz, xform_tex_sz;
    3.45 +int num_spheres, num_planes, num_boxes, num_cones;
    3.46 +float sph_tex_sz, plane_tex_sz, box_tex_sz, cone_tex_sz, xform_tex_sz;
    3.47  
    3.48  #ifdef INIT_EVERYTHING
    3.49  Material default_material;
    3.50 @@ -108,6 +117,10 @@
    3.51  	num_boxes = int(desc.x);
    3.52  	box_tex_sz = desc.y;
    3.53  
    3.54 +	desc = texture2D(tex_cones, vec2(0.0, 0.0));
    3.55 +	num_cones = int(desc.x);
    3.56 +	cone_tex_sz = desc.y;
    3.57 +
    3.58  	xform_tex_sz = texture2D(tex_xforms, vec2(0.0, 0.0)).x;
    3.59  
    3.60  
    3.61 @@ -215,6 +228,16 @@
    3.62  		}
    3.63  	}
    3.64  
    3.65 +	for(int i=0; i<num_cones; i++) {
    3.66 +		Cone cone = read_cone(i);
    3.67 +
    3.68 +		HitPoint tmphit;
    3.69 +		if(cone_intersect(cone, ray, tmphit) && tmphit.dist < hit.dist) {
    3.70 +			hit = tmphit;
    3.71 +			found = true;
    3.72 +		}
    3.73 +	}
    3.74 +
    3.75  	return found;
    3.76  }
    3.77  
    3.78 @@ -419,6 +442,77 @@
    3.79  	return false;
    3.80  }
    3.81  
    3.82 +bool cone_intersect(in Cone cone, in Ray inray, out HitPoint pt)
    3.83 +{
    3.84 +#ifdef USE_XFORM
    3.85 +	mat4 xform, inv_xform;
    3.86 +	read_xform(cone.index, xform, inv_xform);
    3.87 +
    3.88 +	Ray ray = transform(inray, inv_xform, xform);
    3.89 +#else
    3.90 +	Ray ray = inray;
    3.91 +#endif
    3.92 +
    3.93 +#ifdef INIT_EVERYTHING
    3.94 +	pt.dist = 0.0;
    3.95 +	pt.pos = pt.normal = vec3(0.0, 0.0, 0.0);
    3.96 +	pt.mat = default_material;
    3.97 +	pt.texcoord = vec2(0.0, 0.0);
    3.98 +#endif
    3.99 +
   3.100 +	float slope = 2.0 * cone.angle / M_PI;
   3.101 +
   3.102 +	float a = SQ(ray.dir.x) - SQ(slope * ray.dir.y) + SQ(ray.dir.z);
   3.103 +	float b = 2.0 * ray.origin.x * ray.dir.x - 2.0 * SQ(slope) * ray.origin.y * ray.dir.y +
   3.104 +		2.0 * ray.origin.z * ray.dir.z;
   3.105 +	float c = SQ(ray.origin.x) - SQ(slope * ray.origin.y) + SQ(ray.origin.z);
   3.106 +
   3.107 +	float discr = b * b - 4.0 * a * c;
   3.108 +	if(discr < EPSILON)
   3.109 +		return false;
   3.110 +
   3.111 +	float sqrt_discr = sqrt(discr);
   3.112 +	float t0 = (-b + sqrt_discr) / (2.0 * a);
   3.113 +	float t1 = (-b - sqrt_discr) / (2.0 * a);
   3.114 +
   3.115 +	if(t0 < EPSILON)
   3.116 +		t0 = t1;
   3.117 +	if(t1 < EPSILON)
   3.118 +		t1 = t0;
   3.119 +
   3.120 +	float t = min(t0, t1);
   3.121 +	if(t < EPSILON)
   3.122 +		return false;
   3.123 +
   3.124 +	// fill the HitPoint structure
   3.125 +	pt.dist = t;
   3.126 +	pt.pos = ray.origin + ray.dir * t;
   3.127 +
   3.128 +	if(pt.pos.y < cone.start || pt.pos.y >= cone.end) {
   3.129 +		return false;
   3.130 +	}
   3.131 +
   3.132 +	float radius = pt.pos.y * slope;
   3.133 +	pt.normal = vec3(pt.pos.x, 0.0, pt.pos.z) / radius;
   3.134 +
   3.135 +	float ny = sin(cone.angle);
   3.136 +	float xzlen = sqrt(1.0 - ny * ny);
   3.137 +	pt.normal.x *= xzlen;
   3.138 +	pt.normal.y = ny;
   3.139 +	pt.normal.z *= xzlen;
   3.140 +
   3.141 +	pt.mat = cone.mat;
   3.142 +
   3.143 +	pt.texcoord.x = 0.5 * atan(pt.normal.z, pt.normal.x) / M_PI + 0.5;
   3.144 +	pt.texcoord.y = (pt.pos.y - cone.start) / (cone.end - cone.start);
   3.145 +
   3.146 +#ifdef USE_XFORM
   3.147 +	pt.pos = (xform * vec4(pt.pos, 1.0)).xyz;
   3.148 +	pt.normal = normalize(transform(pt.normal, xform));
   3.149 +#endif
   3.150 +	return true;
   3.151 +}
   3.152 +
   3.153  vec3 transform(in vec3 v, in mat4 xform)
   3.154  {
   3.155  	return mat3(xform) * v;
   3.156 @@ -489,6 +583,22 @@
   3.157  	return box;
   3.158  }
   3.159  
   3.160 +Cone read_cone(in float idx)
   3.161 +{
   3.162 +	Cone cone;
   3.163 +	float ty = (idx + 1.0) / cone_tex_sz;
   3.164 +
   3.165 +	cone.index = texture2D(tex_cones, vec2(ITEM(0), ty)).x;
   3.166 +
   3.167 +	vec4 texel = texture2D(tex_cones, vec2(ITEM(1), ty));
   3.168 +	cone.angle = texel.x;
   3.169 +	cone.start = texel.y;
   3.170 +	cone.end = texel.z;
   3.171 +
   3.172 +	cone.mat = read_material(tex_cones, ty);
   3.173 +	return cone;
   3.174 +}
   3.175 +
   3.176  void read_xform(in float idx, out mat4 xform, out mat4 inv_xform)
   3.177  {
   3.178  	float ty = (idx + 1.0) / xform_tex_sz;
     4.1 --- a/src/cone.cc	Sun Nov 09 20:13:33 2014 +0200
     4.2 +++ b/src/cone.cc	Mon Nov 10 01:26:00 2014 +0200
     4.3 @@ -65,10 +65,20 @@
     4.4  	pt->dist = t;
     4.5  	pt->pos = ray.origin + ray.dir * t;
     4.6  
     4.7 -	pt->normal.z = sin(angle);
     4.8 +	if(pt->pos.y < ymin || pt->pos.y >= ymax) {
     4.9 +		return false;
    4.10 +	}
    4.11  
    4.12 -	//pt->normal = (pt->pos - pos) / radius; TODO continue here
    4.13 +	float radius = pt->pos.y * slope;
    4.14 +	pt->normal = Vector3(pt->pos.x, 0.0, pt->pos.z) / radius;
    4.15 +
    4.16 +	float ny = sin(angle);
    4.17 +	float xzlen = sqrt(1.0 - ny * ny);
    4.18 +	pt->normal.x *= xzlen;
    4.19 +	pt->normal.y = ny;
    4.20 +	pt->normal.z *= xzlen;
    4.21  
    4.22  	pt->pos.transform(xform);
    4.23  	pt->normal.transform(dir_xform);
    4.24 +	return true;
    4.25  }
     5.1 --- a/src/gpuscene.cc	Sun Nov 09 20:13:33 2014 +0200
     5.2 +++ b/src/gpuscene.cc	Mon Nov 10 01:26:00 2014 +0200
     5.3 @@ -35,10 +35,12 @@
     5.4  	Sphere *sph;
     5.5  	Plane *plane;
     5.6  	Box *box;
     5.7 +	Cone *cone;
     5.8  
     5.9  	std::vector<Sphere*> spheres;
    5.10  	std::vector<Plane*> planes;
    5.11  	std::vector<Box*> boxes;
    5.12 +	std::vector<Cone*> cones;
    5.13  
    5.14  	// collect all objects into the different type-specific arrays
    5.15  	for(auto obj : objects) {
    5.16 @@ -51,6 +53,9 @@
    5.17  		} else if((box = dynamic_cast<Box*>(obj))) {
    5.18  			boxes.push_back(box);
    5.19  
    5.20 +		} else if((cone = dynamic_cast<Cone*>(obj))) {
    5.21 +			cones.push_back(cone);
    5.22 +
    5.23  		} else {
    5.24  			fprintf(stderr, "skipping object of unknown type: %s\n", obj->get_name());
    5.25  		}
    5.26 @@ -59,6 +64,7 @@
    5.27  	create_sphere_texture(spheres);
    5.28  	create_plane_texture(planes);
    5.29  	create_box_texture(boxes);
    5.30 +	create_cone_texture(cones);
    5.31  
    5.32  	create_env_texture();
    5.33  	create_xform_texture();
    5.34 @@ -194,6 +200,38 @@
    5.35  	delete [] pixels;
    5.36  }
    5.37  
    5.38 +void GPUScene::create_cone_texture(const std::vector<Cone*> &cones)
    5.39 +{
    5.40 +	int xsz = OBJ_LINE_WIDTH;
    5.41 +	int ysz = (int)cones.size() + 1;
    5.42 +	int tex_ysz = next_pow2(ysz);
    5.43 +
    5.44 +	Vector4 *pixels = new Vector4[xsz * tex_ysz];
    5.45 +
    5.46 +	pixels[0].x = (float)ysz;
    5.47 +	pixels[0].y = (float)tex_ysz;
    5.48 +
    5.49 +	Vector4 *pixptr = pixels + xsz;
    5.50 +
    5.51 +	for(size_t i=0; i<cones.size(); i++) {
    5.52 +		pixptr[0].x = object_index(cones[i]);
    5.53 +
    5.54 +		pixptr[1].x = cones[i]->angle;
    5.55 +		pixptr[1].y = cones[i]->ymin;
    5.56 +		pixptr[1].z = cones[i]->ymax;
    5.57 +		pixptr[1].w = 0.0;
    5.58 +
    5.59 +		copy_material(pixptr, &cones[i]->material);
    5.60 +		pixptr += OBJ_LINE_WIDTH;
    5.61 +	}
    5.62 +
    5.63 +	glBindTexture(GL_TEXTURE_2D, textures[TEX_SPHERE]);
    5.64 +	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, xsz, tex_ysz, 0, GL_RGBA, GL_FLOAT, pixels);
    5.65 +
    5.66 +	delete [] pixels;
    5.67 +}
    5.68 +
    5.69 +
    5.70  void GPUScene::create_megatexture()
    5.71  {
    5.72  	// at least a 1x1 dummy white texture
     6.1 --- a/src/gpuscene.h	Sun Nov 09 20:13:33 2014 +0200
     6.2 +++ b/src/gpuscene.h	Mon Nov 10 01:26:00 2014 +0200
     6.3 @@ -6,10 +6,11 @@
     6.4  #include "sphere.h"
     6.5  #include "plane.h"
     6.6  #include "box.h"
     6.7 +#include "cone.h"
     6.8  
     6.9  class GPUScene : public Scene {
    6.10  public:
    6.11 -	enum { TEX_SPHERE, TEX_PLANE, TEX_BOX, TEX_TEXTURE, TEX_ENV, TEX_XFORM, NUM_TEXTURES };
    6.12 +	enum { TEX_SPHERE, TEX_PLANE, TEX_BOX, TEX_CONE, TEX_TEXTURE, TEX_ENV, TEX_XFORM, NUM_TEXTURES };
    6.13  
    6.14  private:
    6.15  	unsigned int textures[NUM_TEXTURES];
    6.16 @@ -20,6 +21,7 @@
    6.17  	void create_sphere_texture(const std::vector<Sphere*> &spheres);
    6.18  	void create_plane_texture(const std::vector<Plane*> &planes);
    6.19  	void create_box_texture(const std::vector<Box*> &box);
    6.20 +	void create_cone_texture(const std::vector<Cone*> &cones);
    6.21  	void create_megatexture();
    6.22  	void create_env_texture();
    6.23  	void create_xform_texture();
     7.1 --- a/src/rend.cc	Sun Nov 09 20:13:33 2014 +0200
     7.2 +++ b/src/rend.cc	Mon Nov 10 01:26:00 2014 +0200
     7.3 @@ -1,4 +1,6 @@
     7.4 +#include <stdio.h>
     7.5  #include <assert.h>
     7.6 +#include <algorithm>
     7.7  #include "scene.h"
     7.8  #include "image.h"
     7.9  #include "rend.h"
    7.10 @@ -10,6 +12,7 @@
    7.11  	TEX_SPHERES,
    7.12  	TEX_PLANES,
    7.13  	TEX_BOXES,
    7.14 +	TEX_CONES,
    7.15  	TEX_TEXTURES,
    7.16  	TEX_ENV,
    7.17  	TEX_XFORM,
    7.18 @@ -31,6 +34,14 @@
    7.19  {
    7.20  	scn = s;
    7.21  
    7.22 +	int max_tex_units;
    7.23 +	glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &max_tex_units);
    7.24 +	printf("maximum texture units: %d\n", max_tex_units);
    7.25 +	if(NUM_SDR_TEXTURES > max_tex_units) {
    7.26 +		fprintf(stderr, "not enough texture units available!\n");
    7.27 +		return false;
    7.28 +	}
    7.29 +
    7.30  	glGenTextures(1, textures + TEX_RAYDIR);
    7.31  	glBindTexture(GL_TEXTURE_2D, textures[TEX_RAYDIR]);
    7.32  	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    7.33 @@ -46,6 +57,7 @@
    7.34  	textures[TEX_SPHERES] = s->get_texture(GPUScene::TEX_SPHERE);
    7.35  	textures[TEX_PLANES] = s->get_texture(GPUScene::TEX_PLANE);
    7.36  	textures[TEX_BOXES] = s->get_texture(GPUScene::TEX_BOX);
    7.37 +	textures[TEX_CONES] = s->get_texture(GPUScene::TEX_CONE);
    7.38  	textures[TEX_TEXTURES] = s->get_texture(GPUScene::TEX_TEXTURE);
    7.39  	textures[TEX_ENV] = s->get_texture(GPUScene::TEX_ENV);
    7.40  	textures[TEX_XFORM] = s->get_texture(GPUScene::TEX_XFORM);
    7.41 @@ -74,6 +86,7 @@
    7.42  	set_uniform_int(sdr, "tex_spheres", TEX_SPHERES);
    7.43  	set_uniform_int(sdr, "tex_planes", TEX_PLANES);
    7.44  	set_uniform_int(sdr, "tex_boxes", TEX_BOXES);
    7.45 +	set_uniform_int(sdr, "tex_cones", TEX_CONES);
    7.46  	set_uniform_int(sdr, "tex_megatex", TEX_TEXTURES);
    7.47  	set_uniform_int(sdr, "tex_env", TEX_ENV);
    7.48  	set_uniform_int(sdr, "tex_xforms", TEX_XFORM);
     8.1 --- a/src/scene_load.cc	Sun Nov 09 20:13:33 2014 +0200
     8.2 +++ b/src/scene_load.cc	Mon Nov 10 01:26:00 2014 +0200
     8.3 @@ -5,6 +5,7 @@
     8.4  #include "sphere.h"
     8.5  #include "plane.h"
     8.6  #include "box.h"
     8.7 +#include "cone.h"
     8.8  #include "light.h"
     8.9  #include "camera.h"
    8.10  #include "texture.h"
    8.11 @@ -13,6 +14,7 @@
    8.12  static Object *parse_sphere(char **argv, const std::map<std::string, Material> &materials);
    8.13  static Object *parse_plane(char **argv, const std::map<std::string, Material> &materials);
    8.14  static Object *parse_box(char **argv, const std::map<std::string, Material> &materials);
    8.15 +static Object *parse_cone(char **argv, const std::map<std::string, Material> &materials);
    8.16  static Light *parse_light(char **argv);
    8.17  static Camera *parse_camera(char **argv);
    8.18  static bool parse_env(char **argv, Scene *scn);
    8.19 @@ -77,6 +79,14 @@
    8.20  			}
    8.21  			scn->add_object(obj);
    8.22  
    8.23 +		} else if(strstr(line, "cone") == line) {
    8.24 +			char *args = strip_space(line + strlen("cone"));
    8.25 +			Object *obj = parse_cone(split_args(args), materials);
    8.26 +			if(!obj) {
    8.27 +				goto err;
    8.28 +			}
    8.29 +			scn->add_object(obj);
    8.30 +
    8.31  		} else if(strstr(line, "light") == line) {
    8.32  			char *args = strip_space(line + strlen("light"));
    8.33  			Light *lt = parse_light(split_args(args));
    8.34 @@ -153,6 +163,7 @@
    8.35  		const Sphere *sph;
    8.36  		const Plane *plane;
    8.37  		const Box *box;
    8.38 +		const Cone *cone;
    8.39  		if((sph = dynamic_cast<const Sphere*>(obj))) {
    8.40  			fprintf(fp, "sphere -material %s", name);
    8.41  			fprintf(fp, " -center %.3f %.3f %.3f", sph->pos.x, sph->pos.y, sph->pos.z);
    8.42 @@ -165,6 +176,10 @@
    8.43  			fprintf(fp, "box -material %s", name);
    8.44  			fprintf(fp, " -min %.3f %.3f %.3f", box->min.x, box->min.y, box->min.z);
    8.45  			fprintf(fp, " -max %.3f %.3f %.3f\n", box->max.x, box->max.y, box->max.z);
    8.46 +		} else if((cone = dynamic_cast<const Cone*>(obj))) {
    8.47 +			fprintf(fp, "cone -material %s", name);
    8.48 +			fprintf(fp, " -angle %g", RAD_TO_DEG(cone->angle));
    8.49 +			fprintf(fp, " -start %g -end %g\n", cone->ymin, cone->ymax);
    8.50  		}
    8.51  	}
    8.52  
    8.53 @@ -374,6 +389,53 @@
    8.54  	return box;
    8.55  }
    8.56  
    8.57 +static Object *parse_cone(char **argv, const std::map<std::string, Material> &materials)
    8.58 +{
    8.59 +	char *endp;
    8.60 +	Cone *cone = new Cone;
    8.61 +
    8.62 +	for(int i=0; argv[i]; i++) {
    8.63 +		if(strcmp(argv[i], "-name") == 0) {
    8.64 +			cone->set_name(argv[++i]);
    8.65 +
    8.66 +		} else if(strcmp(argv[i], "-angle") == 0) {
    8.67 +			cone->angle = DEG_TO_RAD(strtod(argv[++i], &endp));
    8.68 +			if(endp == argv[i]) {
    8.69 +				fprintf(stderr, "failed to parse cone angle\n");
    8.70 +				return 0;
    8.71 +			}
    8.72 +
    8.73 +		} else if(strcmp(argv[i], "-start") == 0) {
    8.74 +			cone->ymin = strtod(argv[++i], &endp);
    8.75 +			if(endp == argv[i]) {
    8.76 +				fprintf(stderr, "failed to parse cone start\n");
    8.77 +				return 0;
    8.78 +			}
    8.79 +
    8.80 +		} else if(strcmp(argv[i], "-end") == 0) {
    8.81 +			cone->ymax = strtod(argv[++i], &endp);
    8.82 +			if(endp == argv[i]) {
    8.83 +				fprintf(stderr, "failed to parse cone end\n");
    8.84 +				return 0;
    8.85 +			}
    8.86 +
    8.87 +		} else if(strcmp(argv[i], "-material") == 0) {
    8.88 +			auto it = materials.find(argv[++i]);
    8.89 +			if(it == materials.end()) {
    8.90 +				fprintf(stderr, "material %s not found\n", argv[i]);
    8.91 +				return 0;
    8.92 +			}
    8.93 +
    8.94 +			cone->material = it->second;
    8.95 +		} else {
    8.96 +			fprintf(stderr, "invalid box option: %s\n", argv[i]);
    8.97 +			return 0;
    8.98 +		}
    8.99 +	}
   8.100 +
   8.101 +	return cone;
   8.102 +}
   8.103 +
   8.104  static Light *parse_light(char **argv)
   8.105  {
   8.106  	Light *lt = new Light;