Example #1
0
/////////////////////////////////////////////////////////
// render
//
/////////////////////////////////////////////////////////
void vertex_combine :: render(GemState *state)
{
  int size,srcL,srcS,count,sizeR,ratio,remainder;
  GLfloat *VertexArray;
  float blendL, blendR, ratiof;

  VertexArray =state->VertexArray;
  if (state->VertexArray == NULL || state->VertexArraySize <= 0) {
    post("no vertex array!");
    return;
  }

  if (state->ColorArray == NULL ) {
    post("no color array!");
    return;
  }

  size = state->VertexArraySize;
  sizeR = m_vertCountR;

  //dumb and dirty x-fade
  blendR = m_blend;
  blendL = fabs(1.f - m_blend);

  if (size > sizeR) {
    //left is larger
    ratiof = static_cast<float>(size)/sizeR;
    ratio = size / sizeR;
    remainder = size % sizeR;
    // post("float ratio %f:1 int ratio %d:1 remainder %d",ratiof,ratio,remainder);
    int i = 0;
    srcL = 0;
    srcS = 0;
    while (i < sizeR) {
      count = 0;
      while (count < ratio) {
        VertexArray[srcL] = (VertexArray[srcL] * blendL) +
                            (m_rightVertexArray[srcS] * blendR);
        VertexArray[srcL+1] = (VertexArray[srcL+1] * blendL) +
                              (m_rightVertexArray[srcS+1] * blendR);
        VertexArray[srcL+2] = (VertexArray[srcL+2] * blendL) +
                              (m_rightVertexArray[srcS+2] * blendR);
        VertexArray[srcL+3] = (VertexArray[srcL+3] * blendL )+
                              (m_rightVertexArray[srcS+3] * blendR);
        srcL+=4;
        count++;
      }
      i++;
      srcS+=4;
    }
    state->VertexArraySize = size;
  } else {
    ratiof = static_cast<float>(sizeR)/size;
    ratio = sizeR / size;
    remainder = sizeR % size;
    post("float ratio %f:1 int ratio %d:1 remainder %d",ratiof,ratio,
         remainder);
  }

  /* -- this almost works - good for fast and dirty integer ratios
  if (size > sizeR){
      //left is larger
      ratiof = static_cast<float>(size)/sizeR;
      ratio = size / sizeR;
      remainder = size % sizeR;
     // post("float ratio %f:1 int ratio %d:1 remainder %d",ratiof,ratio,remainder);
      i = 0;
      srcL = 0;
      srcS = 0;
      while (i < sizeR) {
          count = 0;
          while (count < ratio){
              VertexArray[srcL] = (VertexArray[srcL] * blendL) + (m_rightVertexArray[srcS] * blendR);
              VertexArray[srcL+1] = (VertexArray[srcL+1] * blendL) + (m_rightVertexArray[srcS+1] * blendR);
              VertexArray[srcL+2] = (VertexArray[srcL+2] * blendL) + (m_rightVertexArray[srcS+2] * blendR);
              VertexArray[srcL+3] = (VertexArray[srcL+3] * blendL )+ (m_rightVertexArray[srcS+3] * blendR);
              srcL+=4;
              count++;
          }
          i++;
          srcS+=4;
      }
      state->VertexArraySize = size;
  }else{
      ratiof = static_cast<float>(sizeR)/size;
      ratio = sizeR / size;
      remainder = sizeR % size;
      post("float ratio %f:1 int ratio %d:1 remainder %d",ratiof,ratio,remainder);
  }
  */

}
Example #2
0
static void *netreceive_new(t_symbol *compatflag,
    t_floatarg fportno, t_floatarg udpflag)
{
    t_netreceive *x;
    struct sockaddr_in server;
    int sockfd, portno = fportno, udp = (udpflag != 0);
    int old = !strcmp(compatflag->s_name , "old");
    int intarg;
        /* create a socket */
    sockfd = socket(AF_INET, (udp ? SOCK_DGRAM : SOCK_STREAM), 0);
#if 0
    fprintf(stderr, "receive socket %d\n", sockfd);
#endif
    if (sockfd < 0)
    {
        sys_sockerror("socket");
        return (0);
    }
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = INADDR_ANY;

#if 1
        /* ask OS to allow another Pd to repoen this port after we close it. */
    intarg = 1;
    if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
        (char *)&intarg, sizeof(intarg)) < 0)
            post("setsockopt (SO_REUSEADDR) failed\n");
#endif
#if 0
    intarg = 0;
    if (setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF,
        &intarg, sizeof(intarg)) < 0)
            post("setsockopt (SO_RCVBUF) failed\n");
#endif
    intarg = 1;
    if(setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, 
                  (const void *)&intarg, sizeof(intarg)) < 0)
        post("setting SO_BROADCAST");
        /* Stream (TCP) sockets are set NODELAY */
    if (!udp)
    {
        intarg = 1;
        if (setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY,
            (char *)&intarg, sizeof(intarg)) < 0)
                post("setsockopt (TCP_NODELAY) failed\n");
    }
        /* assign server port number */
    server.sin_port = htons((u_short)portno);

        /* name the socket */
    if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0)
    {
        sys_sockerror("bind");
        sys_closesocket(sockfd);
        return (0);
    }
    x = (t_netreceive *)pd_new(netreceive_class);
    if (old)
    {
        /* old style, nonsecure version */
        x->x_msgout = 0;
    }
    else x->x_msgout = outlet_new(&x->x_obj, &s_anything);

    if (udp)        /* datagram protocol */
    {
        t_socketreceiver *y = socketreceiver_new((void *)x, 
            (t_socketnotifier)netreceive_notify,
                (x->x_msgout ? netreceive_doit : 0), 1);
        sys_addpollfn(sockfd, (t_fdpollfn)socketreceiver_read, y);
        x->x_connectout = 0;
    }
    else        /* streaming protocol */
    {
        if (listen(sockfd, 5) < 0)
        {
            sys_sockerror("listen");
            sys_closesocket(sockfd);
            sockfd = -1;
        }
        else
        {
            sys_addpollfn(sockfd, (t_fdpollfn)netreceive_connectpoll, x);
            x->x_connectout = outlet_new(&x->x_obj, &s_float);
        }
    }
    x->x_connectsocket = sockfd;
    x->x_nconnections = 0;
    x->x_udp = udp;

    return (x);
}
Example #3
0
static void netsend_connect(t_netsend *x, t_symbol *hostname,
    t_floatarg fportno)
{
    struct sockaddr_in server;
    struct hostent *hp;
    int sockfd;
    int portno = fportno;
    int intarg;
    if (x->x_fd >= 0)
    {
        error("netsend_connect: already connected");
        return;
    }

        /* create a socket */
    sockfd = socket(AF_INET, x->x_protocol, 0);
#if 0
    fprintf(stderr, "send socket %d\n", sockfd);
#endif
    if (sockfd < 0)
    {
        sys_sockerror("socket");
        return;
    }
    /* connect socket using hostname provided in command line */
    server.sin_family = AF_INET;
    hp = gethostbyname(hostname->s_name);
    if (hp == 0)
    {
        post("bad host?\n");
        return;
    }
#if 0
    intarg = 0;
    if (setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF,
        &intarg, sizeof(intarg)) < 0)
            post("setsockopt (SO_RCVBUF) failed\n");
