int _make_sphere( float *data, float r, int detail, float *a, float *b, float *c, float *ta, float *tb, float *tc) { if (detail == 0) { float *d = data; *(d++) = a[0] * r; *(d++) = a[1] * r; *(d++) = a[2] * r; *(d++) = a[0]; *(d++) = a[1]; *(d++) = a[2]; *(d++) = ta[0]; *(d++) = ta[1]; *(d++) = b[0] * r; *(d++) = b[1] * r; *(d++) = b[2] * r; *(d++) = b[0]; *(d++) = b[1]; *(d++) = b[2]; *(d++) = tb[0]; *(d++) = tb[1]; *(d++) = c[0] * r; *(d++) = c[1] * r; *(d++) = c[2] * r; *(d++) = c[0]; *(d++) = c[1]; *(d++) = c[2]; *(d++) = tc[0]; *(d++) = tc[1]; return 1; } else { float ab[3], ac[3], bc[3]; for (int i = 0; i < 3; i++) { ab[i] = (a[i] + b[i]) / 2; ac[i] = (a[i] + c[i]) / 2; bc[i] = (b[i] + c[i]) / 2; } normalize(ab + 0, ab + 1, ab + 2); normalize(ac + 0, ac + 1, ac + 2); normalize(bc + 0, bc + 1, bc + 2); float tab[2], tac[2], tbc[2]; tab[0] = 0; tab[1] = 1 - acosf(ab[1]) / PI; tac[0] = 0; tac[1] = 1 - acosf(ac[1]) / PI; tbc[0] = 0; tbc[1] = 1 - acosf(bc[1]) / PI; int total = 0; int n; n = _make_sphere(data, r, detail - 1, a, ab, ac, ta, tab, tac); total += n; data += n * 24; n = _make_sphere(data, r, detail - 1, b, bc, ab, tb, tbc, tab); total += n; data += n * 24; n = _make_sphere(data, r, detail - 1, c, ac, bc, tc, tac, tbc); total += n; data += n * 24; n = _make_sphere(data, r, detail - 1, ab, bc, ac, tab, tbc, tac); total += n; data += n * 24; return total; } }
void make_sphere(float *data, float r, int detail) { // detail, triangles, floats // 0, 8, 192 // 1, 32, 768 // 2, 128, 3072 // 3, 512, 12288 // 4, 2048, 49152 // 5, 8192, 196608 // 6, 32768, 786432 // 7, 131072, 3145728 static int indices[8][3] = { {4, 3, 0}, {1, 4, 0}, {3, 4, 5}, {4, 1, 5}, {0, 3, 2}, {0, 2, 1}, {5, 2, 3}, {5, 1, 2} }; static float positions[6][3] = { { 0, 0,-1}, { 1, 0, 0}, { 0,-1, 0}, {-1, 0, 0}, { 0, 1, 0}, { 0, 0, 1} }; static float uvs[6][3] = { {0, 0.5}, {0, 0.5}, {0, 0}, {0, 0.5}, {0, 1}, {0, 0.5} }; int total = 0; for (int i = 0; i < 8; i++) { int n = _make_sphere( data, r, detail, positions[indices[i][0]], positions[indices[i][1]], positions[indices[i][2]], uvs[indices[i][0]], uvs[indices[i][1]], uvs[indices[i][2]]); total += n; data += n * 24; } }
RES Light::_get_gizmo_geometry() const { Ref<FixedMaterial> mat_area( memnew( FixedMaterial )); mat_area->set_parameter( FixedMaterial::PARAM_DIFFUSE,Color(0.7,0.6,0.0,0.05) ); mat_area->set_parameter( FixedMaterial::PARAM_EMISSION,Color(0.7,0.7,0.7) ); mat_area->set_blend_mode( Material::BLEND_MODE_ADD ); mat_area->set_flag(Material::FLAG_DOUBLE_SIDED,true); // mat_area->set_hint(Material::HINT_NO_DEPTH_DRAW,true); Ref<FixedMaterial> mat_light( memnew( FixedMaterial )); mat_light->set_parameter( FixedMaterial::PARAM_DIFFUSE, Color(1.0,1.0,0.8,0.9) ); mat_light->set_flag(Material::FLAG_UNSHADED,true); Ref< Mesh > mesh; Ref<SurfaceTool> surftool( memnew( SurfaceTool )); switch(type) { case VisualServer::LIGHT_DIRECTIONAL: { mat_area->set_parameter( FixedMaterial::PARAM_DIFFUSE,Color(0.9,0.8,0.1,0.8) ); mat_area->set_blend_mode( Material::BLEND_MODE_MIX); mat_area->set_flag(Material::FLAG_DOUBLE_SIDED,false); mat_area->set_flag(Material::FLAG_UNSHADED,true); _make_sphere( 5,5,0.6, surftool ); surftool->set_material(mat_light); mesh=surftool->commit(mesh); // float radius=1; surftool->begin(Mesh::PRIMITIVE_TRIANGLES); const int arrow_points=5; Vector3 arrow[arrow_points]={ Vector3(0,0,2), Vector3(1,1,2), Vector3(1,1,-1), Vector3(2,2,-1), Vector3(0,0,-3) }; int arrow_sides=4; for(int i = 0; i < arrow_sides ; i++) { Matrix3 ma(Vector3(0,0,1),Math_PI*2*float(i)/arrow_sides); Matrix3 mb(Vector3(0,0,1),Math_PI*2*float(i+1)/arrow_sides); for(int j=0;j<arrow_points-1;j++) { Vector3 points[4]={ ma.xform(arrow[j]), mb.xform(arrow[j]), mb.xform(arrow[j+1]), ma.xform(arrow[j+1]), }; Vector3 n = Plane(points[0],points[1],points[2]).normal; surftool->add_normal(n); surftool->add_vertex(points[0]); surftool->add_normal(n); surftool->add_vertex(points[1]); surftool->add_normal(n); surftool->add_vertex(points[2]); surftool->add_normal(n); surftool->add_vertex(points[0]); surftool->add_normal(n); surftool->add_vertex(points[2]); surftool->add_normal(n); surftool->add_vertex(points[3]); } } surftool->set_material(mat_area); mesh=surftool->commit(mesh); } break; case VisualServer::LIGHT_OMNI: { _make_sphere( 20,20,vars[PARAM_RADIUS], surftool ); surftool->set_material(mat_area); mesh=surftool->commit(mesh); _make_sphere(5,5, 0.1, surftool ); surftool->set_material(mat_light); mesh=surftool->commit(mesh); } break; case VisualServer::LIGHT_SPOT: { _make_sphere( 5,5,0.1, surftool ); surftool->set_material(mat_light); mesh=surftool->commit(mesh); // make cone int points=24; float len=vars[PARAM_RADIUS]; float size=Math::tan(Math::deg2rad(vars[PARAM_SPOT_ANGLE]))*len; surftool->begin(Mesh::PRIMITIVE_TRIANGLES); for(int i = 0; i < points; i++) { float x0=Math::sin(i * Math_PI * 2 / points); float y0=Math::cos(i * Math_PI * 2 / points); float x1=Math::sin((i+1) * Math_PI * 2 / points); float y1=Math::cos((i+1) * Math_PI * 2 / points); Vector3 v1=Vector3(x0*size,y0*size,-len).normalized()*len; Vector3 v2=Vector3(x1*size,y1*size,-len).normalized()*len; Vector3 v3=Vector3(0,0,0); Vector3 v4=Vector3(0,0,v1.z); Vector3 n = Plane(v1,v2,v3).normal; surftool->add_normal(n); surftool->add_vertex(v1); surftool->add_normal(n); surftool->add_vertex(v2); surftool->add_normal(n); surftool->add_vertex(v3); n=Vector3(0,0,-1); surftool->add_normal(n); surftool->add_vertex(v1); surftool->add_normal(n); surftool->add_vertex(v2); surftool->add_normal(n); surftool->add_vertex(v4); } surftool->set_material(mat_area); mesh=surftool->commit(mesh); } break; } return mesh; }