frame3f shape_sample_uniform(Shape* shape, const vec2f& uv) { if(is<Sphere>(shape)) { auto sphere = cast<Sphere>(shape); // see: http://mathworld.wolfram.com/SpherePointPicking.html float z = 1 - 2*uv.y; float rxy = sqrt(1-z*z); float phi = 2*pif*uv.x; vec3f pl = vec3f(rxy*cos(phi),rxy*sin(phi),z); frame3f f; f.o = sphere->center + pl * sphere->radius; f.z = normalize(pl); f = orthonormalize(f); return f; } else if(is<Quad>(shape)) { auto quad = cast<Quad>(shape); frame3f f = identity_frame3f; f.o = (uv.x-0.5f)*quad->width*x3f + (uv.y-0.5f)*quad->height*y3f; return f; } else { not_implemented_error(); return identity_frame3f; } }
/* Allocates memory */ void factor_vm::primitive_unimplemented() { not_implemented_error(); }
/* For testing purposes */ void primitive_unimplemented(void) { not_implemented_error(); }
/// Tesselate Shape the given number of times /// @param shape The Shape to tesselate /// @param level The number of times to tesselate /// @param smooth Determines whether the tesselated mesh will have smoothed normals /// @return The tesselated shape Shape* tesselate_shape(Shape* shape, int level, bool smooth) { if(is<PointSet>(shape)) return new PointSet(*cast<PointSet>(shape)); else if(is<LineSet>(shape)) { auto tesselation = new LineSet(*cast<LineSet>(shape)); return _tesselate_recursive([](Shape* s){ return _tesselate_lineset_once(cast<LineSet>(s));}, tesselation, level, smooth); } else if(is<TriangleMesh>(shape)) { auto tesselation = new TriangleMesh(*cast<TriangleMesh>(shape)); tesselation->_tesselation_lines = EdgeHashTable(tesselation->triangle, vector<vec4i>()).edges; return _tesselate_recursive([](Shape* s){ return _tesselate_trianglemesh_once(cast<TriangleMesh>(s));}, tesselation, level, smooth); } else if(is<Mesh>(shape)) { auto tesselation = new Mesh(*cast<Mesh>(shape)); tesselation->_tesselation_lines = EdgeHashTable(tesselation->triangle,tesselation->quad).edges; return _tesselate_recursive([](Shape* s){ return _tesselate_mesh_once(cast<Mesh>(s));}, tesselation, level, smooth); } else if(is<CatmullClarkSubdiv>(shape)) { auto tesselation = new CatmullClarkSubdiv(*cast<CatmullClarkSubdiv>(shape)); tesselation->_tesselation_lines = EdgeHashTable(vector<vec3i>(),tesselation->quad).edges; return _tesselate_recursive([](Shape* s){ return _tesselate_catmullclark_once(cast<CatmullClarkSubdiv>(s));}, tesselation, level, smooth, [](Shape* s) { auto subdiv = cast<CatmullClarkSubdiv>(s); auto mesh = new Mesh(); mesh->pos = subdiv->pos; mesh->norm = subdiv->norm; mesh->texcoord = subdiv->texcoord; mesh->quad = subdiv->quad; mesh->_tesselation_lines = subdiv->_tesselation_lines; return mesh; }); } else if(is<Subdiv>(shape)) { auto tesselation = new Subdiv(*cast<Subdiv>(shape)); tesselation->_tesselation_lines = EdgeHashTable(tesselation->triangle,tesselation->quad).edges; return _tesselate_recursive([](Shape* s){ return _tesselate_subdiv_once(cast<Subdiv>(s));}, tesselation, level, smooth, [](Shape* s) { auto subdiv = cast<Subdiv>(s); auto mesh = new Mesh(); mesh->pos = subdiv->pos; mesh->norm = subdiv->norm; mesh->texcoord = subdiv->texcoord; mesh->triangle = subdiv->triangle; mesh->quad = subdiv->quad; mesh->_tesselation_lines = subdiv->_tesselation_lines; return mesh; }); } else if(is<Spline>(shape)) { auto spline = cast<Spline>(shape); auto tesselation = new Shape(); if(spline->casteljau) { tesselation = tessellate_adaptive(spline); } else { tesselation = _tesselate_shape_uniform( [spline](float u){ return spline_frame(spline,spline_continous_segment(spline,u), spline_continous_param(spline, u)); }, [spline](float u){ auto elementid = spline_continous_segment(spline,u); auto t = spline_continous_param(spline, u); auto s = spline->cubic[elementid]; return interpolate_bezier_cubic(spline->radius, s, t); }, spline->cubic.size()*pow2(level+2), smooth); } return tesselation; } else if(is<Patch>(shape)) { auto patch = cast<Patch>(shape); auto segments = vec2i(patch->continous_stride,patch->cubic.size()/patch->continous_stride); return _tesselate_shape_uniform( [patch](const vec2f& uv){ return patch_frame(patch,patch_continous_segment(patch, uv), patch_continous_param(patch, uv)); }, segments.x*pow2(level+2), segments.y*pow2(level+2), segments.x*pow2(2), segments.y*pow2(2), false, smooth); } else if(is<TesselationOverride>(shape)) return tesselate_shape(cast<TesselationOverride>(shape)->shape, level, smooth); else if(is<Sphere>(shape)) { auto sphere = cast<Sphere>(shape); return _tesselate_shape_uniform([sphere](const vec2f& uv){return sphere_frame(sphere,uv);}, pow2(level+2), pow2(level+2), pow2(2), pow2(2), true, smooth); } else if(is<Cylinder>(shape)) { auto cylinder = cast<Cylinder>(shape); return _tesselate_shape_uniform([cylinder](const vec2f& uv){return cylinder_frame(cylinder,uv);}, pow2(level+2), pow2(level+2), pow2(2), pow2(2), true, smooth); } else if(is<Quad>(shape)) { auto quad = cast<Quad>(shape); auto mesh = new Mesh(); mesh->pos = { {-quad->width/2,-quad->height/2,0}, {quad->width/2,-quad->height/2,0}, {quad->width/2, quad->height/2,0}, {-quad->width/2, quad->height/2,0} }; mesh->texcoord = { {0,0}, {1,0}, {1,1}, {0,1} }; mesh->quad = { {0,1,2,3} }; auto tesselation = tesselate_shape(mesh,level,smooth); delete mesh; return tesselation; } else if(is<Triangle>(shape)) { auto triangle = cast<Triangle>(shape); auto mesh = new TriangleMesh(); mesh->pos = { triangle->v0, triangle->v1, triangle->v2 }; mesh->texcoord = { {0,0}, {1,0}, {0,1} }; mesh->triangle = { {0,1,2} }; auto tesselation = tesselate_shape(mesh,level,smooth); delete mesh; return tesselation; } else { not_implemented_error(); return nullptr; } }
VM_C_API int inotify_rm_watch(int fd, u32 wd) { not_implemented_error(); return -1; }
VM_C_API int inotify_add_watch(int fd, const char *name, u32 mask) { not_implemented_error(); return -1; }
VM_C_API int inotify_init() { not_implemented_error(); return -1; }
void serialize_members(Node* node, Serializer& ser) { if(not node) warning("node is null"); else if(is<Shape>(node)) { auto shape = cast<Shape>(node); if(not shape) error("node is null"); else if(is<Sphere>(node)) { auto sphere = cast<Sphere>(node); ser.serialize_member("r",sphere->r); } else if(is<Cylinder>(node)) { auto cylinder = cast<Cylinder>(node); ser.serialize_member("r",cylinder->r); ser.serialize_member("h",cylinder->h); } else if(is<CappedCylinder>(node)) { auto cylinder = cast<CappedCylinder>(node); ser.serialize_member("r",cylinder->r); ser.serialize_member("h",cylinder->h); } else if(is<Quad>(node)) { auto quad = cast<Quad>(node); ser.serialize_member("w",quad->w); ser.serialize_member("h",quad->h); } else if(is<Triangle>(node)) { auto triangle = cast<Triangle>(node); ser.serialize_member("v0",triangle->v0); ser.serialize_member("v1",triangle->v1); ser.serialize_member("v2",triangle->v2); } else not_implemented_error(); } else if(is<Material>(node)) { auto material = cast<Material>(node); if(not material) error("node is null"); else if(is<Lambert>(node)) { auto lambert = cast<Lambert>(node); ser.serialize_member("kd",lambert->kd); } else if(is<Blinn>(node)) { auto blinn = cast<Blinn>(node); ser.serialize_member("kd",blinn->kd); ser.serialize_member("ks",blinn->ks); ser.serialize_member("kr",blinn->kr); ser.serialize_member("n",blinn->n); } else not_implemented_error(); } else if(is<Camera>(node)) { auto camera = cast<Camera>(node); ser.serialize_member("f",camera->f); ser.serialize_member("l",camera->l); ser.serialize_member("w",camera->w); ser.serialize_member("h",camera->h); ser.serialize_member("d",camera->d); } else if(is<Light>(node)) { auto light = cast<Light>(node); ser.serialize_member("f",light->f); if(is<PointLight>(node)) { auto points = cast<PointLight>(node); ser.serialize_member("intensity",points->intensity); } else if(is<DirectionalLight>(node)) { auto directional = cast<DirectionalLight>(node); ser.serialize_member("intensity",directional->intensity); } else not_implemented_error(); } else if(is<LightGroup>(node)) { auto lights = cast<LightGroup>(node); ser.serialize_member("lights",lights->lights); } else if(is<Primitive>(node)) { auto prim = cast<Primitive>(node); ser.serialize_member("f",prim->f); ser.serialize_member("material",prim->material); if(not prim) error("node is null"); else if(is<Surface>(node)) { auto surface = cast<Surface>(node); ser.serialize_member("shape",surface->shape); } else not_implemented_error(); } else if(is<PrimitiveGroup>(node)) { auto group = cast<PrimitiveGroup>(node); ser.serialize_member("prims",group->prims); } else if(is<Scene>(node)) { auto scene = cast<Scene>(node); ser.serialize_member("camera",scene->camera); ser.serialize_member("lights",scene->lights); ser.serialize_member("prims",scene->prims); } else if(is<RaytraceOptions>(node)) { auto opts = cast<RaytraceOptions>(node); ser.serialize_member("res", opts->res); ser.serialize_member("samples", opts->samples); ser.serialize_member("doublesided", opts->doublesided); ser.serialize_member("time", opts->time); ser.serialize_member("background", opts->background); ser.serialize_member("ambient", opts->ambient); ser.serialize_member("shadows", opts->shadows); ser.serialize_member("reflections", opts->reflections); } else not_implemented_error(); }