#endif
    intarg = 1;
    if(setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, 
                  (const void *)&intarg, sizeof(intarg)) < 0)
        post("setting SO_BROADCAST");
        /* for stream (TCP) sockets, specify "nodelay" */
    if (x->x_protocol == SOCK_STREAM)
    {
        intarg = 1;
        if (setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY,
            (char *)&intarg, sizeof(intarg)) < 0)
                post("setsockopt (TCP_NODELAY) failed\n");
    }
    memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length);

    /* assign client port number */
    server.sin_port = htons((u_short)portno);

    post("connecting to port %d", portno);
        /* try to connect.  LATER make a separate thread to do this
        because it might block */
    if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) < 0)
    {
        sys_sockerror("connecting stream socket");
        sys_closesocket(sockfd);
        return;
    }
    x->x_fd = sockfd;
    outlet_float(x->x_obj.ob_outlet, 1);
}
Example #4
0
static void routeOSC_verbosity(t_routeOSC *x, t_floatarg v)
{
    x->x_verbosity = (v == 0)? 0: 1;
    if (x->x_verbosity) post("routeOSC_verbosity(%p) is %d", x, x->x_verbosity);
}
Example #5
0
static void routeOSC_doanything(t_routeOSC *x, t_symbol *s, int argc, t_atom *argv)
{
    char    *pattern, *nextSlash;
    int     i = 0, pattern_depth = 0, matchedAnything = 0;
    int     noPath = 0; // nonzero if we are dealing with a simple list (as from a previous [routeOSC])

    pattern = s->s_name;
    if (x->x_verbosity) post("routeOSC_doanything(%p): pattern is %s", x, pattern);
    if (pattern[0] != '/')
    {
        /* output unmatched data on rightmost outlet */
        if (x->x_verbosity) post("routeOSC_doanything no OSC path(%p) , %d args", x, argc);
        outlet_anything(x->x_outlets[x->x_num], s, argc, argv);
        return;
    }
    pattern_depth = routeOSC_count_slashes(pattern);
    if (x->x_verbosity) post("routeOSC_doanything(%p): pattern_depth is %i", x, pattern_depth);
    nextSlash = NextSlashOrNull(pattern+1);
    if (*nextSlash == '\0')
    { /* pattern_depth == 1 */
        /* last level of the address, so we'll output the argument list */
    
        for (i = 0; i < x->x_num; ++i)
        {
            if
            (
                (x->x_prefix_depth[i] <= pattern_depth)
                && (MyPatternMatch(pattern+1, x->x_prefixes[i]+1))
            )
            {
                ++matchedAnything;
                if (noPath)
                { // just a list starting with a symbol
                  // The special symbol is s
                  if (x->x_verbosity) post("routeOSC_doanything _1_(%p): (%d) noPath: s is \"%s\"", x, i, s->s_name);
                  outlet_anything(x->x_outlets[i], s, argc, argv);
                }
                else // normal OSC path
                {
                    // I hate stupid Max lists with a special first element
                    if (argc == 0)
                    {
                        if (x->x_verbosity) post("routeOSC_doanything _2_(%p): (%d) no args", x, i);
                        outlet_bang(x->x_outlets[i]);
                    }
                    else if (argv[0].a_type == A_SYMBOL)
                    {
                        // Promote the symbol that was argv[0] to the special symbol
                        if (x->x_verbosity) post("routeOSC_doanything _3_(%p): (%d) symbol: is \"%s\"", x, i, argv[0].a_w.w_symbol->s_name);
                        outlet_anything(x->x_outlets[i], argv[0].a_w.w_symbol, argc-1, argv+1);
                    }
                    else if (argc > 1)
                    {
                        // Multiple arguments starting with a number, so naturally we have
                        // to use a special function to output this "list", since it's what
                        // Max originally meant by "list".
                        if (x->x_verbosity) post("routeOSC_doanything _4_(%p): (%d) list:", x, i);
                        outlet_list(x->x_outlets[i], 0L, argc, argv);
                    }
                    else
                    {
                        // There was only one argument, and it was a number, so we output it
                        // not as a list
                        if (argv[0].a_type == A_FLOAT)
                        {
                            if (x->x_verbosity) post("routeOSC_doanything _5_(%p): (%d) a single float", x, i);
                            outlet_float(x->x_outlets[i], argv[0].a_w.w_float);
                        }
                        else
                        {
                            pd_error(x, "* routeOSC: unrecognized atom type!");
                        }
                    }
                }
            }
        }
    }
    else
    {
        /* There's more address after this part, so our output list will begin with
           the next slash.  */
        t_symbol *restOfPattern = 0; /* avoid the gensym unless we have to output */
        char patternBegin[1000];

        /* Get the incoming pattern to match against all our prefixes */

        for (i = 0; i < x->x_num; ++i)
        {
            restOfPattern = 0;
            if (x->x_prefix_depth[i] <= pattern_depth)
            {
                StrCopyUntilNthSlash(patternBegin, pattern+1, x->x_prefix_depth[i]);
                if (x->x_verbosity)
                    post("routeOSC_doanything _6_(%p): (%d) patternBegin is %s", x, i, patternBegin);
                if (MyPatternMatch(patternBegin, x->x_prefixes[i]+1))
                {
                    if (x->x_verbosity)
                        post("routeOSC_doanything _7_(%p): (%d) matched %s depth %d", x, i, x->x_prefixes[i], x->x_prefix_depth[i]);
                    ++matchedAnything;
                    nextSlash = NthSlashOrNull(pattern+1, x->x_prefix_depth[i]);
                    if (x->x_verbosity)
                        post("routeOSC_doanything _8_(%p): (%d) nextSlash %s [%d]", x, i, nextSlash, nextSlash[0]);
                    if (*nextSlash != '\0')
                    {
                        if (x->x_verbosity) post("routeOSC_doanything _9_(%p): (%d) more pattern", x, i);
                        restOfPattern = gensym(nextSlash);
                        outlet_anything(x->x_outlets[i], restOfPattern, argc, argv);
                    }
                    else if (argc == 0)
                    {
                        if (x->x_verbosity) post("routeOSC_doanything _10_(%p): (%d) no more pattern, no args", x, i);
                        outlet_bang(x->x_outlets[i]);
                    }
                    else
                    {
                        if (x->x_verbosity) post("routeOSC_doanything _11_(%p): (%d) no more pattern, %d args", x, i, argc);
                        if (argv[0].a_type == A_SYMBOL) // Promote the symbol that was argv[0] to the special symbol
                            outlet_anything(x->x_outlets[i], argv[0].a_w.w_symbol, argc-1, argv+1);
                        else
                            outlet_anything(x->x_outlets[i], gensym("list"), argc, argv);
                    }
                }
            }
        }
    }
    if (!matchedAnything)
    {
        // output unmatched data on rightmost outlet a la normal 'route' object, jdl 20020908
        if (x->x_verbosity) post("routeOSC_doanything _13_(%p) unmatched %d, %d args", x, i, argc);
        outlet_anything(x->x_outlets[x->x_num], s, argc, argv);
    }
}
Example #6
0
static void *NLMSerr_in_tilde_new(t_symbol *s, t_int argc, t_atom *argv)
{
    t_NLMSerr_in_tilde *x = (t_NLMSerr_in_tilde *)pd_new(NLMSerr_in_tilde_class);
    t_int i, n_order=39;
    t_symbol    *w_name;
    t_float beta=0.01f;
    t_float gammax=0.00001f;
    
    if((argc >= 4) &&
        IS_A_FLOAT(argv,0) &&   //IS_A_FLOAT/SYMBOL from iemlib.h
        IS_A_FLOAT(argv,1) &&
        IS_A_FLOAT(argv,2) &&
        IS_A_SYMBOL(argv,3))
    {
        n_order = (t_int)atom_getintarg(0, argc, argv);
        beta    = (t_float)atom_getfloatarg(1, argc, argv);
        gammax  = (t_float)atom_getfloatarg(2, argc, argv);
        w_name  = (t_symbol *)atom_getsymbolarg(3, argc, argv);
        
        if(beta < 0.0f)
            beta = 0.0f;
        if(beta > 2.0f)
            beta = 2.0f;
        
        if(gammax < 0.0f)
            gammax = 0.0f;
        if(gammax > 1.0f)
            gammax = 1.0f;
        
        if(n_order < 2)
            n_order = 2;
        if(n_order > 1111111)
            n_order = 1111111;
        
        inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
        inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
        outlet_new(&x->x_obj, &s_signal);
        
        x->x_flt_sig_in1 = 0;
        x->x_n_order = n_order;
        x->x_update = 0;
        x->x_beta = beta;
        x->x_gamma = gammax;
        // 2 times in and one time err_in memory allocation (history)
        x->x_ref_filt_in_hist = (t_float *)getbytes(x->x_n_order*sizeof(t_float));
        x->x_ref_adapt_in_hist = (t_float *)getbytes(x->x_n_order*sizeof(t_float));
        
        // table-symbols will be linked to their memory in future (dsp_routine)
        x->x_w_array_sym_name = gensym(w_name->s_name);
        x->x_w_array_mem_beg = (t_float *)0;
        
        x->x_rw_index = 0;
        
        return(x);
    }
    else
    {
        post("NLMSerr_in~-ERROR: need 3 float- + 1 symbol-arguments:");
        post("  order_of_filter + learnrate_beta + security_value + array_name_taps");
        return(0);
    }
}
Example #7
0
static void routeOSC_paths(t_routeOSC *x, t_symbol *s, int argc, t_atom *argv)
{ /* print  out the paths we are matching */
    int i;
    
    for (i = 0; i < x->x_num; ++i) post("path[%d]: %s (depth %d)", i, x->x_prefixes[i], x->x_prefix_depth[i]);
}
Example #8
0
void kbuffer_info(t_kbuffer *x) {
	post("function length is %d samples",x->length);
	post("function sampling rate is %.2f",x->ksrate);
	post("function byte size is %d",x->memsize);
	post("function duration is %.2f seconds",x->duration);
}
Example #9
0
unsigned int KeenClient::addEvents(const char *events)
{
	buildResource();
	setAuthorizationHeader(write_key);
	return post(resource, events);
}
Example #10
0
static void ctw_cancel_request(void *args) {
	struct _ctw *common = args; 
	curl_multi_remove_handle(common->multi_handle, common->easy_handle);
	common->locked = 0;
	post("request cancelled.");
}
Example #11
0
static t_symbol *iem_image_calc_size(t_iem_image *x)
{
    char dirbuf[MAXPDSTRING], *namebufptr;
    char namebuf[MAXPDSTRING];
    unsigned char buf[222];
    unsigned int i;
    char *c;
    int fd;
    FILE *fh;
    size_t items;

    if(!x->x_gifsym || !x->x_gifsym->s_name)
    {
        post("iem_image-ERROR: no gifname");
        x->x_gifsym = (t_symbol *)0;
        return((t_symbol *)0);
    }
    fd = open_via_path(canvas_getdir(glist_getcanvas(x->x_gui.x_glist))->s_name, x->x_gifsym->s_name,
                       "", dirbuf, &namebufptr, MAXPDSTRING, 1);
    if (fd < 0)
    {
        post("iem_image-ERROR: cannot open %s first time", x->x_gifsym->s_name);
        x->x_gifsym = (t_symbol *)0;
        return((t_symbol *)0);
    }
    else
    {
        if(fd >= 0)
            close(fd);
        strcpy(namebuf, dirbuf);
        strcat(namebuf, "/");
        strcat(namebuf, namebufptr);
        fh = fopen(namebuf, "r");
        if(fh == NULL)
        {
            post("iem_image-ERROR: cannot open %s second time", namebuf);
            x->x_gifsym = (t_symbol *)0;
            return((t_symbol *)0);
        }
        else
        {
            items=fread(buf, 22, sizeof(unsigned char), fh);
            if((items < 1)||(strlen((char*)buf)<7)) {
                post("iem_image-ERROR: can not read header in %s, only %d items read: %s.", namebuf, strlen((char*)buf), (char*) buf);
                x->x_gifsym = (t_symbol *)0;
                return((t_symbol *)0);
            };
            fclose(fh);
            c = (char *)buf;
            if((c[0] != 'G')||(c[1] != 'I')||(c[2] != 'F'))
            {
                post("iem_image-ERROR: %s is not a GIF-file", namebuf);
                x->x_gifsym = (t_symbol *)0;
                return((t_symbol *)0);
            }
            i = 256*(unsigned int)buf[7];
            i += (unsigned int)buf[6];
            x->x_gui.x_w = (int)i;
            i = 256*(unsigned int)buf[9];
            i += (unsigned int)buf[8];
            x->x_gui.x_h = (int)i;
            SETFLOAT(x->x_at_out, (t_float)x->x_gui.x_w);
            SETFLOAT(x->x_at_out+1, (t_float)x->x_gui.x_h);
            outlet_list(x->x_gui.x_obj.ob_outlet, &s_list, 2, x->x_at_out);
            if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing)
                pd_list(x->x_gui.x_snd->s_thing, &s_list, 2, x->x_at_out);
            return(gensym(namebuf));
        }
    }
}
Example #12
0
int main(int argc, char **argv, char **envp) {
	if (argc != 2) {
		print_usage(argc, argv);
		return 0;
	}

	//flags
	int server_flag = 0;
	int start_flag = 0;
	int stop_flag = 0;
	int quit_flag = 0;
	int bot_flag = 0;
	int debug_flag = 0;
	int help_flag = 0;

	//process options
	struct option long_options[] = {
		/* Flag options. */
		{"server",		no_argument,		&server_flag,	1},
		{"start",		no_argument,		&start_flag,	1},
		{"stop",		no_argument,		&stop_flag,		1},
		{"bot",			no_argument,		&bot_flag,		1},
		{"quit",		no_argument,		&quit_flag,		1},
		{"debug",		no_argument,		&debug_flag,	1},
		{"help",		no_argument,		&help_flag,		1},
		/* End of options. */
		{0, 0, 0, 0}
	};
	int opt;
	int option_index = 0;
	while ((opt = getopt_long(argc, argv, "01bsqdh", long_options, &option_index)) != -1) {
		switch (opt) {

		case 's':
			server_flag = 1;
			break;
		case '1':
			start_flag = 1;
			break;

		case '0':
			stop_flag = 1;
			break;

		case 'b':
			bot_flag = 1;
			break;

		case 'q':
			quit_flag = 1;
			break;

		case 'd':
			debug_flag = 1;
			break;

		case 'h':
			help_flag = 1;
			break;

/*
		default:
			print_usage(argc, argv);
			exit(EXIT_FAILURE);
*/
		}
	}

	if (help_flag) {
		print_usage(argc, argv);
		return 1;
	}

	if (start_flag) {
		return post(startNotification);
	}
	if (stop_flag) {
		return post(stopNotification);
	}
	if (quit_flag) {
		return post(quitNotification);
	}
	if (debug_flag) {
		return post(debugNotification);
	}

	if (server_flag) {
		return runDaemonRun();
	}
	if (bot_flag) {
		return runBotRun();
	}

	return 0;
}
Example #13
0
int sys_rcfile(void)
{
    FILE* file;
    int i;
    int k;
    int rcargc;
    char* rcargv[NUMARGS];
    char* buffer;
    char  fname[FILENAME_MAX], buf[1000], *home = getenv("HOME");
    int retval = 1; /* that's what we will return at the end; for now, let's think it'll be an error */
 
    /* initialize rc-arg-array so we can safely clean up at the end */
    for (i = 1; i < NUMARGS-1; i++)
      rcargv[i]=0;


    /* parse a startup file */
    
    *fname = '\0'; 

    strncat(fname, home? home : ".", FILENAME_MAX-10);
    strcat(fname, "/");

    strcat(fname, STARTUPNAME);

    if (!(file = fopen(fname, "r")))
        return 1;

    post("reading startup file: %s", fname);

    rcargv[0] = ".";    /* this no longer matters to sys_argparse() */

    for (i = 1; i < NUMARGS-1; i++)
    {
        if (fscanf(file, "%998s", buf) < 0)
            break;
        buf[999] = 0;
        if (!(rcargv[i] = malloc(strlen(buf) + 1)))
            goto cleanup;
        strcpy(rcargv[i], buf);
    }
    if (i >= NUMARGS-1)
        fprintf(stderr, "startup file too long; extra args dropped\n");
    rcargv[i] = 0;

    rcargc = i;

    /* parse the options */

    fclose(file);
    if (sys_verbose)
    {
        if (rcargc)
        {
            post("startup args from RC file:");
            for (i = 1; i < rcargc; i++)
                post("%s", rcargv[i]);
        }
        else post("no RC file arguments found");
    }
    if (sys_argparse(rcargc-1, rcargv+1))
    {
        post("error parsing RC arguments");
        goto cleanup;
    }

    retval=0; /* we made it without an error */


 cleanup: /* prevent memleak */
    for (i = 1; i < NUMARGS-1; i++)
      if(rcargv[i])free(rcargv[i]);
    
    return(retval);
}
static void featureMean_print(t_featureMean *x)
{
    post("averaging %i vectors with %i features", x->numFrames, x->featureLength);
}
Example #15
0
void mapblock_mesh_generate_special(MeshMakeData *data,
		MeshCollector &collector)
{
	INodeDefManager *nodedef = data->m_gamedef->ndef();

	// 0ms
	//TimeTaker timer("mapblock_mesh_generate_special()");

	/*
		Some settings
	*/
	bool new_style_water = g_settings->getBool("new_style_water");
	
	float node_liquid_level = 1.0;
	if(new_style_water)
		node_liquid_level = 0.85;
	
	v3s16 blockpos_nodes = data->m_blockpos*MAP_BLOCKSIZE;

	for(s16 z=0; z<MAP_BLOCKSIZE; z++)
	for(s16 y=0; y<MAP_BLOCKSIZE; y++)
	for(s16 x=0; x<MAP_BLOCKSIZE; x++)
	{
		v3s16 p(x,y,z);

		MapNode n = data->m_vmanip.getNodeNoEx(blockpos_nodes+p);
		const ContentFeatures &f = nodedef->get(n);

		// Only solidness=0 stuff is drawn here
		if(f.solidness != 0)
			continue;
		
		switch(f.drawtype){
		default:
			infostream<<"Got "<<f.drawtype<<std::endl;
			assert(0);
			break;
		case NDT_AIRLIKE:
			break;
		case NDT_LIQUID:
		{
			/*
				Add water sources to mesh if using new style
			*/
			TileSpec tile_liquid = f.special_tiles[0];
			TileSpec tile_liquid_bfculled = getNodeTile(n, p, v3s16(0,0,0), data);

			bool top_is_same_liquid = false;
			MapNode ntop = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x,y+1,z));
			content_t c_flowing = nodedef->getId(f.liquid_alternative_flowing);
			content_t c_source = nodedef->getId(f.liquid_alternative_source);
			if(ntop.getContent() == c_flowing || ntop.getContent() == c_source)
				top_is_same_liquid = true;

			u16 l = getInteriorLight(n, 0, data);
			video::SColor c = MapBlock_LightColor(f.alpha, l, decode_light(f.light_source));

			/*
				Generate sides
			 */
			v3s16 side_dirs[4] = {
				v3s16(1,0,0),
				v3s16(-1,0,0),
				v3s16(0,0,1),
				v3s16(0,0,-1),
			};
			for(u32 i=0; i<4; i++)
			{
				v3s16 dir = side_dirs[i];

				MapNode neighbor = data->m_vmanip.getNodeNoEx(blockpos_nodes + p + dir);
				content_t neighbor_content = neighbor.getContent();
				const ContentFeatures &n_feat = nodedef->get(neighbor_content);
				MapNode n_top = data->m_vmanip.getNodeNoEx(blockpos_nodes + p + dir+ v3s16(0,1,0));
				content_t n_top_c = n_top.getContent();

				if(neighbor_content == CONTENT_IGNORE)
					continue;

				/*
					If our topside is liquid and neighbor's topside
					is liquid, don't draw side face
				*/
				if(top_is_same_liquid && (n_top_c == c_flowing ||
						n_top_c == c_source || n_top_c == CONTENT_IGNORE))
					continue;

				// Don't draw face if neighbor is blocking the view
				if(n_feat.solidness == 2)
					continue;

				bool neighbor_is_same_liquid = (neighbor_content == c_source
						|| neighbor_content == c_flowing);

				// Don't draw any faces if neighbor same is liquid and top is
				// same liquid
				if(neighbor_is_same_liquid && !top_is_same_liquid)
					continue;

				// Use backface culled material if neighbor doesn't have a
				// solidness of 0
				const TileSpec *current_tile = &tile_liquid;
				if(n_feat.solidness != 0 || n_feat.visual_solidness != 0)
					current_tile = &tile_liquid_bfculled;

				video::S3DVertex vertices[4] =
				{
					video::S3DVertex(-BS/2,0,BS/2,0,0,0, c, 0,1),
					video::S3DVertex(BS/2,0,BS/2,0,0,0, c, 1,1),
					video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, 1,0),
					video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,0),
				};

				/*
					If our topside is liquid, set upper border of face
					at upper border of node
				*/
				if(top_is_same_liquid)
				{
					vertices[2].Pos.Y = 0.5*BS;
					vertices[3].Pos.Y = 0.5*BS;
				}
				/*
					Otherwise upper position of face is liquid level
				*/
				else
				{
					vertices[2].Pos.Y = (node_liquid_level-0.5)*BS;
					vertices[3].Pos.Y = (node_liquid_level-0.5)*BS;
				}
				/*
					If neighbor is liquid, lower border of face is liquid level
				*/
				if(neighbor_is_same_liquid)
				{
					vertices[0].Pos.Y = (node_liquid_level-0.5)*BS;
					vertices[1].Pos.Y = (node_liquid_level-0.5)*BS;
				}
				/*
					If neighbor is not liquid, lower border of face is
					lower border of node
				*/
				else
				{
					vertices[0].Pos.Y = -0.5*BS;
					vertices[1].Pos.Y = -0.5*BS;
				}

				for(s32 j=0; j<4; j++)
				{
					if(dir == v3s16(0,0,1))
						vertices[j].Pos.rotateXZBy(0);
					if(dir == v3s16(0,0,-1))
						vertices[j].Pos.rotateXZBy(180);
					if(dir == v3s16(-1,0,0))
						vertices[j].Pos.rotateXZBy(90);
					if(dir == v3s16(1,0,-0))
						vertices[j].Pos.rotateXZBy(-90);

					// Do this to not cause glitches when two liquids are
					// side-by-side
					/*if(neighbor_is_same_liquid == false){
						vertices[j].Pos.X *= 0.98;
						vertices[j].Pos.Z *= 0.98;
					}*/

					vertices[j].Pos += intToFloat(p, BS);
				}

				u16 indices[] = {0,1,2,2,3,0};
				// Add to mesh collector
				collector.append(*current_tile, vertices, 4, indices, 6);
			}

			/*
				Generate top
			 */
			if(top_is_same_liquid)
				continue;
			
			video::S3DVertex vertices[4] =
			{
				video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,1),
				video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, 1,1),
				video::S3DVertex(BS/2,0,-BS/2, 0,0,0, c, 1,0),
				video::S3DVertex(-BS/2,0,-BS/2, 0,0,0, c, 0,0),
			};

			v3f offset(p.X*BS, p.Y*BS + (-0.5+node_liquid_level)*BS, p.Z*BS);
			for(s32 i=0; i<4; i++)
			{
				vertices[i].Pos += offset;
			}

			u16 indices[] = {0,1,2,2,3,0};
			// Add to mesh collector
			collector.append(tile_liquid, vertices, 4, indices, 6);
		break;}
		case NDT_FLOWINGLIQUID:
		{
			/*
				Add flowing liquid to mesh
			*/
			TileSpec tile_liquid = f.special_tiles[0];
			TileSpec tile_liquid_bfculled = f.special_tiles[1];

			bool top_is_same_liquid = false;
			MapNode ntop = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x,y+1,z));
			content_t c_flowing = nodedef->getId(f.liquid_alternative_flowing);
			content_t c_source = nodedef->getId(f.liquid_alternative_source);
			if(ntop.getContent() == c_flowing || ntop.getContent() == c_source)
				top_is_same_liquid = true;
			
			u16 l = 0;
			// If this liquid emits light and doesn't contain light, draw
			// it at what it emits, for an increased effect
			u8 light_source = nodedef->get(n).light_source;
			if(light_source != 0){
				//l = decode_light(undiminish_light(light_source));
				l = decode_light(light_source);
				l = l | (l<<8);
			}
			// Use the light of the node on top if possible
			else if(nodedef->get(ntop).param_type == CPT_LIGHT)
				l = getInteriorLight(ntop, 0, data);
			// Otherwise use the light of this node (the liquid)
			else
				l = getInteriorLight(n, 0, data);
			video::SColor c = MapBlock_LightColor(f.alpha, l, decode_light(f.light_source));
			
			u8 range = rangelim(nodedef->get(c_flowing).liquid_range, 0, 8);

			// Neighbor liquid levels (key = relative position)
			// Includes current node
			std::map<v3s16, f32> neighbor_levels;
			std::map<v3s16, content_t> neighbor_contents;
			std::map<v3s16, u8> neighbor_flags;
			const u8 neighborflag_top_is_same_liquid = 0x01;
			v3s16 neighbor_dirs[9] = {
				v3s16(0,0,0),
				v3s16(0,0,1),
				v3s16(0,0,-1),
				v3s16(1,0,0),
				v3s16(-1,0,0),
				v3s16(1,0,1),
				v3s16(-1,0,-1),
				v3s16(1,0,-1),
				v3s16(-1,0,1),
			};
			for(u32 i=0; i<9; i++)
			{
				content_t content = CONTENT_AIR;
				float level = -0.5 * BS;
				u8 flags = 0;
				// Check neighbor
				v3s16 p2 = p + neighbor_dirs[i];
				MapNode n2 = data->m_vmanip.getNodeNoEx(blockpos_nodes + p2);
				if(n2.getContent() != CONTENT_IGNORE)
				{
					content = n2.getContent();

					if(n2.getContent() == c_source)
						level = (-0.5+node_liquid_level) * BS;
					else if(n2.getContent() == c_flowing){
						u8 liquid_level = (n2.param2&LIQUID_LEVEL_MASK) - (LIQUID_LEVEL_MAX+1-range);
						level = (-0.5 + ((float)liquid_level+ 0.5) / (float)range * node_liquid_level) * BS;
					}

					// Check node above neighbor.
					// NOTE: This doesn't get executed if neighbor
					//       doesn't exist
					p2.Y += 1;
					n2 = data->m_vmanip.getNodeNoEx(blockpos_nodes + p2);
					if(n2.getContent() == c_source ||
							n2.getContent() == c_flowing)
						flags |= neighborflag_top_is_same_liquid;
				}
				
				neighbor_levels[neighbor_dirs[i]] = level;
				neighbor_contents[neighbor_dirs[i]] = content;
				neighbor_flags[neighbor_dirs[i]] = flags;
			}

			// Corner heights (average between four liquids)
			f32 corner_levels[4];
			
			v3s16 halfdirs[4] = {
				v3s16(0,0,0),
				v3s16(1,0,0),
				v3s16(1,0,1),
				v3s16(0,0,1),
			};
			for(u32 i=0; i<4; i++)
			{
				v3s16 cornerdir = halfdirs[i];
				float cornerlevel = 0;
				u32 valid_count = 0;
				u32 air_count = 0;
				for(u32 j=0; j<4; j++)
				{
					v3s16 neighbordir = cornerdir - halfdirs[j];
					content_t content = neighbor_contents[neighbordir];
					// If top is liquid, draw starting from top of node
					if(neighbor_flags[neighbordir] &
							neighborflag_top_is_same_liquid)
					{
						cornerlevel = 0.5*BS;
						valid_count = 1;
						break;
					}
					// Source is always the same height
					else if(content == c_source)
					{
						cornerlevel = (-0.5+node_liquid_level)*BS;
						valid_count = 1;
						break;
					}
					// Flowing liquid has level information
					else if(content == c_flowing)
					{
						cornerlevel += neighbor_levels[neighbordir];
						valid_count++;
					}
					else if(content == CONTENT_AIR)
					{
						air_count++;
					}
				}
				if(air_count >= 2)
					cornerlevel = -0.5*BS+0.2;
				else if(valid_count > 0)
					cornerlevel /= valid_count;
				corner_levels[i] = cornerlevel;
			}

			/*
				Generate sides
			*/

			v3s16 side_dirs[4] = {
				v3s16(1,0,0),
				v3s16(-1,0,0),
				v3s16(0,0,1),
				v3s16(0,0,-1),
			};
			s16 side_corners[4][2] = {
				{1, 2},
				{3, 0},
				{2, 3},
				{0, 1},
			};
			for(u32 i=0; i<4; i++)
			{
				v3s16 dir = side_dirs[i];

				/*
					If our topside is liquid and neighbor's topside
					is liquid, don't draw side face
				*/
				if(top_is_same_liquid &&
						neighbor_flags[dir] & neighborflag_top_is_same_liquid)
					continue;

				content_t neighbor_content = neighbor_contents[dir];
				const ContentFeatures &n_feat = nodedef->get(neighbor_content);
				
				// Don't draw face if neighbor is blocking the view
				if(n_feat.solidness == 2)
					continue;
				
				bool neighbor_is_same_liquid = (neighbor_content == c_source
						|| neighbor_content == c_flowing);
				
				// Don't draw any faces if neighbor same is liquid and top is
				// same liquid
				if(neighbor_is_same_liquid == true
						&& top_is_same_liquid == false)
					continue;

				// Use backface culled material if neighbor doesn't have a
				// solidness of 0
				const TileSpec *current_tile = &tile_liquid;
				if(n_feat.solidness != 0 || n_feat.visual_solidness != 0)
					current_tile = &tile_liquid_bfculled;
				
				video::S3DVertex vertices[4] =
				{
					video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,1),
					video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, 1,1),
					video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, 1,0),
					video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,0),
				};
				
				/*
					If our topside is liquid, set upper border of face
					at upper border of node
				*/
				if(top_is_same_liquid)
				{
					vertices[2].Pos.Y = 0.5*BS;
					vertices[3].Pos.Y = 0.5*BS;
				}
				/*
					Otherwise upper position of face is corner levels
				*/
				else
				{
					vertices[2].Pos.Y = corner_levels[side_corners[i][0]];
					vertices[3].Pos.Y = corner_levels[side_corners[i][1]];
				}
				
				/*
					If neighbor is liquid, lower border of face is corner
					liquid levels
				*/
				if(neighbor_is_same_liquid)
				{
					vertices[0].Pos.Y = corner_levels[side_corners[i][1]];
					vertices[1].Pos.Y = corner_levels[side_corners[i][0]];
				}
				/*
					If neighbor is not liquid, lower border of face is
					lower border of node
				*/
				else
				{
					vertices[0].Pos.Y = -0.5*BS;
					vertices[1].Pos.Y = -0.5*BS;
				}
				
				for(s32 j=0; j<4; j++)
				{
					if(dir == v3s16(0,0,1))
						vertices[j].Pos.rotateXZBy(0);
					if(dir == v3s16(0,0,-1))
						vertices[j].Pos.rotateXZBy(180);
					if(dir == v3s16(-1,0,0))
						vertices[j].Pos.rotateXZBy(90);
					if(dir == v3s16(1,0,-0))
						vertices[j].Pos.rotateXZBy(-90);
						
					// Do this to not cause glitches when two liquids are
					// side-by-side
					/*if(neighbor_is_same_liquid == false){
						vertices[j].Pos.X *= 0.98;
						vertices[j].Pos.Z *= 0.98;
					}*/

					vertices[j].Pos += intToFloat(p, BS);
				}

				u16 indices[] = {0,1,2,2,3,0};
				// Add to mesh collector
				collector.append(*current_tile, vertices, 4, indices, 6);
			}
			
			/*
				Generate top side, if appropriate
			*/
			
			if(top_is_same_liquid == false)
			{
				video::S3DVertex vertices[4] =
				{
					video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,1),
					video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, 1,1),
					video::S3DVertex(BS/2,0,-BS/2, 0,0,0, c, 1,0),
					video::S3DVertex(-BS/2,0,-BS/2, 0,0,0, c, 0,0),
				};
				
				// To get backface culling right, the vertices need to go
				// clockwise around the front of the face. And we happened to
				// calculate corner levels in exact reverse order.
				s32 corner_resolve[4] = {3,2,1,0};

				for(s32 i=0; i<4; i++)
				{
					//vertices[i].Pos.Y += liquid_level;
					//vertices[i].Pos.Y += neighbor_levels[v3s16(0,0,0)];
					s32 j = corner_resolve[i];
					vertices[i].Pos.Y += corner_levels[j];
					vertices[i].Pos += intToFloat(p, BS);
				}
				
				// Default downwards-flowing texture animation goes from 
				// -Z towards +Z, thus the direction is +Z.
				// Rotate texture to make animation go in flow direction
				// Positive if liquid moves towards +Z
				int dz = (corner_levels[side_corners[3][0]] +
						corner_levels[side_corners[3][1]]) -
						(corner_levels[side_corners[2][0]] +
						corner_levels[side_corners[2][1]]);
				// Positive if liquid moves towards +X
				int dx = (corner_levels[side_corners[1][0]] +
						corner_levels[side_corners[1][1]]) -
						(corner_levels[side_corners[0][0]] +
						corner_levels[side_corners[0][1]]);
				// -X
				if(-dx >= abs(dz))
				{
					v2f t = vertices[0].TCoords;
					vertices[0].TCoords = vertices[1].TCoords;
					vertices[1].TCoords = vertices[2].TCoords;
					vertices[2].TCoords = vertices[3].TCoords;
					vertices[3].TCoords = t;
				}
				// +X
				if(dx >= abs(dz))
				{
					v2f t = vertices[0].TCoords;
					vertices[0].TCoords = vertices[3].TCoords;
					vertices[3].TCoords = vertices[2].TCoords;
					vertices[2].TCoords = vertices[1].TCoords;
					vertices[1].TCoords = t;
				}
				// -Z
				if(-dz >= abs(dx))
				{
					v2f t = vertices[0].TCoords;
					vertices[0].TCoords = vertices[3].TCoords;
					vertices[3].TCoords = vertices[2].TCoords;
					vertices[2].TCoords = vertices[1].TCoords;
					vertices[1].TCoords = t;
					t = vertices[0].TCoords;
					vertices[0].TCoords = vertices[3].TCoords;
					vertices[3].TCoords = vertices[2].TCoords;
					vertices[2].TCoords = vertices[1].TCoords;
					vertices[1].TCoords = t;
				}

				u16 indices[] = {0,1,2,2,3,0};
				// Add to mesh collector
				collector.append(tile_liquid, vertices, 4, indices, 6);
			}
		break;}
		case NDT_GLASSLIKE:
		{
			TileSpec tile = getNodeTile(n, p, v3s16(0,0,0), data);

			u16 l = getInteriorLight(n, 1, data);
			video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));

			for(u32 j=0; j<6; j++)
			{
				// Check this neighbor
				v3s16 n2p = blockpos_nodes + p + g_6dirs[j];
				MapNode n2 = data->m_vmanip.getNodeNoEx(n2p);
				// Don't make face if neighbor is of same type
				if(n2.getContent() == n.getContent())
					continue;

				// The face at Z+
				video::S3DVertex vertices[4] = {
					video::S3DVertex(-BS/2,-BS/2,BS/2, 0,0,0, c, 0,1),
					video::S3DVertex(BS/2,-BS/2,BS/2, 0,0,0, c, 1,1),
					video::S3DVertex(BS/2,BS/2,BS/2, 0,0,0, c, 1,0),
					video::S3DVertex(-BS/2,BS/2,BS/2, 0,0,0, c, 0,0),
				};
				
				// Rotations in the g_6dirs format
				if(j == 0) // Z+
					for(u16 i=0; i<4; i++)
						vertices[i].Pos.rotateXZBy(0);
				else if(j == 1) // Y+
					for(u16 i=0; i<4; i++)
						vertices[i].Pos.rotateYZBy(-90);
				else if(j == 2) // X+
					for(u16 i=0; i<4; i++)
						vertices[i].Pos.rotateXZBy(-90);
				else if(j == 3) // Z-
					for(u16 i=0; i<4; i++)
						vertices[i].Pos.rotateXZBy(180);
				else if(j == 4) // Y-
					for(u16 i=0; i<4; i++)
						vertices[i].Pos.rotateYZBy(90);
				else if(j == 5) // X-
					for(u16 i=0; i<4; i++)
						vertices[i].Pos.rotateXZBy(90);

				for(u16 i=0; i<4; i++){
					vertices[i].Pos += intToFloat(p, BS);
				}

				u16 indices[] = {0,1,2,2,3,0};
				// Add to mesh collector
				collector.append(tile, vertices, 4, indices, 6);
			}
		break;}
		case NDT_GLASSLIKE_FRAMED:
		{
			static const v3s16 dirs[6] = {
				v3s16( 0, 1, 0),
				v3s16( 0,-1, 0),
				v3s16( 1, 0, 0),
				v3s16(-1, 0, 0),
				v3s16( 0, 0, 1),
				v3s16( 0, 0,-1)
			};
			TileSpec tiles[2];
			tiles[0] = getNodeTile(n, p, dirs[0], data);
			tiles[1] = getNodeTile(n, p, dirs[1], data);
			u16 l = getInteriorLight(n, 1, data);
			video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));
			v3f pos = intToFloat(p, BS);
			static const float a=BS/2;
			static const float b=.876*(BS/2);
			static const aabb3f frame_edges[12] = {
				aabb3f( b, b,-a, a, a, a), // y+
				aabb3f(-a, b,-a,-b, a, a), // y+
				aabb3f( b,-a,-a, a,-b, a), // y-
				aabb3f(-a,-a,-a,-b,-b, a), // y-
				aabb3f( b,-a, b, a, a, a), // x+
				aabb3f( b,-a,-a, a, a,-b), // x+
				aabb3f(-a,-a, b,-b, a, a), // x-
				aabb3f(-a,-a,-a,-b, a,-b), // x-
				aabb3f(-a, b, b, a, a, a), // z+
				aabb3f(-a,-a, b, a,-b, a), // z+
				aabb3f(-a,-a,-a, a,-b,-b), // z-
				aabb3f(-a, b,-a, a, a,-b)  // z-
			};
			aabb3f glass_faces[6] = {
				aabb3f(-a, a,-a, a, a, a), // y+
				aabb3f(-a,-a,-a, a,-a, a), // y-
				aabb3f( a,-a,-a, a, a, a), // x+
				aabb3f(-a,-a,-a,-a, a, a), // x-
				aabb3f(-a,-a, a, a, a, a), // z+
				aabb3f(-a,-a,-a, a, a,-a)  // z-
			};
			
			int visible_faces[6] = {0,0,0,0,0,0};
			int nb[18] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
			u8 i;
			content_t current = n.getContent();
			content_t content;
			MapNode n2;
			v3s16 n2p;
			for(i=0; i<18; i++)
			{
				n2p = blockpos_nodes + p + g_26dirs[i];
				n2 = data->m_vmanip.getNodeNoEx(n2p);
				content_t n2c = n2.getContent();
				//TODO: remove CONTENT_IGNORE check when getNodeNoEx is fixed
				if (n2c == current || n2c == CONTENT_IGNORE)
					nb[i]=1;
			}
			for(i=0; i<6; i++)
			{
				n2p = blockpos_nodes + p + dirs[i];
				n2 = data->m_vmanip.getNodeNoEx(n2p);
				content = n2.getContent();
				const ContentFeatures &f2 = nodedef->get(content);
				if (content == CONTENT_AIR || f2.isLiquid())
					visible_faces[i]=1;
			}
			static const u8 nb_triplet[12*3] = {
				1,2, 7,  1,5, 6,  4,2,15,  4,5,14,
				2,0,11,  2,3,13,  5,0,10,  5,3,12,
				0,1, 8,  0,4,16,  3,4,17,  3,1, 9
			};

			f32 tx1,ty1,tz1,tx2,ty2,tz2;
			aabb3f box;
			for(i=0; i<12; i++)
			{
				int edge_invisible;
				if (nb[nb_triplet[i*3+2]]==1)
					edge_invisible=nb[nb_triplet[i*3]] & nb[nb_triplet[i*3+1]];
				else
					edge_invisible=nb[nb_triplet[i*3]] ^ nb[nb_triplet[i*3+1]];
				if (edge_invisible)
					continue;
				box=frame_edges[i];
				box.MinEdge += pos;
				box.MaxEdge += pos;
				tx1 = (box.MinEdge.X/BS)+0.5;
				ty1 = (box.MinEdge.Y/BS)+0.5;
				tz1 = (box.MinEdge.Z/BS)+0.5;
				tx2 = (box.MaxEdge.X/BS)+0.5;
				ty2 = (box.MaxEdge.Y/BS)+0.5;
				tz2 = (box.MaxEdge.Z/BS)+0.5;
				f32 txc1[24] = {
					tx1,   1-tz2,   tx2, 1-tz1,
					tx1,     tz1,   tx2,   tz2,
					tz1,   1-ty2,   tz2, 1-ty1,
					1-tz2, 1-ty2, 1-tz1, 1-ty1,
					1-tx2, 1-ty2, 1-tx1, 1-ty1,
					tx1,   1-ty2,   tx2, 1-ty1,
				};
				makeCuboid(&collector, box, &tiles[0], 1, c, txc1);
			}
			for(i=0; i<6; i++)
			{
				if (visible_faces[i]==0)
					continue;
				box=glass_faces[i];
				box.MinEdge += pos;
				box.MaxEdge += pos;
				tx1 = (box.MinEdge.X/BS)+0.5;
				ty1 = (box.MinEdge.Y/BS)+0.5;
				tz1 = (box.MinEdge.Z/BS)+0.5;
				tx2 = (box.MaxEdge.X/BS)+0.5;
				ty2 = (box.MaxEdge.Y/BS)+0.5;
				tz2 = (box.MaxEdge.Z/BS)+0.5;
				f32 txc2[24] = {
					tx1,   1-tz2,   tx2, 1-tz1,
					tx1,     tz1,   tx2,   tz2,
					tz1,   1-ty2,   tz2, 1-ty1,
					1-tz2, 1-ty2, 1-tz1, 1-ty1,
					1-tx2, 1-ty2, 1-tx1, 1-ty1,
					tx1,   1-ty2,   tx2, 1-ty1,
				};
				makeCuboid(&collector, box, &tiles[1], 1, c, txc2);
			}
		break;}
		case NDT_ALLFACES:
		{
			TileSpec tile_leaves = getNodeTile(n, p,
					v3s16(0,0,0), data);

			u16 l = getInteriorLight(n, 1, data);
			video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));

			v3f pos = intToFloat(p, BS);
			aabb3f box(-BS/2,-BS/2,-BS/2,BS/2,BS/2,BS/2);
			box.MinEdge += pos;
			box.MaxEdge += pos;
			makeCuboid(&collector, box, &tile_leaves, 1, c, NULL);
		break;}
		case NDT_ALLFACES_OPTIONAL:
			// This is always pre-converted to something else
			assert(0);
			break;
		case NDT_TORCHLIKE:
		{
			v3s16 dir = n.getWallMountedDir(nodedef);
			
			u8 tileindex = 0;
			if(dir == v3s16(0,-1,0)){
				tileindex = 0; // floor
			} else if(dir == v3s16(0,1,0)){
				tileindex = 1; // ceiling
			// For backwards compatibility
			} else if(dir == v3s16(0,0,0)){
				tileindex = 0; // floor
			} else {
				tileindex = 2; // side
			}

			TileSpec tile = getNodeTileN(n, p, tileindex, data);
			tile.material_flags &= ~MATERIAL_FLAG_BACKFACE_CULLING;
			tile.material_flags |= MATERIAL_FLAG_CRACK_OVERLAY;

			u16 l = getInteriorLight(n, 1, data);
			video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));

			// Wall at X+ of node
			video::S3DVertex vertices[4] =
			{
				video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c, 0,1),
				video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c, 1,1),
				video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 1,0),
				video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 0,0),
			};

			for(s32 i=0; i<4; i++)
			{
				if(dir == v3s16(1,0,0))
					vertices[i].Pos.rotateXZBy(0);
				if(dir == v3s16(-1,0,0))
					vertices[i].Pos.rotateXZBy(180);
				if(dir == v3s16(0,0,1))
					vertices[i].Pos.rotateXZBy(90);
				if(dir == v3s16(0,0,-1))
					vertices[i].Pos.rotateXZBy(-90);
				if(dir == v3s16(0,-1,0))
					vertices[i].Pos.rotateXZBy(45);
				if(dir == v3s16(0,1,0))
					vertices[i].Pos.rotateXZBy(-45);

				vertices[i].Pos += intToFloat(p, BS);
			}

			u16 indices[] = {0,1,2,2,3,0};
			// Add to mesh collector
			collector.append(tile, vertices, 4, indices, 6);
		break;}
		case NDT_SIGNLIKE:
		{
			TileSpec tile = getNodeTileN(n, p, 0, data);
			tile.material_flags &= ~MATERIAL_FLAG_BACKFACE_CULLING;
			tile.material_flags |= MATERIAL_FLAG_CRACK_OVERLAY;

			u16 l = getInteriorLight(n, 0, data);
			video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));
				
			float d = (float)BS/16;
			// Wall at X+ of node
			video::S3DVertex vertices[4] =
			{
				video::S3DVertex(BS/2-d,BS/2,BS/2, 0,0,0, c, 0,0),
				video::S3DVertex(BS/2-d,BS/2,-BS/2, 0,0,0, c, 1,0),
				video::S3DVertex(BS/2-d,-BS/2,-BS/2, 0,0,0, c, 1,1),
				video::S3DVertex(BS/2-d,-BS/2,BS/2, 0,0,0, c, 0,1),
			};

			v3s16 dir = n.getWallMountedDir(nodedef);

			for(s32 i=0; i<4; i++)
			{
				if(dir == v3s16(1,0,0))
					vertices[i].Pos.rotateXZBy(0);
				if(dir == v3s16(-1,0,0))
					vertices[i].Pos.rotateXZBy(180);
				if(dir == v3s16(0,0,1))
					vertices[i].Pos.rotateXZBy(90);
				if(dir == v3s16(0,0,-1))
					vertices[i].Pos.rotateXZBy(-90);
				if(dir == v3s16(0,-1,0))
					vertices[i].Pos.rotateXYBy(-90);
				if(dir == v3s16(0,1,0))
					vertices[i].Pos.rotateXYBy(90);

				vertices[i].Pos += intToFloat(p, BS);
			}

			u16 indices[] = {0,1,2,2,3,0};
			// Add to mesh collector
			collector.append(tile, vertices, 4, indices, 6);
		break;}
		case NDT_PLANTLIKE:
		{
			TileSpec tile = getNodeTileN(n, p, 0, data);
			tile.material_flags |= MATERIAL_FLAG_CRACK_OVERLAY;
			
			u16 l = getInteriorLight(n, 1, data);
			video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));

			for(u32 j=0; j<2; j++)
			{
				video::S3DVertex vertices[4] =
				{
					video::S3DVertex(-BS/2*f.visual_scale,-BS/2,0, 0,0,0, c, 0,1),
					video::S3DVertex( BS/2*f.visual_scale,-BS/2,0, 0,0,0, c, 1,1),
					video::S3DVertex( BS/2*f.visual_scale,
						-BS/2 + f.visual_scale*BS,0, 0,0,0, c, 1,0),
					video::S3DVertex(-BS/2*f.visual_scale,
						-BS/2 + f.visual_scale*BS,0, 0,0,0, c, 0,0),
				};

				if(j == 0)
				{
					for(u16 i=0; i<4; i++)
						vertices[i].Pos.rotateXZBy(45);
				}
				else if(j == 1)
				{
					for(u16 i=0; i<4; i++)
						vertices[i].Pos.rotateXZBy(-45);
				}

				for(u16 i=0; i<4; i++)
				{
					vertices[i].Pos *= f.visual_scale;
					vertices[i].Pos += intToFloat(p, BS);
				}

				u16 indices[] = {0,1,2,2,3,0};
				// Add to mesh collector
				collector.append(tile, vertices, 4, indices, 6);
			}
		break;}
		case NDT_FENCELIKE:
		{
			TileSpec tile = getNodeTile(n, p, v3s16(0,0,0), data);
			TileSpec tile_nocrack = tile;
			tile_nocrack.material_flags &= ~MATERIAL_FLAG_CRACK;
			
			// A hack to put wood the right way around in the posts
			ITextureSource *tsrc = data->m_gamedef->tsrc();
			std::string texturestring_rot = tsrc->getTextureName(
					tile.texture_id) + "^[transformR90";
			TileSpec tile_rot = tile;
			tile_rot.texture = tsrc->getTexture(
					texturestring_rot,
					&tile_rot.texture_id);
			
			u16 l = getInteriorLight(n, 1, data);
			video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));

			const f32 post_rad=(f32)BS/8;
			const f32 bar_rad=(f32)BS/16;
			const f32 bar_len=(f32)(BS/2)-post_rad;

			v3f pos = intToFloat(p, BS);

			// The post - always present
			aabb3f post(-post_rad,-BS/2,-post_rad,post_rad,BS/2,post_rad);
			post.MinEdge += pos;
			post.MaxEdge += pos;
			f32 postuv[24]={
					6/16.,6/16.,10/16.,10/16.,
					6/16.,6/16.,10/16.,10/16.,
					0/16.,0,4/16.,1,
					4/16.,0,8/16.,1,
					8/16.,0,12/16.,1,
					12/16.,0,16/16.,1};
			makeCuboid(&collector, post, &tile_rot, 1, c, postuv);

			// Now a section of fence, +X, if there's a post there
			v3s16 p2 = p;
			p2.X++;
			MapNode n2 = data->m_vmanip.getNodeNoEx(blockpos_nodes + p2);
			const ContentFeatures *f2 = &nodedef->get(n2);
			if(f2->drawtype == NDT_FENCELIKE)
			{
				aabb3f bar(-bar_len+BS/2,-bar_rad+BS/4,-bar_rad,
						bar_len+BS/2,bar_rad+BS/4,bar_rad);
				bar.MinEdge += pos;
				bar.MaxEdge += pos;
				f32 xrailuv[24]={
					0/16.,2/16.,16/16.,4/16.,
					0/16.,4/16.,16/16.,6/16.,
					6/16.,6/16.,8/16.,8/16.,
					10/16.,10/16.,12/16.,12/16.,
					0/16.,8/16.,16/16.,10/16.,
					0/16.,14/16.,16/16.,16/16.};
				makeCuboid(&collector, bar, &tile_nocrack, 1,
						c, xrailuv);
				bar.MinEdge.Y -= BS/2;
				bar.MaxEdge.Y -= BS/2;
				makeCuboid(&collector, bar, &tile_nocrack, 1,
						c, xrailuv);
			}

			// Now a section of fence, +Z, if there's a post there
			p2 = p;
			p2.Z++;
			n2 = data->m_vmanip.getNodeNoEx(blockpos_nodes + p2);
			f2 = &nodedef->get(n2);
			if(f2->drawtype == NDT_FENCELIKE)
			{
				aabb3f bar(-bar_rad,-bar_rad+BS/4,-bar_len+BS/2,
						bar_rad,bar_rad+BS/4,bar_len+BS/2);
				bar.MinEdge += pos;
				bar.MaxEdge += pos;
				f32 zrailuv[24]={
					3/16.,1/16.,5/16.,5/16., // cannot rotate; stretch
					4/16.,1/16.,6/16.,5/16., // for wood texture instead
					0/16.,9/16.,16/16.,11/16.,
					0/16.,6/16.,16/16.,8/16.,
					6/16.,6/16.,8/16.,8/16.,
					10/16.,10/16.,12/16.,12/16.};
				makeCuboid(&collector, bar, &tile_nocrack, 1,
						c, zrailuv);
				bar.MinEdge.Y -= BS/2;
				bar.MaxEdge.Y -= BS/2;
				makeCuboid(&collector, bar, &tile_nocrack, 1,
						c, zrailuv);
			}
		break;}
		case NDT_RAILLIKE:
		{
			bool is_rail_x [] = { false, false };  /* x-1, x+1 */
			bool is_rail_z [] = { false, false };  /* z-1, z+1 */

			bool is_rail_z_minus_y [] = { false, false };  /* z-1, z+1; y-1 */
			bool is_rail_x_minus_y [] = { false, false };  /* x-1, z+1; y-1 */
			bool is_rail_z_plus_y [] = { false, false };  /* z-1, z+1; y+1 */
			bool is_rail_x_plus_y [] = { false, false };  /* x-1, x+1; y+1 */

			MapNode n_minus_x = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x-1,y,z));
			MapNode n_plus_x = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x+1,y,z));
			MapNode n_minus_z = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x,y,z-1));
			MapNode n_plus_z = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x,y,z+1));
			MapNode n_plus_x_plus_y = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x+1, y+1, z));
			MapNode n_plus_x_minus_y = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x+1, y-1, z));
			MapNode n_minus_x_plus_y = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x-1, y+1, z));
			MapNode n_minus_x_minus_y = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x-1, y-1, z));
			MapNode n_plus_z_plus_y = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x, y+1, z+1));
			MapNode n_minus_z_plus_y = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x, y+1, z-1));
			MapNode n_plus_z_minus_y = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x, y-1, z+1));
			MapNode n_minus_z_minus_y = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x, y-1, z-1));

			content_t thiscontent = n.getContent();
			std::string groupname = "connect_to_raillike"; // name of the group that enables connecting to raillike nodes of different kind
			bool self_connect_to_raillike = ((ItemGroupList) nodedef->get(n).groups)[groupname] != 0;

			if ((nodedef->get(n_minus_x).drawtype == NDT_RAILLIKE
					&& ((ItemGroupList) nodedef->get(n_minus_x).groups)[groupname] != 0
					&& self_connect_to_raillike)
					|| n_minus_x.getContent() == thiscontent)
				is_rail_x[0] = true;

			if ((nodedef->get(n_minus_x_minus_y).drawtype == NDT_RAILLIKE
					&& ((ItemGroupList) nodedef->get(n_minus_x_minus_y).groups)[groupname] != 0
					&& self_connect_to_raillike)
					|| n_minus_x_minus_y.getContent() == thiscontent)
				is_rail_x_minus_y[0] = true;

			if ((nodedef->get(n_minus_x_plus_y).drawtype == NDT_RAILLIKE
					&& ((ItemGroupList) nodedef->get(n_minus_x_plus_y).groups)[groupname] != 0
					&& self_connect_to_raillike)
					|| n_minus_x_plus_y.getContent() == thiscontent)
				is_rail_x_plus_y[0] = true;

			if ((nodedef->get(n_plus_x).drawtype == NDT_RAILLIKE
					&& ((ItemGroupList) nodedef->get(n_plus_x).groups)[groupname] != 0
					&& self_connect_to_raillike)
					|| n_plus_x.getContent() == thiscontent)
				is_rail_x[1] = true;

			if ((nodedef->get(n_plus_x_minus_y).drawtype == NDT_RAILLIKE
					&& ((ItemGroupList) nodedef->get(n_plus_x_minus_y).groups)[groupname] != 0
					&& self_connect_to_raillike)
					|| n_plus_x_minus_y.getContent() == thiscontent)
				is_rail_x_minus_y[1] = true;

			if ((nodedef->get(n_plus_x_plus_y).drawtype == NDT_RAILLIKE
					&& ((ItemGroupList) nodedef->get(n_plus_x_plus_y).groups)[groupname] != 0
					&& self_connect_to_raillike)
					|| n_plus_x_plus_y.getContent() == thiscontent)
				is_rail_x_plus_y[1] = true;

			if ((nodedef->get(n_minus_z).drawtype == NDT_RAILLIKE
					&& ((ItemGroupList) nodedef->get(n_minus_z).groups)[groupname] != 0
					&& self_connect_to_raillike)
					|| n_minus_z.getContent() == thiscontent)
				is_rail_z[0] = true;

			if ((nodedef->get(n_minus_z_minus_y).drawtype == NDT_RAILLIKE
					&& ((ItemGroupList) nodedef->get(n_minus_z_minus_y).groups)[groupname] != 0
					&& self_connect_to_raillike)
					|| n_minus_z_minus_y.getContent() == thiscontent)
				is_rail_z_minus_y[0] = true;

			if ((nodedef->get(n_minus_z_plus_y).drawtype == NDT_RAILLIKE
					&& ((ItemGroupList) nodedef->get(n_minus_z_plus_y).groups)[groupname] != 0
					&& self_connect_to_raillike)
					|| n_minus_z_plus_y.getContent() == thiscontent)
				is_rail_z_plus_y[0] = true;

			if ((nodedef->get(n_plus_z).drawtype == NDT_RAILLIKE
					&& ((ItemGroupList) nodedef->get(n_plus_z).groups)[groupname] != 0
					&& self_connect_to_raillike)
					|| n_plus_z.getContent() == thiscontent)
				is_rail_z[1] = true;

			if ((nodedef->get(n_plus_z_minus_y).drawtype == NDT_RAILLIKE
					&& ((ItemGroupList) nodedef->get(n_plus_z_minus_y).groups)[groupname] != 0
					&& self_connect_to_raillike)
					|| n_plus_z_minus_y.getContent() == thiscontent)
				is_rail_z_minus_y[1] = true;

			if ((nodedef->get(n_plus_z_plus_y).drawtype == NDT_RAILLIKE
					&& ((ItemGroupList) nodedef->get(n_plus_z_plus_y).groups)[groupname] != 0
					&& self_connect_to_raillike)
					|| n_plus_z_plus_y.getContent() == thiscontent)
				is_rail_z_plus_y[1] = true;

			bool is_rail_x_all[] = {false, false};
			bool is_rail_z_all[] = {false, false};
			is_rail_x_all[0]=is_rail_x[0] || is_rail_x_minus_y[0] || is_rail_x_plus_y[0];
			is_rail_x_all[1]=is_rail_x[1] || is_rail_x_minus_y[1] || is_rail_x_plus_y[1];
			is_rail_z_all[0]=is_rail_z[0] || is_rail_z_minus_y[0] || is_rail_z_plus_y[0];
			is_rail_z_all[1]=is_rail_z[1] || is_rail_z_minus_y[1] || is_rail_z_plus_y[1];

			// reasonable default, flat straight unrotated rail
			bool is_straight = true;
			int adjacencies = 0;
			int angle = 0;
			u8 tileindex = 0;

			// check for sloped rail
			if (is_rail_x_plus_y[0] || is_rail_x_plus_y[1] || is_rail_z_plus_y[0] || is_rail_z_plus_y[1])
			{
				adjacencies = 5; //5 means sloped
				is_straight = true; // sloped is always straight
			}
			else
			{
				// is really straight, rails on both sides
				is_straight = (is_rail_x_all[0] && is_rail_x_all[1]) || (is_rail_z_all[0] && is_rail_z_all[1]);
				adjacencies = is_rail_x_all[0] + is_rail_x_all[1] + is_rail_z_all[0] + is_rail_z_all[1];
			}

			switch (adjacencies) {
			case 1:
				if(is_rail_x_all[0] || is_rail_x_all[1])
					angle = 90;
				break;
			case 2:
				if(!is_straight)
					tileindex = 1; // curved
				if(is_rail_x_all[0] && is_rail_x_all[1])
					angle = 90;
				if(is_rail_z_all[0] && is_rail_z_all[1]){
					if (is_rail_z_plus_y[0])
						angle = 180;
				}
				else if(is_rail_x_all[0] && is_rail_z_all[0])
					angle = 270;
				else if(is_rail_x_all[0] && is_rail_z_all[1])
					angle = 180;
				else if(is_rail_x_all[1] && is_rail_z_all[1])
					angle = 90;
				break;
			case 3:
				// here is where the potential to 'switch' a junction is, but not implemented at present
				tileindex = 2; // t-junction
				if(!is_rail_x_all[1])
					angle=180;
				if(!is_rail_z_all[0])
					angle=90;
				if(!is_rail_z_all[1])
					angle=270;
				break;
			case 4:
				tileindex = 3; // crossing
				break;
			case 5: //sloped
				if(is_rail_z_plus_y[0])
					angle = 180;
				if(is_rail_x_plus_y[0])
					angle = 90;
				if(is_rail_x_plus_y[1])
					angle = -90;
				break;
			default:
				break;
			}

			TileSpec tile = getNodeTileN(n, p, tileindex, data);
			tile.material_flags &= ~MATERIAL_FLAG_BACKFACE_CULLING;
			tile.material_flags |= MATERIAL_FLAG_CRACK_OVERLAY;

			u16 l = getInteriorLight(n, 0, data);
			video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));

			float d = (float)BS/64;
			
			char g=-1;
			if (is_rail_x_plus_y[0] || is_rail_x_plus_y[1] || is_rail_z_plus_y[0] || is_rail_z_plus_y[1])
				g=1; //Object is at a slope

			video::S3DVertex vertices[4] =
			{
					video::S3DVertex(-BS/2,-BS/2+d,-BS/2, 0,0,0, c, 0,1),
					video::S3DVertex(BS/2,-BS/2+d,-BS/2, 0,0,0, c, 1,1),
					video::S3DVertex(BS/2,g*BS/2+d,BS/2, 0,0,0, c, 1,0),
					video::S3DVertex(-BS/2,g*BS/2+d,BS/2, 0,0,0, c, 0,0),
			};

			for(s32 i=0; i<4; i++)
			{
				if(angle != 0)
					vertices[i].Pos.rotateXZBy(angle);
				vertices[i].Pos += intToFloat(p, BS);
			}

			u16 indices[] = {0,1,2,2,3,0};
			collector.append(tile, vertices, 4, indices, 6);
		break;}
		case NDT_NODEBOX:
		{
			static const v3s16 tile_dirs[6] = {
				v3s16(0, 1, 0),
				v3s16(0, -1, 0),
				v3s16(1, 0, 0),
				v3s16(-1, 0, 0),
				v3s16(0, 0, 1),
				v3s16(0, 0, -1)
			};
			TileSpec tiles[6];
			
			u16 l = getInteriorLight(n, 0, data);
			video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));

			v3f pos = intToFloat(p, BS);

			std::vector<aabb3f> boxes = n.getNodeBoxes(nodedef);
			for(std::vector<aabb3f>::iterator
					i = boxes.begin();
					i != boxes.end(); i++)
			{
			for(int j = 0; j < 6; j++)
				{
				// Handles facedir rotation for textures
				tiles[j] = getNodeTile(n, p, tile_dirs[j], data);
				}
				aabb3f box = *i;
				box.MinEdge += pos;
				box.MaxEdge += pos;
				
				f32 temp;
				if (box.MinEdge.X > box.MaxEdge.X)
				{
					temp=box.MinEdge.X;
					box.MinEdge.X=box.MaxEdge.X;
					box.MaxEdge.X=temp;
				}
				if (box.MinEdge.Y > box.MaxEdge.Y)
				{
					temp=box.MinEdge.Y;
					box.MinEdge.Y=box.MaxEdge.Y;
					box.MaxEdge.Y=temp;
				}
				if (box.MinEdge.Z > box.MaxEdge.Z)
				{
					temp=box.MinEdge.Z;
					box.MinEdge.Z=box.MaxEdge.Z;
					box.MaxEdge.Z=temp;
				}

				//
				// Compute texture coords
				f32 tx1 = (box.MinEdge.X/BS)+0.5;
				f32 ty1 = (box.MinEdge.Y/BS)+0.5;
				f32 tz1 = (box.MinEdge.Z/BS)+0.5;
				f32 tx2 = (box.MaxEdge.X/BS)+0.5;
				f32 ty2 = (box.MaxEdge.Y/BS)+0.5;
				f32 tz2 = (box.MaxEdge.Z/BS)+0.5;
				f32 txc[24] = {
					// up
					tx1, 1-tz2, tx2, 1-tz1,
					// down
					tx1, tz1, tx2, tz2,
					// right
					tz1, 1-ty2, tz2, 1-ty1,
					// left
					1-tz2, 1-ty2, 1-tz1, 1-ty1,
					// back
					1-tx2, 1-ty2, 1-tx1, 1-ty1,
					// front
					tx1, 1-ty2, tx2, 1-ty1,
				};
				makeCuboid(&collector, box, tiles, 6, c, txc);
			}
		break;}
		}
	}
}
Example #16
0
 ViewMover (const GlobalRef& view_, int x_, int y_, int w_, int h_)
     : view (view_), x (x_), y (y_), w (w_), h (h_)
 {
     post();
 }
