|  | @@ -117,6 +117,7 @@ const char LA_IMM_FRAGMENT_SHADER[] = "#version 330\n\
 | 
	
		
			
				|  |  |  uniform sampler2D TexColor;\
 | 
	
		
			
				|  |  |  uniform sampler2DMS TexColorMS;\
 | 
	
		
			
				|  |  |  uniform int TextureMode;\n\
 | 
	
		
			
				|  |  | +uniform int ColorMode;\n\
 | 
	
		
			
				|  |  |  uniform int MultiplyColor;\n\
 | 
	
		
			
				|  |  |  uniform int SampleAmount;\n\
 | 
	
		
			
				|  |  |  uniform int UseNormal;\n\
 | 
	
	
		
			
				|  | @@ -128,6 +129,7 @@ in vec3 fGPos;\n\
 | 
	
		
			
				|  |  |  layout(location = 0) out vec4 outColor;\n\
 | 
	
		
			
				|  |  |  layout(location = 1) out vec3 outNormal;\n\
 | 
	
		
			
				|  |  |  layout(location = 2) out vec3 outGPos;\n\
 | 
	
		
			
				|  |  | +#with TNS_SHADER_COLOR_COMMON\n\
 | 
	
		
			
				|  |  |  void main(){\n\
 | 
	
		
			
				|  |  |      vec4 color=vec4(1,0,1,1);\n\
 | 
	
		
			
				|  |  |      if(TextureMode==0){ color = fColor;}\n\
 | 
	
	
		
			
				|  | @@ -151,6 +153,7 @@ void main(){\n\
 | 
	
		
			
				|  |  |          vec3 oNormal=fNormal; if(view<0){ oNormal=-fNormal; }\n\
 | 
	
		
			
				|  |  |          outNormal = oNormal;\n\
 | 
	
		
			
				|  |  |      }\n\
 | 
	
		
			
				|  |  | +    if(ColorMode!=0){ color.rgb=okhsl_to_srgb(color.rgb); }\n\
 | 
	
		
			
				|  |  |      outColor = color;\n\
 | 
	
		
			
				|  |  |      outGPos = fGPos;\n\
 | 
	
		
			
				|  |  |  }";
 | 
	
	
		
			
				|  | @@ -526,7 +529,9 @@ void tnsShaderApplyShadowMatrix(tnsShader *tns, tnsMatrix44d m){
 | 
	
		
			
				|  |  |      glUniformMatrix4fv(tns->iShadow, 1, 0, mf);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -//--------------------Export
 | 
	
		
			
				|  |  | +char* tnsEnsureShaderCommoms(char* Content){
 | 
	
		
			
				|  |  | +    return strSub(Content,"#with TNS_SHADER_COLOR_COMMON",TNS_SHADER_COLOR_COMMON);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  int tnsNewVertexShader(char *Content){
 | 
	
		
			
				|  |  |      int status = 0;
 | 
	
		
			
				|  |  |      char error[1024];
 | 
	
	
		
			
				|  | @@ -537,7 +542,8 @@ int tnsNewVertexShader(char *Content){
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      VertexShaderObject = glCreateShader(GL_VERTEX_SHADER);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    glShaderSource(VertexShaderObject, 1, &Content, 0);
 | 
	
		
			
				|  |  | +    char* UseContent=tnsEnsureShaderCommoms(Content);
 | 
	
		
			
				|  |  | +    glShaderSource(VertexShaderObject, 1, &UseContent, 0); free(UseContent);
 | 
	
		
			
				|  |  |      glCompileShader(VertexShaderObject);
 | 
	
		
			
				|  |  |      glGetShaderiv(VertexShaderObject, GL_COMPILE_STATUS, &status);
 | 
	
		
			
				|  |  |      if (status == GL_FALSE){
 | 
	
	
		
			
				|  | @@ -559,7 +565,8 @@ int tnsNewFragmentShader(char *Content){
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      FragmentShaderObject = glCreateShader(GL_FRAGMENT_SHADER);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    glShaderSource(FragmentShaderObject, 1, &Content, 0);
 | 
	
		
			
				|  |  | +    char* UseContent=tnsEnsureShaderCommoms(Content);
 | 
	
		
			
				|  |  | +    glShaderSource(FragmentShaderObject, 1, &UseContent, 0); free(UseContent);
 | 
	
		
			
				|  |  |      glCompileShader(FragmentShaderObject);
 | 
	
		
			
				|  |  |      glGetShaderiv(FragmentShaderObject, GL_COMPILE_STATUS, &status);
 | 
	
		
			
				|  |  |      if (status == GL_FALSE){
 | 
	
	
		
			
				|  | @@ -581,7 +588,8 @@ int tnsNewGeometryShader(char *Content){
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      GeometryShaderObject = glCreateShader(GL_GEOMETRY_SHADER);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    glShaderSource(GeometryShaderObject, 1, &Content, 0);
 | 
	
		
			
				|  |  | +    char* UseContent=tnsEnsureShaderCommoms(Content);
 | 
	
		
			
				|  |  | +    glShaderSource(GeometryShaderObject, 1, &UseContent, 0); free(UseContent);
 | 
	
		
			
				|  |  |      glCompileShader(GeometryShaderObject);
 | 
	
		
			
				|  |  |      glGetShaderiv(GeometryShaderObject, GL_COMPILE_STATUS, &status);
 | 
	
		
			
				|  |  |      if (status == GL_FALSE){
 | 
	
	
		
			
				|  | @@ -1976,6 +1984,9 @@ void tnsUniformUseMultiplyColor(tnsShader* s, int enable){
 | 
	
		
			
				|  |  |      int mode=enable?1:0;
 | 
	
		
			
				|  |  |      if(s->StateMultiplyColor != mode){ s->StateMultiplyColor=mode; glUniform1i(s->iMultiplyColor,mode); }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  | +void tnsUniformColorMode(tnsShader* s, int mode){
 | 
	
		
			
				|  |  | +    glUniform1i(s->iColorMode,mode);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  void tnsDraw2DTextureDirectly(tnsTexture *t, real x, real y, real w, real h){
 | 
	
		
			
				|  |  |      real Verts[8];
 | 
	
	
		
			
				|  | @@ -2644,7 +2655,7 @@ void tnsDrawToOffscreen(tnsOffscreen *toff, int HowMany, GLuint *AttachmentArray
 | 
	
		
			
				|  |  |      T->IsOffscreen = 1;
 | 
	
		
			
				|  |  |      T->BindedShader = 0;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  | -//void tnsDrawToExtraColorAttachment(tnsOffscreen *toff){
 | 
	
		
			
				|  |  | +//void tnsDraw_toextraColorAttachment(tnsOffscreen *toff){
 | 
	
		
			
				|  |  |  //    if (!toff) return;
 | 
	
		
			
				|  |  |  //    if (!toff->pColor[1]){
 | 
	
		
			
				|  |  |  //        tnsCreate2DOffscreenMSAttachmentExtraColor(toff);
 | 
	
	
		
			
				|  | @@ -2654,7 +2665,7 @@ void tnsDrawToOffscreen(tnsOffscreen *toff, int HowMany, GLuint *AttachmentArray
 | 
	
		
			
				|  |  |  //    T->IsOffscreen = 1;
 | 
	
		
			
				|  |  |  //    T->BindedShader = 0;
 | 
	
		
			
				|  |  |  //}
 | 
	
		
			
				|  |  | -//void tnsDrawToExtraNormalAttachment(tnsOffscreen *toff){
 | 
	
		
			
				|  |  | +//void tnsDraw_toextraNormalAttachment(tnsOffscreen *toff){
 | 
	
		
			
				|  |  |  //    if (!toff) return;
 | 
	
		
			
				|  |  |  //    if (!toff->pColor[2]){
 | 
	
		
			
				|  |  |  //        tnsCreate2DOffscreenMSAttachmentExtraNormal(toff);
 | 
	
	
		
			
				|  | @@ -3811,17 +3822,17 @@ void tnsLinearToLog(real *rgb, real gamma){
 | 
	
		
			
				|  |  |      if (rgb[0] < 0) rgb[0] = 0;
 | 
	
		
			
				|  |  |      if (rgb[1] < 0) rgb[1] = 0;
 | 
	
		
			
				|  |  |      if (rgb[2] < 0) rgb[2] = 0;
 | 
	
		
			
				|  |  | -    rgb[0] = powf(rgb[0], gamma);
 | 
	
		
			
				|  |  | -    rgb[1] = powf(rgb[1], gamma);
 | 
	
		
			
				|  |  | -    rgb[2] = powf(rgb[2], gamma);
 | 
	
		
			
				|  |  | +    rgb[0] = pow(rgb[0], gamma);
 | 
	
		
			
				|  |  | +    rgb[1] = pow(rgb[1], gamma);
 | 
	
		
			
				|  |  | +    rgb[2] = pow(rgb[2], gamma);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  void tnsLogToLinear(real *rgb, real gamma){
 | 
	
		
			
				|  |  |      if (rgb[0] < 0) rgb[0] = 0;
 | 
	
		
			
				|  |  |      if (rgb[1] < 0) rgb[1] = 0;
 | 
	
		
			
				|  |  |      if (rgb[2] < 0) rgb[2] = 0;
 | 
	
		
			
				|  |  | -    rgb[0] = powf(rgb[0], 1.0f / gamma);
 | 
	
		
			
				|  |  | -    rgb[1] = powf(rgb[1], 1.0f / gamma);
 | 
	
		
			
				|  |  | -    rgb[2] = powf(rgb[2], 1.0f / gamma);
 | 
	
		
			
				|  |  | +    rgb[0] = pow(rgb[0], 1.0f / gamma);
 | 
	
		
			
				|  |  | +    rgb[1] = pow(rgb[1], 1.0f / gamma);
 | 
	
		
			
				|  |  | +    rgb[2] = pow(rgb[2], 1.0f / gamma);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  void tnsRgbToLuminance(real *rgb){
 | 
	
		
			
				|  |  |      real l;
 | 
	
	
		
			
				|  | @@ -3832,153 +3843,277 @@ void tnsRgbToLuminance(real *rgb){
 | 
	
		
			
				|  |  |      rgb[0] = rgb[1] = rgb[2] = l;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static const double LA_LUMA_WEIGHTS[]={ 0.2126, 0.7152, 0.0722 };
 | 
	
		
			
				|  |  | -void tnsHCYtoRGB(real *hcy, real *rgb){
 | 
	
		
			
				|  |  | -    double red, green, blue;
 | 
	
		
			
				|  |  | -    double Y_peak = 0., H_insec, X, m;
 | 
	
		
			
				|  |  | -    int H_sec;
 | 
	
		
			
				|  |  | +real _srgb_transfer_function(real a){
 | 
	
		
			
				|  |  | +	return .0031308f >= a ? 12.92f * a : 1.055f * powf(a, .4166666666666667f) - .055f;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +real _srgb_transfer_function_inv(real a){
 | 
	
		
			
				|  |  | +	return .04045f < a ? powf((a + .055f) / 1.055f, 2.4f) : a / 12.92f;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +void tnsRGB2OKLAB(real* rgb, real* oklab){
 | 
	
		
			
				|  |  | +    real l = 0.4122214708f * rgb[0] + 0.5363325363f * rgb[1] + 0.0514459929f * rgb[2];
 | 
	
		
			
				|  |  | +	real m = 0.2119034982f * rgb[0] + 0.6806995451f * rgb[1] + 0.1073969566f * rgb[2];
 | 
	
		
			
				|  |  | +	real s = 0.0883024619f * rgb[0] + 0.2817188376f * rgb[1] + 0.6299787005f * rgb[2];
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    double hue = hcy[0];
 | 
	
		
			
				|  |  | -    double chroma = hcy[1];
 | 
	
		
			
				|  |  | -    double luma = hcy[2];
 | 
	
		
			
				|  |  | -    double* weights=LA_LUMA_WEIGHTS;
 | 
	
		
			
				|  |  | +    real l_ = cbrt(l); real m_ = cbrt(m); real s_ = cbrt(s);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    if (chroma < DBL_EPSILON){
 | 
	
		
			
				|  |  | -        red = green = blue = luma;
 | 
	
		
			
				|  |  | -    }else{
 | 
	
		
			
				|  |  | -        hue = fmod(hue, 1.0);
 | 
	
		
			
				|  |  | -        hue += hue < 0.0;
 | 
	
		
			
				|  |  | -        hue *= 6.0;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        H_sec = (int)hue;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        switch (H_sec){
 | 
	
		
			
				|  |  | -        case 0:
 | 
	
		
			
				|  |  | -            H_insec = hue - H_sec;
 | 
	
		
			
				|  |  | -            Y_peak = weights[0] + H_insec * weights[1];
 | 
	
		
			
				|  |  | -            chroma *= luma < Y_peak ? luma / Y_peak : (1. - luma) / (1. - Y_peak);
 | 
	
		
			
				|  |  | -            X = chroma * H_insec;
 | 
	
		
			
				|  |  | -            m = luma - (weights[0] * chroma + weights[1] * X);
 | 
	
		
			
				|  |  | -            red = m + chroma;
 | 
	
		
			
				|  |  | -            green = m + X;
 | 
	
		
			
				|  |  | -            blue = m;
 | 
	
		
			
				|  |  | -            break;
 | 
	
		
			
				|  |  | -        case 1:
 | 
	
		
			
				|  |  | -            H_insec = 1. - (hue - H_sec);
 | 
	
		
			
				|  |  | -            Y_peak = weights[1] + H_insec * weights[0];
 | 
	
		
			
				|  |  | -            chroma *= luma < Y_peak ? luma / Y_peak : (1. - luma) / (1. - Y_peak);
 | 
	
		
			
				|  |  | -            X = chroma * H_insec;
 | 
	
		
			
				|  |  | -            m = luma - (weights[0] * X + weights[1] * chroma);
 | 
	
		
			
				|  |  | -            red = m + X;
 | 
	
		
			
				|  |  | -            green = m + chroma;
 | 
	
		
			
				|  |  | -            blue = m;
 | 
	
		
			
				|  |  | -            break;
 | 
	
		
			
				|  |  | -        case 2:
 | 
	
		
			
				|  |  | -            H_insec = hue - H_sec;
 | 
	
		
			
				|  |  | -            Y_peak = weights[1] + H_insec * weights[2];
 | 
	
		
			
				|  |  | -            chroma *= luma < Y_peak ? luma / Y_peak : (1. - luma) / (1. - Y_peak);
 | 
	
		
			
				|  |  | -            X = chroma * H_insec;
 | 
	
		
			
				|  |  | -            m = luma - (weights[1] * chroma + weights[2] * X);
 | 
	
		
			
				|  |  | -            red = m;
 | 
	
		
			
				|  |  | -            green = m + chroma;
 | 
	
		
			
				|  |  | -            blue = m + X;
 | 
	
		
			
				|  |  | -            break;
 | 
	
		
			
				|  |  | -        case 3:
 | 
	
		
			
				|  |  | -            H_insec = 1. - (hue - H_sec);
 | 
	
		
			
				|  |  | -            Y_peak = weights[2] + H_insec * weights[1];
 | 
	
		
			
				|  |  | -            chroma *= luma < Y_peak ? luma / Y_peak : (1. - luma) / (1. - Y_peak);
 | 
	
		
			
				|  |  | -            X = chroma * H_insec;
 | 
	
		
			
				|  |  | -            m = luma - (weights[1] * X + weights[2] * chroma);
 | 
	
		
			
				|  |  | -            red = m;
 | 
	
		
			
				|  |  | -            green = m + X;
 | 
	
		
			
				|  |  | -            blue = m + chroma;
 | 
	
		
			
				|  |  | -            break;
 | 
	
		
			
				|  |  | -        case 4:
 | 
	
		
			
				|  |  | -            H_insec = hue - H_sec;
 | 
	
		
			
				|  |  | -            Y_peak = weights[2] + H_insec * weights[0];
 | 
	
		
			
				|  |  | -            chroma *= luma < Y_peak ? luma / Y_peak : (1. - luma) / (1. - Y_peak);
 | 
	
		
			
				|  |  | -            X = chroma * H_insec;
 | 
	
		
			
				|  |  | -            m = luma - (weights[0] * X + weights[2] * chroma);
 | 
	
		
			
				|  |  | -            red = m + X;
 | 
	
		
			
				|  |  | -            green = m;
 | 
	
		
			
				|  |  | -            blue = m + chroma;
 | 
	
		
			
				|  |  | -            break;
 | 
	
		
			
				|  |  | -        default:
 | 
	
		
			
				|  |  | -            H_insec = 1. - (hue - H_sec);
 | 
	
		
			
				|  |  | -            Y_peak = weights[0] + H_insec * weights[2];
 | 
	
		
			
				|  |  | -            chroma *= luma < Y_peak ? luma / Y_peak : (1. - luma) / (1. - Y_peak);
 | 
	
		
			
				|  |  | -            X = chroma * H_insec;
 | 
	
		
			
				|  |  | -            m = luma - (weights[0] * chroma + weights[2] * X);
 | 
	
		
			
				|  |  | -            red = m + chroma;
 | 
	
		
			
				|  |  | -            green = m;
 | 
	
		
			
				|  |  | -            blue = m + X;
 | 
	
		
			
				|  |  | -            break;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | +    oklab[0]=0.2104542553f*l_ + 0.7936177850f*m_ - 0.0040720468f*s_;
 | 
	
		
			
				|  |  | +    oklab[1]=1.9779984951f*l_ - 2.4285922050f*m_ + 0.4505937099f*s_;
 | 
	
		
			
				|  |  | +    oklab[2]=0.0259040371f*l_ + 0.7827717662f*m_ - 0.8086757660f*s_;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +void tnsOKLAB2RGB(real* oklab, real* rgb){
 | 
	
		
			
				|  |  | +    real l_ = oklab[0] + 0.3963377774f * oklab[1] + 0.2158037573f * oklab[2];
 | 
	
		
			
				|  |  | +    real m_ = oklab[0] - 0.1055613458f * oklab[1] - 0.0638541728f * oklab[2];
 | 
	
		
			
				|  |  | +    real s_ = oklab[0] - 0.0894841775f * oklab[1] - 1.2914855480f * oklab[2];
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    rgb[0] =red;
 | 
	
		
			
				|  |  | -    rgb[1] =green;
 | 
	
		
			
				|  |  | -    rgb[2] =blue;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -void tnsRGBtoHCY(real *rgb, real *hcy){
 | 
	
		
			
				|  |  | -    double hue, chroma, luma;
 | 
	
		
			
				|  |  | -    double X, Y_peak = 0.;
 | 
	
		
			
				|  |  | -    int H_sec = 4, t = -1;
 | 
	
		
			
				|  |  | -    double* weights=LA_LUMA_WEIGHTS;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    int ix[3] = {0, 1, 2};
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    if (rgb[0] < rgb[1]){
 | 
	
		
			
				|  |  | -        if (rgb[1] > rgb[2]){
 | 
	
		
			
				|  |  | -            if (rgb[0] < rgb[2]){
 | 
	
		
			
				|  |  | -                ix[1] = 2;
 | 
	
		
			
				|  |  | -                ix[2] = 1;
 | 
	
		
			
				|  |  | -                H_sec = 2;
 | 
	
		
			
				|  |  | -                t = 1;
 | 
	
		
			
				|  |  | -            }else{
 | 
	
		
			
				|  |  | -                ix[0] = 2;
 | 
	
		
			
				|  |  | -                ix[1] = 0;
 | 
	
		
			
				|  |  | -                ix[2] = 1;
 | 
	
		
			
				|  |  | -                H_sec = 2;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -    }else{
 | 
	
		
			
				|  |  | -        if (rgb[1] < rgb[2]){
 | 
	
		
			
				|  |  | -            if (rgb[0] < rgb[2]){
 | 
	
		
			
				|  |  | -                ix[0] = 1;
 | 
	
		
			
				|  |  | -                ix[1] = 0;
 | 
	
		
			
				|  |  | -                H_sec = 4;
 | 
	
		
			
				|  |  | -                t = 1;
 | 
	
		
			
				|  |  | -            }else{
 | 
	
		
			
				|  |  | -                ix[0] = 1;
 | 
	
		
			
				|  |  | -                ix[1] = 2;
 | 
	
		
			
				|  |  | -                ix[2] = 0;
 | 
	
		
			
				|  |  | -                H_sec = 6;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -        }else{
 | 
	
		
			
				|  |  | -            ix[0] = 2;
 | 
	
		
			
				|  |  | -            ix[2] = 0;
 | 
	
		
			
				|  |  | -            H_sec = 0;
 | 
	
		
			
				|  |  | -            t = 1;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | +    real l = l_*l_*l_; real m = m_*m_*m_; real s = s_*s_*s_;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    rgb[0]=+4.0767416621f * l - 3.3077115913f * m + 0.2309699292f * s;
 | 
	
		
			
				|  |  | +    rgb[1]=-1.2684380046f * l + 2.6097574011f * m - 0.3413193965f * s;
 | 
	
		
			
				|  |  | +    rgb[2]=-0.0041960863f * l - 0.7034186147f * m + 1.7076147010f * s;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +real _compute_max_saturation(real a, real b){
 | 
	
		
			
				|  |  | +	real k0, k1, k2, k3, k4, wl, wm, ws;
 | 
	
		
			
				|  |  | +	if (-1.88170328f * a - 0.80936493f * b > 1){
 | 
	
		
			
				|  |  | +		k0 = +1.19086277f; k1 = +1.76576728f; k2 = +0.59662641f; k3 = +0.75515197f; k4 = +0.56771245f;
 | 
	
		
			
				|  |  | +		wl = +4.0767416621f; wm = -3.3077115913f; ws = +0.2309699292f;
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	else if (1.81444104f * a - 1.19445276f * b > 1){
 | 
	
		
			
				|  |  | +		k0 = +0.73956515f; k1 = -0.45954404f; k2 = +0.08285427f; k3 = +0.12541070f; k4 = +0.14503204f;
 | 
	
		
			
				|  |  | +		wl = -1.2684380046f; wm = +2.6097574011f; ws = -0.3413193965f;
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	else{
 | 
	
		
			
				|  |  | +		k0 = +1.35733652f; k1 = -0.00915799f; k2 = -1.15130210f; k3 = -0.50559606f; k4 = +0.00692167f;
 | 
	
		
			
				|  |  | +		wl = -0.0041960863f; wm = -0.7034186147f; ws = +1.7076147010f;
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	real S = k0 + k1 * a + k2 * b + k3 * a * a + k4 * a * b;
 | 
	
		
			
				|  |  | +	real k_l = +0.3963377774f * a + 0.2158037573f * b;
 | 
	
		
			
				|  |  | +	real k_m = -0.1055613458f * a - 0.0638541728f * b;
 | 
	
		
			
				|  |  | +	real k_s = -0.0894841775f * a - 1.2914855480f * b;
 | 
	
		
			
				|  |  | +	{
 | 
	
		
			
				|  |  | +		real l_ = 1.f + S * k_l;
 | 
	
		
			
				|  |  | +		real m_ = 1.f + S * k_m;
 | 
	
		
			
				|  |  | +		real s_ = 1.f + S * k_s;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		real l = l_ * l_ * l_;
 | 
	
		
			
				|  |  | +		real m = m_ * m_ * m_;
 | 
	
		
			
				|  |  | +		real s = s_ * s_ * s_;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		real l_dS = 3.f * k_l * l_ * l_;
 | 
	
		
			
				|  |  | +		real m_dS = 3.f * k_m * m_ * m_;
 | 
	
		
			
				|  |  | +		real s_dS = 3.f * k_s * s_ * s_;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		real l_dS2 = 6.f * k_l * k_l * l_;
 | 
	
		
			
				|  |  | +		real m_dS2 = 6.f * k_m * k_m * m_;
 | 
	
		
			
				|  |  | +		real s_dS2 = 6.f * k_s * k_s * s_;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		real f = wl * l + wm * m + ws * s;
 | 
	
		
			
				|  |  | +		real f1 = wl * l_dS + wm * m_dS + ws * s_dS;
 | 
	
		
			
				|  |  | +		real f2 = wl * l_dS2 + wm * m_dS2 + ws * s_dS2;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		S = S - f * f1 / (f1 * f1 - 0.5f * f * f2);
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return S;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +void _find_cusp(real a, real b, real *l, real *c)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	real S_cusp = _compute_max_saturation(a, b);
 | 
	
		
			
				|  |  | +    real oklab[3]={1, S_cusp * a, S_cusp * b}; real rgb_at_max[3];
 | 
	
		
			
				|  |  | +    tnsOKLAB2RGB(oklab,rgb_at_max);
 | 
	
		
			
				|  |  | +	real L_cusp = cbrt(1.f / TNS_MAX3(rgb_at_max[0], rgb_at_max[1], rgb_at_max[2])); 
 | 
	
		
			
				|  |  | +	real C_cusp = L_cusp * S_cusp;
 | 
	
		
			
				|  |  | +	*l=L_cusp; *c=C_cusp;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +real _find_gamut_intersection(real a, real b, real L1, real C1, real L0, real cusp_L, real cusp_C)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	real t;
 | 
	
		
			
				|  |  | +	if (((L1 - L0) * cusp_C - (cusp_L - L0) * C1) <= 0.f) {
 | 
	
		
			
				|  |  | +		t = cusp_C * L0 / (C1 * cusp_L + cusp_C * (L0 - L1));
 | 
	
		
			
				|  |  | +	}else{
 | 
	
		
			
				|  |  | +		t = cusp_C * (L0 - 1.f) / (C1 * (cusp_L - 1.f) + cusp_C * (L0 - L1));
 | 
	
		
			
				|  |  | +		{
 | 
	
		
			
				|  |  | +			real dL = L1 - L0; real dC = C1;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +			real k_l = +0.3963377774f * a + 0.2158037573f * b;
 | 
	
		
			
				|  |  | +			real k_m = -0.1055613458f * a - 0.0638541728f * b;
 | 
	
		
			
				|  |  | +			real k_s = -0.0894841775f * a - 1.2914855480f * b;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +			real l_dt = dL + dC * k_l;
 | 
	
		
			
				|  |  | +			real m_dt = dL + dC * k_m;
 | 
	
		
			
				|  |  | +			real s_dt = dL + dC * k_s;
 | 
	
		
			
				|  |  | +			{
 | 
	
		
			
				|  |  | +				real L = L0 * (1.f - t) + t * L1;
 | 
	
		
			
				|  |  | +				real C = t * C1;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +				real l_ = L + C * k_l;
 | 
	
		
			
				|  |  | +				real m_ = L + C * k_m;
 | 
	
		
			
				|  |  | +				real s_ = L + C * k_s;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +				real l = l_ * l_ * l_;
 | 
	
		
			
				|  |  | +				real m = m_ * m_ * m_;
 | 
	
		
			
				|  |  | +				real s = s_ * s_ * s_;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +				real ldt = 3 * l_dt * l_ * l_;
 | 
	
		
			
				|  |  | +				real mdt = 3 * m_dt * m_ * m_;
 | 
	
		
			
				|  |  | +				real sdt = 3 * s_dt * s_ * s_;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +				real ldt2 = 6 * l_dt * l_dt * l_;
 | 
	
		
			
				|  |  | +				real mdt2 = 6 * m_dt * m_dt * m_;
 | 
	
		
			
				|  |  | +				real sdt2 = 6 * s_dt * s_dt * s_;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +				real r = 4.0767416621f * l - 3.3077115913f * m + 0.2309699292f * s - 1;
 | 
	
		
			
				|  |  | +				real r1 = 4.0767416621f * ldt - 3.3077115913f * mdt + 0.2309699292f * sdt;
 | 
	
		
			
				|  |  | +				real r2 = 4.0767416621f * ldt2 - 3.3077115913f * mdt2 + 0.2309699292f * sdt2;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +				real u_r = r1 / (r1 * r1 - 0.5f * r * r2);
 | 
	
		
			
				|  |  | +				real t_r = -r * u_r;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +				real g = -1.2684380046f * l + 2.6097574011f * m - 0.3413193965f * s - 1;
 | 
	
		
			
				|  |  | +				real g1 = -1.2684380046f * ldt + 2.6097574011f * mdt - 0.3413193965f * sdt;
 | 
	
		
			
				|  |  | +				real g2 = -1.2684380046f * ldt2 + 2.6097574011f * mdt2 - 0.3413193965f * sdt2;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +				real u_g = g1 / (g1 * g1 - 0.5f * g * g2);
 | 
	
		
			
				|  |  | +				real t_g = -g * u_g;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +				real b = -0.0041960863f * l - 0.7034186147f * m + 1.7076147010f * s - 1;
 | 
	
		
			
				|  |  | +				real b1 = -0.0041960863f * ldt - 0.7034186147f * mdt + 1.7076147010f * sdt;
 | 
	
		
			
				|  |  | +				real b2 = -0.0041960863f * ldt2 - 0.7034186147f * mdt2 + 1.7076147010f * sdt2;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +				real u_b = b1 / (b1 * b1 - 0.5f * b * b2);
 | 
	
		
			
				|  |  | +				real t_b = -b * u_b;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +				t_r = u_r >= 0.f ? t_r : FLT_MAX;
 | 
	
		
			
				|  |  | +				t_g = u_g >= 0.f ? t_g : FLT_MAX;
 | 
	
		
			
				|  |  | +				t_b = u_b >= 0.f ? t_b : FLT_MAX;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +				t += fmin(t_r, fmin(t_g, t_b));
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return t;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +real _toe(real x) {
 | 
	
		
			
				|  |  | +	const real k_1 = 0.206f; const real k_2 = 0.03f; const real k_3 = (1.f + k_1) / (1.f + k_2);
 | 
	
		
			
				|  |  | +	return 0.5f * (k_3 * x - k_1 + sqrt((k_3 * x - k_1) * (k_3 * x - k_1) + 4 * k_2 * k_3 * x));
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +real _toe_inv(real x) {
 | 
	
		
			
				|  |  | +	const real k_1 = 0.206f; const real k_2 = 0.03f; const real k_3 = (1.f + k_1) / (1.f + k_2);
 | 
	
		
			
				|  |  | +	return (x * x + k_1 * x) / (k_3 * (x + k_2));
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +void _to_ST(real cusp_L, real cusp_C, real* _s, real* _t) {
 | 
	
		
			
				|  |  | +	real L = cusp_L; real C = cusp_C;
 | 
	
		
			
				|  |  | +	*_s=C / L; *_t=C / (1 - L);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +void _get_ST_mid(real a_, real b_, real *s,real *t){
 | 
	
		
			
				|  |  | +	*s = 0.11516993f + 1.f / (
 | 
	
		
			
				|  |  | +		+7.44778970f + 4.15901240f * b_
 | 
	
		
			
				|  |  | +		+ a_ * (-2.19557347f + 1.75198401f * b_
 | 
	
		
			
				|  |  | +			+ a_ * (-2.13704948f - 10.02301043f * b_
 | 
	
		
			
				|  |  | +				+ a_ * (-4.24894561f + 5.38770819f * b_ + 4.69891013f * a_
 | 
	
		
			
				|  |  | +					)))
 | 
	
		
			
				|  |  | +		);
 | 
	
		
			
				|  |  | +	*t = 0.11239642f + 1.f / (
 | 
	
		
			
				|  |  | +		+1.61320320f - 0.68124379f * b_
 | 
	
		
			
				|  |  | +		+ a_ * (+0.40370612f + 0.90148123f * b_
 | 
	
		
			
				|  |  | +			+ a_ * (-0.27087943f + 0.61223990f * b_
 | 
	
		
			
				|  |  | +				+ a_ * (+0.00299215f - 0.45399568f * b_ - 0.14661872f * a_
 | 
	
		
			
				|  |  | +					)))
 | 
	
		
			
				|  |  | +		);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +void _get_Cs(real L, real a_, real b_,real *rC_0, real *rC_mid, real *rC_max){
 | 
	
		
			
				|  |  | +	real cusp_L,cusp_C; _find_cusp(a_, b_,&cusp_L,&cusp_C);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	real C_max = _find_gamut_intersection(a_, b_, L, 1, L,cusp_L,cusp_C);
 | 
	
		
			
				|  |  | +	real _S,_T; _to_ST(cusp_L,cusp_C,&_S, &_T);
 | 
	
		
			
				|  |  | +	real k = C_max / fmin((L * _S), (1 - L) * _T);
 | 
	
		
			
				|  |  | +	real C_mid;{
 | 
	
		
			
				|  |  | +		real _s, _t; _get_ST_mid(a_, b_,&_s,&_t);
 | 
	
		
			
				|  |  | +		real C_a = L * _s; real C_b = (1.f - L) * _t;
 | 
	
		
			
				|  |  | +		C_mid = 0.9f * k * sqrt(sqrt(1.f / (1.f / (C_a * C_a * C_a * C_a) + 1.f / (C_b * C_b * C_b * C_b))));
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	real C_0;{
 | 
	
		
			
				|  |  | +		real C_a = L * 0.4f;
 | 
	
		
			
				|  |  | +		real C_b = (1.f - L) * 0.8f;
 | 
	
		
			
				|  |  | +		C_0 = sqrt(1.f / (1.f / (C_a * C_a) + 1.f / (C_b * C_b)));
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    luma = weights[0] * rgb[0] + weights[1] * rgb[1] + weights[2] * rgb[2];
 | 
	
		
			
				|  |  | -    chroma = rgb[ix[2]] - rgb[ix[0]];
 | 
	
		
			
				|  |  | +	*rC_0=C_0; *rC_mid=C_mid; *rC_max=C_max;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +void tnsHCY2RGB(real *hcy, real *rgb){
 | 
	
		
			
				|  |  | +	real h = hcy[0]; real s = hcy[1]; real l = hcy[2];
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (l >= 1.0f){ tnsVectorSet3(rgb,1,1,1); return; }
 | 
	
		
			
				|  |  | +	else if (l <= 0.0f){ tnsVectorSet3(rgb,0,0,0); return; }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    if (chroma >= DBL_EPSILON){
 | 
	
		
			
				|  |  | -        X = (rgb[ix[1]] - rgb[ix[0]]) / chroma;
 | 
	
		
			
				|  |  | +	real a_ = cos(2.f * TNS_PI * h);
 | 
	
		
			
				|  |  | +	real b_ = sin(2.f * TNS_PI * h);
 | 
	
		
			
				|  |  | +	real L = _toe_inv(l);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        Y_peak = weights[ix[2]] + X * weights[ix[1]];
 | 
	
		
			
				|  |  | -        if (luma != 0. && luma != 1.) chroma /= luma < Y_peak ? luma / Y_peak : (1. - luma) / (1. - Y_peak);
 | 
	
		
			
				|  |  | +	real C_0, C_mid, C_max;
 | 
	
		
			
				|  |  | +    _get_Cs(L, a_, b_,&C_0,&C_mid,&C_max);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        hue = (H_sec + t * X) / 6.;
 | 
	
		
			
				|  |  | -    }else
 | 
	
		
			
				|  |  | -        chroma = hue = 0.0;
 | 
	
		
			
				|  |  | +	real mid = 0.8f; real mid_inv = 1.25f;
 | 
	
		
			
				|  |  | +	real C, t, k_0, k_1, k_2;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    hcy[0] = hue;
 | 
	
		
			
				|  |  | -    hcy[1] = chroma;
 | 
	
		
			
				|  |  | -    hcy[2] = luma;
 | 
	
		
			
				|  |  | +	if (s < mid){
 | 
	
		
			
				|  |  | +		t = mid_inv * s;
 | 
	
		
			
				|  |  | +		k_1 = mid * C_0;
 | 
	
		
			
				|  |  | +		k_2 = (1.f - k_1 / C_mid);
 | 
	
		
			
				|  |  | +		C = t * k_1 / (1.f - k_2 * t);
 | 
	
		
			
				|  |  | +	}else{
 | 
	
		
			
				|  |  | +		t = (s - mid)/ (1 - mid);
 | 
	
		
			
				|  |  | +		k_0 = C_mid;
 | 
	
		
			
				|  |  | +		k_1 = (1.f - mid) * C_mid * C_mid * mid_inv * mid_inv / C_0;
 | 
	
		
			
				|  |  | +		k_2 = (1.f - (k_1) / (C_max - C_mid));
 | 
	
		
			
				|  |  | +		C = k_0 + t * k_1 / (1.f - k_2 * t);
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    real okl[3]={L, C * a_, C * b_};
 | 
	
		
			
				|  |  | +	tnsOKLAB2RGB(okl, rgb);
 | 
	
		
			
				|  |  | +    rgb[0]=_srgb_transfer_function(rgb[0]);
 | 
	
		
			
				|  |  | +    rgb[1]=_srgb_transfer_function(rgb[1]);
 | 
	
		
			
				|  |  | +    rgb[2]=_srgb_transfer_function(rgb[2]);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +void tnsRGB2HCY(real *rgb, real *hcy){
 | 
	
		
			
				|  |  | +	real lab[3]; real lrgb[3];
 | 
	
		
			
				|  |  | +    lrgb[0]=_srgb_transfer_function_inv(rgb[0]);
 | 
	
		
			
				|  |  | +    lrgb[1]=_srgb_transfer_function_inv(rgb[1]);
 | 
	
		
			
				|  |  | +    lrgb[2]=_srgb_transfer_function_inv(rgb[2]);
 | 
	
		
			
				|  |  | +    tnsRGB2OKLAB(lrgb,lab);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if(lab[0]>=1.0f-1e-4){ tnsVectorSet3(hcy,0,0,1); return; }
 | 
	
		
			
				|  |  | +    if(lab[0]<=1e-4){ tnsVectorSet3(hcy,0,0,0); return; }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	real C = sqrt(lab[1]*lab[1] + lab[2]*lab[2]);
 | 
	
		
			
				|  |  | +	real a_ = (!C)?0:(lab[1] / C);
 | 
	
		
			
				|  |  | +	real b_ = (!C)?0:(lab[2] / C);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	real L = lab[0];
 | 
	
		
			
				|  |  | +	real h = 0.5f + 0.5f * atan2(-lab[2], -lab[1]) / TNS_PI;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	real C_0, C_mid, C_max;
 | 
	
		
			
				|  |  | +    _get_Cs(L, a_, b_,&C_0,&C_mid,&C_max);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	real mid = 0.8f; real mid_inv = 1.25f;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	real s;
 | 
	
		
			
				|  |  | +	if (C < C_mid){
 | 
	
		
			
				|  |  | +		real k_1 = mid * C_0;
 | 
	
		
			
				|  |  | +		real k_2 = (1.f - k_1 / C_mid);
 | 
	
		
			
				|  |  | +		real t = C / (k_1 + k_2 * C);
 | 
	
		
			
				|  |  | +		s = t * mid;
 | 
	
		
			
				|  |  | +	}else{
 | 
	
		
			
				|  |  | +		real k_0 = C_mid;
 | 
	
		
			
				|  |  | +		real k_1 = (1.f - mid) * C_mid * C_mid * mid_inv * mid_inv / C_0;
 | 
	
		
			
				|  |  | +		real k_2 = (1.f - (k_1) / (C_max - C_mid));
 | 
	
		
			
				|  |  | +		real t = (C - k_0) / (k_1 + k_2 * (C - k_0));
 | 
	
		
			
				|  |  | +		s = mid + (1.f - mid) * t;
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	real l = _toe(L);
 | 
	
		
			
				|  |  | +	hcy[0]=h; hcy[1]=s; hcy[2]=l;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  void tnsClearAll(){
 | 
	
	
		
			
				|  | @@ -4070,7 +4205,7 @@ void tnsMakeQuad4d(real *arr, real x1, real y1, real z1, real w1, real x2, real
 | 
	
		
			
				|  |  |      arr[14] = z4;
 | 
	
		
			
				|  |  |      arr[15] = w4;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  | -void tnsMakeCircle2d(real *arr, int slices, real ctrX, real ctrY, real r){
 | 
	
		
			
				|  |  | +void tnsMakeCircle2d(real *arr, int slices, real ctrX, real ctrY, real r, int jump){
 | 
	
		
			
				|  |  |      int i;
 | 
	
		
			
				|  |  |      real radstep = 2 * TNS_PI / (real)slices;
 | 
	
		
			
				|  |  |      real rd = 0;
 | 
	
	
		
			
				|  | @@ -4078,8 +4213,9 @@ void tnsMakeCircle2d(real *arr, int slices, real ctrX, real ctrY, real r){
 | 
	
		
			
				|  |  |      for (i = 0; i < slices; i++){
 | 
	
		
			
				|  |  |          x = ctrX + cos(rd) * r;
 | 
	
		
			
				|  |  |          y = ctrY + sin(rd) * r;
 | 
	
		
			
				|  |  | -        arr[2 * i] = x;
 | 
	
		
			
				|  |  | -        arr[2 * i + 1] = y;
 | 
	
		
			
				|  |  | +        int idx=2 * i * (1+jump);
 | 
	
		
			
				|  |  | +        arr[idx] = x;
 | 
	
		
			
				|  |  | +        arr[idx+1] = y;
 | 
	
		
			
				|  |  |          rd += radstep;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 | 
	
	
		
			
				|  | @@ -4113,8 +4249,8 @@ void tnsMakeBridgedIndex(unsigned int *result, int num, int revert, int begin){
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  void tnsMakeRing2d(real *arr, int *index, int slices, real ctrX, real ctrY, real r1, real r2){
 | 
	
		
			
				|  |  | -    tnsMakeCircle2d(arr, slices, ctrX, ctrY, r1);
 | 
	
		
			
				|  |  | -    tnsMakeCircle2d(&arr[slices*2], slices, ctrX, ctrY, r2);
 | 
	
		
			
				|  |  | +    tnsMakeCircle2d(arr, slices, ctrX, ctrY, r1,0);
 | 
	
		
			
				|  |  | +    tnsMakeCircle2d(&arr[slices*2], slices, ctrX, ctrY, r2,0);
 | 
	
		
			
				|  |  |      tnsMakeBridgedIndex(index, slices, 0, 0);
 | 
	
		
			
				|  |  |      index[slices*2]=0; index[slices*2+1]=slices;
 | 
	
		
			
				|  |  |  }
 |