Example #17
0
static t_int *fofsynth_perform(t_int *w)
{
     t_fofsynth* x = (t_fofsynth*) (w[1]);
     t_sample *in = (t_sample *)(w[2]);
     t_sample *out = (t_sample *)(w[3]);
     int n = (int)(w[4]);

     t_float totaldur = (x->risedur+ x->falldur)*0.01/ *in;

     t_sample srate = 44100.0; /*((t_signal*)w[2])->s_sr;*/
     t_sample israte = 1.0/srate;

     t_float fundphase = x->fundph;
     t_float numperiods = totaldur*x->formfreq;
     t_float formphinc = (x->formfreq/srate);

     t_sample risinc;
     t_sample fallinc;

     t_grain* cur;

     risinc  = (x->risedur == 0.0) ? 1.0 : 1.0/ (srate*totaldur*0.01*x->risedur);
     fallinc = (x->falldur == 0.0) ? 1.0 : 1.0/ (srate*totaldur*0.01*x->falldur);
     
     DEBUG(" fundph %3.2f",x->fundph);
     DEBUG(" fundfreq %3.2f",x->fundfreq);
     DEBUG(" formfreq %3.2f",x->formfreq);
     DEBUG(" risedur %3.2f %",x->risedur);
     DEBUG(" falldur %3.2f %",x->falldur);
     DEBUG(" totaldur %3.2f s",totaldur);
     DEBUG(" risinc %0.6f",risinc);
     DEBUG(" fallinc %0.6f",fallinc);
     DEBUG(" formant increase %3.2f",formphinc);
     DEBUG(" numgrains %d",x->numgrains);
    
     while (n--)
     {
	  fundphase+=*++in*israte;
	  *out = 0.0;

	  if (x->neednewgrain) {  /* new grain, they are deleted separetely */
	       t_grain* newgrain = x->grainend;
/*	       DEBUG("new grain created",0); */
	       if (newgrain->next == x->grainstart) {
		    post("fof: grain overflow");		   
		    x->neednewgrain = 0;  
	       }
	       else {
		    x->numgrains++;
		    x->grainend = newgrain->next;
		    newgrain->formphinc = formphinc;
		    newgrain->falling = 0;
		    newgrain->formph = newgrain->envph = 0.0;
		    x->neednewgrain = 0;  
	       }
	  }

	  cur = x->grainstart;
	  while (cur != x->grainend) {
	       t_sample formphase = cur->formph;
	       t_sample envelope;

	       t_sample tph = (formphase - (t_sample)((int) formphase));
	       t_sample val = x->x_vec[(int) (tph * x->x_npoints)].w_float;

	       /* Apply the envelope */

	       if (!cur->falling && (cur->envph <= 1.0)) { 
		    envelope = *(halfcos_table + (int) (cur->envph * COSTABSIZE));
		    cur->envph+=risinc;
		    val *= envelope;
	       }
	       else if (!cur->falling)
	       {
		    cur->falling = 1;
		    cur->envph = 0;
	       }
	       

	       if (cur->falling) {
		    envelope = *(exp_table + (int) (cur->envph * COSTABSIZE));
		    cur->envph+=fallinc;
		    val *= envelope;
	       }		    

	       /* end of envelope code */


	       formphase+=cur->formphinc;
	       cur->formph = formphase;
	       
	       if (formphase >= numperiods) { /* dead */
		    DEBUG("grain died",0);
		    x->grainstart = cur->next;
		    x->numgrains--;/* not needed */
	       }
	       
	       cur = cur->next;
	       *out += val;
	  }
	  

	  if (fundphase > 1.0) {
	       fundphase -=  1.0;
	       x->neednewgrain=1;
	  }
	  out++;
     }

     x->fundph=fundphase;
     x->debug = 0;


     return (w+5);
}
Example #18
0
/*! Get sample frames
	\param buf		pointer array to channel buffers
	\param frames	number of maximum frames to get
	\return			frames put into buffers
*/
int Stream::doGet(int ch,float *const *buf,int frames,float sr)
{
	ASSERT(ch > 0 && frames >= 0 && sr > 0);

	if(isOk() && !isInitializing()) {
		// signal thread worker
		pthread_cond_signal(&cond);

		// check/(re)allocate buffers

		int strch = getChannels();
		if(bufs && bufch < strch) { 
			delete[] decoded;
			for(int i = 0; i < bufch; ++i) src_delete(src_state[i]);
			delete[] src_state;
			delete[] bufs;	bufs = NULL; 
		}

		if(!bufs) {
			if(bufch < strch) bufch = strch;
			bufs = new float *[bufch];
			decoded = new Fifo<float>[bufch];

			src_state = new SRC_STATE *[bufch];
			for(int i = 0; i < bufch; ++i) {
				int error;
				src_state[i] = src_new(SRC_ZERO_ORDER_HOLD,1,&error);
				if(!src_state[i]) post("src init error %i",error);
			}
		}

		// get frames

		float ratio = sr/getSamplerate();
		int frneed = (int)(frames/ratio)+DECMORE;  // number of frames to read from decoder fifo

		if(decoded[0].Size() < frneed) {
			// fifos are too small -> resize them (while keeping their contents)
			for(int i = 0; i < bufch; ++i) decoded[i].Resize(frneed,true);
		}

		// how many frames do we need to get from decoder?
		int frread = frneed-decoded[0].Have();

		int ret = state == ST_WAIT?0:DataRead(frread);

		if(ret < 0) {
			if(debug) post("read error");
			// clear output
			for(int c = 0; c < ch; ++c)
				memset(buf[c],0,frames*sizeof *buf[c]);
			return 0;
		}
		else {
			// how many channels do we really need for output?
			// this should be set elsewhere, because we can't change anyway!!! 
			// (SRC_STATE for dangling channels would be incorrect)
			int cmin = strch;
			if(ch < cmin) cmin = ch;

			// write data to fifo
			for(int i = 0; i < cmin; ++i) {
				int wr = decoded[i].Write(ret,bufs[i]);
				if(wr < ret) post("fifo overflow");
			}

//			state = ST_PROCESS;

			if(ratio == 1) {
				// no resampling necessary

				// hopefully all channel fifos advance uniformly.....
				for(int i = 0; i < cmin; ++i) {

					for(int got = 0; got < frames; ) {
						int cnt = frames-got;

						if(decoded[i].Have()) {
							got += decoded[i].Read(cnt,buf[i]+got);
						}
						else {
							state = ST_WAIT;
							if(debug) post("fifo underrun");

							// Buffer underrun!! -> zero output buffer
							memset(buf[i]+got,0,cnt*sizeof(*buf[i]));
							got += cnt;
						}
					}
				}
			}
			else 
			{
				SRC_DATA src_data;
				src_data.src_ratio = ratio;
				src_data.end_of_input = 0;

				// hopefully all channel fifos advance uniformly.....
				for(int i = 0; i < cmin; ++i) {
					src_set_ratio(src_state[i],ratio);

					for(int got = 0; got < frames; ) {
						src_data.data_out = buf[i]+got;
						src_data.output_frames = frames-got;

						if(decoded[i].Have()) {
							src_data.data_in = decoded[i].ReadPtr();
							src_data.input_frames = decoded[i].ReadSamples();

							int err = src_process(src_state[i],&src_data);
							if(err) post("src_process error %i",err);

							// advance buffer
							decoded[i].Read(src_data.input_frames_used,NULL);
						}
						else {
							state = ST_WAIT;
							if(debug) post("fifo underrun");

							// Buffer underrun!! -> zero output buffer
							memset(src_data.data_out,0,src_data.output_frames*sizeof(*src_data.data_out));
							src_data.output_frames_gen = src_data.output_frames;
						}
						got += src_data.output_frames_gen;
					}
				}
			}

			// zero remaining channels
			for(int c = cmin; c < ch; ++c)
				memset(buf[c],0,frames*sizeof *buf[c]);

			return ret;
		}
	}
	else {
		for(int c = 0; c < ch; ++c)
			memset(buf[c],0,frames*sizeof *buf[c]);
		return 0;
	}
}
Example #19
0
/*! Thread worker - fill the fifo with socket data */
void Stream::Work()
{
	int waittime = 0;

	// lower thread priority
    {
	    struct sched_param parm;
	    int policy;
	    if(pthread_getschedparam(pthread_self(),&policy,&parm) >= 0) {
            int minprio = sched_get_priority_min(policy);

            if(debug) post("priority was %i (min = %i)",parm.sched_priority,minprio);

            parm.sched_priority += THRPRIOR;

    		if(parm.sched_priority < minprio) parm.sched_priority = minprio;
            pthread_setschedparam(pthread_self(),policy,&parm);
        }

	    if(pthread_getschedparam(pthread_self(),&policy,&parm) >= 0) {
            if(debug) post("priority set to %i",parm.sched_priority);
        }
    }

	while(!exit) {
		pthread_mutex_lock(&mutex);

		bool wait = true;

		if(!hostname.length() || !mountpt.length() || port < 0) {}
		else
		if(state == ST_INIT || state == ST_RECONNECT) {
			// initialize!

			bool ok = true;

			try {
				file = Connect( hostname.c_str(),mountpt.c_str(),port);
			}
			catch(char *str) {
				if(state != ST_RECONNECT) post(str);
				ok = false;
			}
			catch(...) {
				post("Unknown error while connecting");
				ok = false;
			}

			// initialize decoder
			if(ok) ok = WorkInit();

			// try to fill buffer
			if(ok) {
				int i,lim = (int)(encoded.Size()*encthresh);
				for(i = MAXINITTRIES; i > 0 && encoded.Have() < lim; ) {
					int n = ReadChunk(encoded.Free(),true);
					if(!n) --i;
				}
				if(!i) ok = false;
			}

			if(!ok) {
				Reset();

				if(state == ST_INIT) state = ST_IDLE;
				// if reconnecting keep on doing that...
			}
			else {
				state = ST_PROCESS;
				waittime = 0;
			}
		}
		else if(isOk()) {
			SOCKET fd = file;
			int chunk = encoded.Free();
			if(chunk > encchunk) chunk = encchunk;
			
			if(chunk) {
				int n = ReadChunk(chunk,true);

				if(n == 0) {
					if(debug) post("error receiving data");
					state = ST_WAIT;
				}
				else
					// reset error state
					state = ST_PROCESS;
			}

			if(encoded.Have() < encoded.Size()*encthresh) 
				// immediately get the next chunk
				wait = false;
		}

		if(debug && encoded.Free()) {
			post("fifo: sz/fill = %5i/%3.0f%%",encoded.Size(),(float)encoded.Have()/encoded.Size()*100);
		}

		if(state == ST_WAIT) {
			if(debug) post("Wait for data");
			Sleep(waitgrain);
			waittime += waitgrain;
			if(waittime > waitreconnect) {
				if(debug) post("do reconnect");
				state = ST_RECONNECT;
			}
			wait = false;
		}
		else if(state == ST_RECONNECT) {
			if(debug) post("Reconnecting again");
			Sleep(waitgrain);
			wait = false;
		}


		if(wait) pthread_cond_wait(&cond,&mutex);

		pthread_mutex_unlock(&mutex);
	}

	state = ST_FINISHED;
}
Example #20
0
HttpResponse HttpClient::post(const HttpUrl& url, const FormData& form_data){
    return post(url, form_data.get_string(), form_data.get_content_type());
}
Example #21
0
 inline ExecStatus
 QXorv<BVA,BVB,BVC>::post(Home home, QBoolVar b0, QBoolVar b1, BVC b2) {
   return post(home,b0.x,b0.q,b0.r,b1.x,b1.q,b1.r,b2);
 }
Example #22
0
 response const post (request const & request_, string_type const & body_) {
     return post(request_, "x-application/octet-stream", body_);
 }
Example #23
0
// function to create new instance and initialise its parameters
void *drag_new(t_symbol *s, short argc, t_atom *argv)
{
    t_double bound_lo = -1.0, bound_hi = 1.0;
    t_int i = 0, dir = -1;
    t_drag *x = object_alloc(drag_class); // set aside memory for the struct for the object

    x->mode = 0;
    x->drag = DRAG_DEFAULT;
    x->dragCurve = DRAGCURVE;
    x->maxcrash = log(CRASHMAX);
    x->fmax = FMAX * 0.5;
    x->bound_lo = bound_lo;
    x->bound_hi = bound_hi;
    atom_arg_getlong(&(x->voice_count), 0, argc, argv);
    atom_arg_getdouble(&(x->bound_lo), 1, argc, argv);
    atom_arg_getdouble(&(x->bound_hi), 2, argc, argv);
    x->mode = atom_getintarg(3,argc,argv);
    if(x->mode < 0) x->mode = 0;
    else if (x->mode > 4) x->mode = 4;
    atom_arg_getdouble(&(x->drag), 4, argc, argv);

    //protect against invalid parameters
    if(x->voice_count > MAX_VOICES) {
        x->voice_count = MAX_VOICES;
    } else if (x->voice_count < 1) {
        x->voice_count = 1;
    }
    if (x->bound_lo < BOUND_L_MIN) x->bound_lo = BOUND_L_MIN;
    if (x->bound_hi > BOUND_H_MAX) x->bound_lo = BOUND_H_MAX;
    if(x->bound_lo >= x->bound_hi) {
        x->bound_lo = BOUND_L_MIN;
        x->bound_hi = BOUND_H_MAX;
        post("invalid args for bounds, set to %f, %f", BOUND_L_MIN, BOUND_H_MAX);
    }
    x->drag = DRAG_DEFAULT;

    // add to dsp chain, set up inlets
    dsp_setup((t_pxobject *)x, 2*x->voice_count + 2); // upper and lower bounds, plus hz and symm per voice
    x->obj.z_misc |= Z_NO_INPLACE; // force independent signal vectors

    // allocate memory for variable arrays
    x->hz = (t_double **) t_getbytes(x->voice_count * sizeof(t_double *));
    x->symm = (t_double **) t_getbytes(x->voice_count * sizeof(t_double *));
    x->out = (t_double **) t_getbytes(x->voice_count * sizeof(t_double *));
    x->hzFloat = (t_double *) t_getbytes(x->voice_count * sizeof(t_double));
    x->hzActual = (t_double *) t_getbytes(x->voice_count * sizeof(t_double));
    x->grad = (t_double *) t_getbytes(x->voice_count * sizeof(t_double));
    x->ball_loc = (t_double *) t_getbytes(x->voice_count * sizeof(t_double));
    x->crash = (t_double *) t_getbytes(x->voice_count * sizeof(t_double));
    x->lastcrash = (t_double *) t_getbytes(x->voice_count * sizeof(t_double));
    x->direction = (t_int *) t_getbytes(x->voice_count * sizeof(t_int));
    x->hz_conn = (t_int *) t_getbytes(x->voice_count * sizeof(t_int));
    x->symm_conn = (t_int *) t_getbytes(x->voice_count * sizeof(t_int));
    x->dcblock_on = (t_bool *) t_getbytes(x->voice_count * sizeof(t_bool));
    x->dc_prev_in = (t_double *) t_getbytes(x->voice_count * sizeof(t_double));
    x->dc_prev_out = (t_double *) t_getbytes(x->voice_count * sizeof(t_double));
    x->shape = (t_double *) t_getbytes(x->voice_count * sizeof(t_double));
    x->sin = (t_double *)  t_getbytes(LKTBL_LNGTH * sizeof(t_double));
    x->sinh = (t_double *)  t_getbytes(LKTBL_LNGTH * sizeof(t_double));
    x->isfree = (t_bool *) t_getbytes(x->voice_count * sizeof(t_bool));

    setup_lktables(x,0); // build lookup tables for waveshaper

    //set up outlets & and get rate for each voice from args
    x->ball_loc[0] = bound_lo + THINNESTPIPE;
    x->direction[0] = 1;
    for(i=0; i < x->voice_count; i++) {
        outlet_new((t_object *)x, "signal");

        x->shape[i] = 0.1f;
        x->grad[i] = 2;
        x->hzActual[i] = x->hzFloat[i] = 100;
        x->ball_loc[i] =  (x->ball_loc[i-1] + THINNESTPIPE); // begin near bottom of current bound
        dir *= -1,  x->direction[i] = dir;	// alternate up and down
        x->dcblock_on[i] = 0;
        x->dc_prev_in[i] = x->dc_prev_out[i] = 0.f;

    }

    // initialize remaining parameters
    x->srate = (t_double)sys_getsr();

#if DEBUG_ON == 1|| DEBUG_ON == 2
    x->poll_count = POLL_NO_SAMPLES-1;
    x->stopdebug = x->debug_count = 0;
#endif

    return x;
}
Example #24
0
 response const post (request request_, string_type const & content_type, string_type const & body_) {
     request_ << ::boost::network::body(body_)
         << header("Content-Type", content_type)
         << header("Content-Length", boost::lexical_cast<string_type>(body_.size()));
     return post(request_);
 }
Example #25
0
/// Append Holmes-elements for phones in (phonestr) to (eltq).
/// Returns ps->t.
unsigned phone_to_elm(phtoelm_state_t *ps, char *phonestr, dsqueue_t *eltq) {

#ifdef PHOLMES_DEBUG
  post("phone_to_elm(): called with phonestr='%s'", phonestr);
#endif

  ps->s = phonestr;
  while (ps->s && *ps->s) {
    pte_eltseq_str es = trie_lookup(&phtoelm, &(ps->s));
    if (es) {
     int n = *es++;
     while (n-- > 0) {
       int eid = *es++;             // -- index of sequence-element in Elements[]
       holmes_qelt_t he;            // -- encoded Holmes-triple for output-queue
       Elm_ptr ep = &Elements[eid]; // -- pointer to actual current element
       int dur;                     // -- placeholder for element duration

       //
       // This works because only vowels have ud != du,
       //  and we set stress just before a vowel
       //
       if (!(ep->feat & vwl)) ps->stress = 0;
       dur = StressDur(ep,ps->stress);
       he = hqeNew(eid,dur,ps->stress);

       // append the encoded element to the output queue
       dsqueue_append(eltq, (void *)he);

#ifdef PHOLMES_DEBUG
       post("phone_to_elm(): enqueued Holmes-triple %s,%d,%d", ep->name,dur,ps->stress);
#endif
     }
    }
    else {
     char ch = *(ps->s++);
     switch (ch) {
     case '\'':                // Primary stress
       ps->stress = 3;
       break;
     case ',':                 // Secondary stress
       ps->stress = 2;
       break;
     case '+':                 // Tertiary stress
       ps->stress = 1;
       break;
     case '-':                 // hyphen in input
       break;
     case '.':                 // literal dot indicates end-of-utterance
       dsqueue_append(eltq, (void *)hqeNew(0,0,0));
       break;
     default:
       {
	 fprintf(stderr,
		 "phone_to_elm(): ignoring unknown character '%c'\n",
		 ch);
	 break;
       }
     }
    }
  }
  return ps->t;
}
Example #26
0
    /* open ogg/vorbis file */                 
static void oggread_open(t_oggread *x, t_symbol *filename)
{
	int i;

	x->x_stream = 0;
		/* first close previous file */
	if(x->x_fd > 0)
	{
		ov_clear(&x->x_ov);
		post("oggread~: previous file closed");
	}
		/* open file for reading */
#ifdef WIN32
	if((x->x_file = fopen(filename->s_name, "rb")) < 0)
#else
   if((x->x_file = fopen(filename->s_name, "r")) < 0)
#endif
    {
		post("oggread~: could not open file \"%s\"", filename->s_name);
		x->x_eos = 1;
		x->x_fd = -1;
    }
    else
    {
		x->x_stream = 0;
		x->x_eos = 0;
		x->x_fd = 1;
		x->x_outreadposition = 0;
		x->x_outwriteposition = 0;
		x->x_outunread = 0;
		post("oggread~: file \"%s\" opened", filename->s_name);
		outlet_float( x->x_out_position, 0);

			/* try to open as ogg vorbis file */
		if(ov_open(x->x_file, &x->x_ov, NULL, -1) < 0)
		{		/* an error occured (no ogg vorbis file ?) */
			post("oggread~: error: could not open \"%s\" as an OggVorbis file", filename->s_name);
			ov_clear(&x->x_ov);
			post("oggread~: file closed due to error");
      x->x_fd=-1;
      x->x_eos=1;
      return;
		}

			/* print details about each logical bitstream in the input */
		if(ov_seekable(&x->x_ov))
		{
			post("oggread~: input bitstream contained %ld logical bitstream section(s)", ov_streams(&x->x_ov));
			post("oggread~: total bitstream playing time: %ld seconds", (long)ov_time_total(&x->x_ov,-1));
			post("oggread~: encoded by: %s\n",ov_comment(&x->x_ov,-1)->vendor);
		}
		else
		{
			post("oggread~: file \"%s\" was not seekable\n"
			"oggread~: first logical bitstream information:", filename->s_name);
		}

		for(i = 0; i < ov_streams(&x->x_ov); i++)
		{
			x->x_vi = ov_info(&x->x_ov,i);
			post("\tlogical bitstream section %d information:",i+1);
			post("\t\t%ldHz %d channels bitrate %ldkbps serial number=%ld",
				x->x_vi->rate,x->x_vi->channels,ov_bitrate(&x->x_ov,i)/1000, ov_serialnumber(&x->x_ov,i));
			post("\t\theader length: %ld bytes",(long)
			(x->x_ov.dataoffsets[i] - x->x_ov.offsets[i]));
			post("\t\tcompressed length: %ld bytes",(long)(ov_raw_total(&x->x_ov,i)));
			post("\t\tplay time: %ld seconds\n",(long)ov_time_total(&x->x_ov,i));
		}

    } 
}
Example #27
0
static void zeroCrossing_tilde_overlap(t_zeroCrossing_tilde *x, t_floatarg f)
{
	x->overlap = (int)f;

    post("overlap: %i", x->overlap);
}
Example #28
0
 void post(typename queue_type::job_type job)
 {
     post(std::move(job),0);
 }
Example #29
0
    /* stop playing */               
static void oggread_stop(t_oggread *x)
{
	if(x->x_stream)post("oggread~: STOP");
    x->x_stream = 0;
	clock_unset(x->x_clock);
}
void
somatic_snv_caller_strand_grid::
position_somatic_snv_call(const extended_pos_info& normal_epi,
                          const extended_pos_info& tumor_epi,
                          const extended_pos_info* normal_epi_t2_ptr,
                          const extended_pos_info* tumor_epi_t2_ptr,
                          somatic_snv_genotype_grid& sgt) const {

    static const bool is_always_test(false);

    {
        const snp_pos_info& normal_pi(normal_epi.pi);
        const snp_pos_info& tumor_pi(tumor_epi.pi);

        if(normal_pi.ref_base=='N') return;
        sgt.ref_gt=base_to_id(normal_pi.ref_base);

        // check that a non-reference call meeting quality criteria even
        // exists:
        if(not is_always_test) {
            if(is_spi_allref(normal_pi,sgt.ref_gt) and is_spi_allref(tumor_pi,sgt.ref_gt)) return;
        }
    }

    // strawman model treats normal and tumor as independent, so
    // calculate separate lhoods:
    blt_float_t normal_lhood[DIGT_SGRID::SIZE];
    blt_float_t tumor_lhood[DIGT_SGRID::SIZE];

    const bool is_tier2(NULL != normal_epi_t2_ptr);

    static const unsigned n_tier(2);
    result_set tier_rs[n_tier];
    for(unsigned i(0); i<n_tier; ++i) {
        const bool is_include_tier2(i==1);
        if(is_include_tier2) {
            if(! is_tier2) continue;
            if(tier_rs[0].snv_qphred==0) {
                tier_rs[1].snv_qphred=0;
                continue;
            }
        }

        // get likelihood of each genotype
        //
        static const bool is_normal_het_bias(false);
        static const blt_float_t normal_het_bias(0.0);
        static const bool is_tumor_het_bias(false);
        static const blt_float_t tumor_het_bias(0.0);

        const extended_pos_info& nepi(is_include_tier2 ? *normal_epi_t2_ptr : normal_epi );
        const extended_pos_info& tepi(is_include_tier2 ? *tumor_epi_t2_ptr : tumor_epi );
        get_diploid_gt_lhood_spi(_opt,nepi.pi,is_normal_het_bias,normal_het_bias,normal_lhood);
        get_diploid_gt_lhood_spi(_opt,tepi.pi,is_tumor_het_bias,tumor_het_bias,tumor_lhood);

        get_diploid_het_grid_lhood_spi(nepi.pi,normal_lhood+DIGT::SIZE);
        get_diploid_het_grid_lhood_spi(tepi.pi,tumor_lhood+DIGT::SIZE);

        get_diploid_strand_grid_lhood_spi(nepi.pi,sgt.ref_gt,normal_lhood+DIGT_SGRID::PRESTRAND_SIZE);
        get_diploid_strand_grid_lhood_spi(tepi.pi,sgt.ref_gt,tumor_lhood+DIGT_SGRID::PRESTRAND_SIZE);

        // genomic site results:
        calculate_result_set_grid(normal_lhood,
                                  tumor_lhood,
                                  get_prior_set(sgt.ref_gt),
                                  _ln_som_match,_ln_som_mismatch,
                                  sgt.ref_gt,
                                  tier_rs[i]);

#if 0
#ifdef ENABLE_POLY
        // polymorphic site results:
        assert(0); // still needs to be adapted for 2-tier system:
        calculate_result_set(normal_lhood,tumor_lhood,
                             lnprior_polymorphic(sgt.ref_gt),sgt.ref_gt,sgt.poly);
#else
        sgt.poly.snv_qphred = 0;
#endif
#endif

#ifdef SOMATIC_DEBUG
        if((i==0) && (tier_rs[i].snv_qphred > 0)) {
            const somatic_snv_caller_strand_grid::prior_set& pset(get_prior_set(sgt.ref_gt));
            const blt_float_t lnmatch(_ln_som_match);
            const blt_float_t lnmismatch(_ln_som_mismatch);

            log_os << "DUMP ON\n";
            log_os << "tier1_qphred: " << tier_rs[0].snv_qphred << "\n";

            // instead of dumping the entire distribution, we sort the lhood,prior,and prob to print out the N top values of each:
            std::vector<double> lhood(DDIGT_SGRID::SIZE);
            std::vector<double> prior(DDIGT_SGRID::SIZE);
            std::vector<double> post(DDIGT_SGRID::SIZE);

            // first get raw lhood:
            //
            for(unsigned ngt(0); ngt<DIGT_SGRID::PRESTRAND_SIZE; ++ngt) {
                for(unsigned tgt(0); tgt<DIGT_SGRID::PRESTRAND_SIZE; ++tgt) {
                    const unsigned dgt(DDIGT_SGRID::get_state(ngt,tgt));
                    // unorm takes the role of the normal prior for the somatic case:
                    //            static const blt_float_t unorm(std::log(static_cast<blt_float_t>(DIGT_SGRID::PRESTRAND_SIZE)));

                    //blt_float_t prior;
                    //if(tgt==ngt) { prior=pset.normal[ngt]+lnmatch; }
                    //else         { prior=pset.somatic_marginal[ngt]+lnmismatch; }
                    blt_float_t pr;
                    if(tgt==ngt) { pr=pset.normal[ngt]+lnmatch; }
                    else         { pr=pset.somatic_marginal[ngt]+lnmismatch; }
                    prior[dgt] = pr;

                    lhood[dgt] = normal_lhood[ngt]+tumor_lhood[tgt];
                    post[dgt] = lhood[dgt] + prior[dgt];
                }
            }

            for(unsigned gt(DIGT_SGRID::PRESTRAND_SIZE); gt<DIGT_SGRID::SIZE; ++gt) {
                const unsigned dgt(DDIGT_SGRID::get_state(gt,gt));
                lhood[dgt] = normal_lhood[gt]+tumor_lhood[gt];
                prior[dgt] = pset.normal[gt]+lnmatch;
                post[dgt] = lhood[dgt] + prior[dgt];
            }

            std::vector<double> lhood2(lhood);
            sort_n_dump("lhood_prior",lhood,prior,sgt.ref_gt);
            sort_n_dump("post_lhood",post,lhood2,sgt.ref_gt);

            log_os << "DUMP OFF\n";
        }
#endif

    }

    if((tier_rs[0].snv_qphred==0) ||
       (is_tier2 && (tier_rs[1].snv_qphred==0))) return;

    sgt.snv_tier=0;
    sgt.snv_from_ntype_tier=0;
    if(is_tier2) {
        if(tier_rs[0].snv_qphred > tier_rs[1].snv_qphred) {
            sgt.snv_tier=1;
        }

        if(tier_rs[0].snv_from_ntype_qphred > tier_rs[1].snv_from_ntype_qphred) {
            sgt.snv_from_ntype_tier=1;
        }
    }

    sgt.rs=tier_rs[sgt.snv_from_ntype_tier];

    if(is_tier2 && (tier_rs[0].ntype != tier_rs[1].ntype)) {
        // catch NTYPE conflict states:
        sgt.rs.ntype = NTYPE::CONFLICT;
        sgt.rs.snv_from_ntype_qphred = 0;
    } else {
        // classify NTYPE:
        //

        // convert diploid genotype into more limited ntype set:
        //
        if       (sgt.rs.ntype==sgt.ref_gt) {
            sgt.rs.ntype=NTYPE::REF;
        } else if(DIGT::is_het(sgt.rs.ntype)) {
            sgt.rs.ntype=NTYPE::HET;
        } else {
            sgt.rs.ntype=NTYPE::HOM;
        }
    }

    sgt.rs.snv_qphred = tier_rs[sgt.snv_tier].snv_qphred;
    sgt.is_snv=((sgt.rs.snv_qphred != 0));
}