void World::RenderGroup(SceneGroup *i, mat4 t) { int ii, time = 0; // sphere vars double r; MaterialInfo m; // light vars LightInfo l; // camera vars CameraInfo f; // if this is a terminal node if (i->getChildCount() == 0) { // if this node is a sphere if (i->computeSphere(r,m,time)) { _spheres.push_back(Sphere(vec4(0,0,0,1), r, m, t)); } else if (i->computeLight(l)) { if (l.type == LIGHT_POINT) { _lights[l.type].push_back(Light(vec3(t*vec4(0,0,0,1),VW),0, l)); }else if (l.type == LIGHT_DIRECTIONAL){ _lights[l.type].push_back(Light(0,vec3(t*vec4(0,0,-1,0),VW), l)); }else if (l.type == LIGHT_AMBIENT) _ambientLight = l.color; } else if (i->computeCamera(f)) { vec4 eye(0.0, 0.0, 0.0, 1.0); vec4 LL(f.sides[FRUS_LEFT], f.sides[FRUS_BOTTOM], -1*f.sides[FRUS_NEAR], 1.0); vec4 UL(f.sides[FRUS_LEFT], f.sides[FRUS_TOP], -1*f.sides[FRUS_NEAR], 1.0); vec4 LR(f.sides[FRUS_RIGHT], f.sides[FRUS_BOTTOM], -1*f.sides[FRUS_NEAR], 1.0); vec4 UR(f.sides[FRUS_RIGHT], f.sides[FRUS_TOP], -1*f.sides[FRUS_NEAR], 1.0); _view = Viewport(eye, LL, UL, LR, UR, IMAGE_WIDTH, IMAGE_HEIGHT); } } else { // expand and traverse this node for(ii=0; ii<i->getChildCount();ii++) RenderInstance(i->getChild(ii), t); } }
/* push index */ int qindex_push_index(QINDEX *qindex, int64_t key, IBDATA *block) { DOCHEADER *docheader = NULL; XPACKET *xpackets = NULL; int mid = 0, old = 0; if(qindex && block->ndata > 0 && (docheader = (DOCHEADER *)block->data)) { MUTEX_LOCK(qindex->mutex); if(docheader->size == block->ndata && (xpackets = (XPACKET *)(qindex->xpacketio.map)) && (mid = mmtree64_try_insert(qindex->idmap, qindex->state->rootid, key, (qindex->state->id_max+1), &old)) > 0) { if(old > 0) mid = old; else mid = ++(qindex->state->id_max); db_set_data(PDB(qindex->db), mid, block->data, block->ndata); if(mid <= qindex->state->xpackettotal) { if(xpackets[mid].crc != docheader->crc) qindex_update(qindex, mid, 1); else qindex_update(qindex, mid, 0); xpackets[mid].status = docheader->status; xpackets[mid].crc = docheader->crc; ACCESS_LOGGER(qindex->logger, "update-index{gloablid:%lld mid:%d total:%d}", LL(docheader->globalid), mid, qindex->state->xpackettotal); } else { qindex->state->xpackettotal = mid; CHECK_XPACKETIO(qindex); if((xpackets = (XPACKET *)(qindex->xpacketio.map))) { xpackets[mid].status = docheader->status; xpackets[mid].crc = docheader->crc; ACCESS_LOGGER(qindex->logger, "new-index{gloablid:%lld mid:%d}", LL(docheader->globalid), mid); } } } else { FATAL_LOGGER(qindex->logger, "Invalid document size:%d ndata:%d id:%lld crc:%d", docheader->size, block->ndata, LL(docheader->globalid), docheader->crc); _exit(-1); } MUTEX_UNLOCK(qindex->mutex); } return mid; }
static bool f12h_mc0_mce(u16 ec, u8 xec) { bool ret = false; if (MEM_ERROR(ec)) { u8 ll = LL(ec); ret = true; if (ll == LL_L2) pr_cont("during L1 linefill from L2.\n"); else if (ll == LL_L1) pr_cont("Data/Tag %s error.\n", R4_MSG(ec)); else ret = false; } return ret; }
session * session_malloc (void) { session *s = (session *) malloc (sizeof (session)); if (!s) { LL (); fprintf (stderr, "%s: session malloc() failed: %s (%i)\n", progname, strerror (errno), errno); exit (EXIT_FAILURE); } else memset (s, '\0', sizeof (session)); return s; }
bool Run(string &buf) { bool bResult; float outRT; LeptLog LL("c:/recogText.log"); LeptTextRecognition LTR(LL); //LTR.TrainingFromPath("C:/recog/GOSTdigits", 0); LTR.TrainingFromPath("../../../TestImage/TEXT/GOSTfont"); bResult = LTR.FileRecognition("../../../TestImage/TEXT/Picture11.tif", buf, outRT); //bResult = LTR.FileRecognition("C:/test2/Image 3.tif", buf, outRT); //pixDisplay(pixdb, 800, 800); //pixDisplay(pixat->pix[2], 800, 800); return bResult; }
Direction DumbDirectionSolver::tryToMove(Point pt) { int count = 0; int newX = pt.getX(); int newY = pt.getY(); Direction result(LL("NULL")); bool again = false; do { result = whereICanGoFrom(pt); if (result.isNull()) { return result; } newX = result.changeX(pt.getX()); newY = result.changeY(pt.getY()); bool bombAtWay = (!bomb.isNull()) && (bomb == Point(newX, newY)); bool barrierAtWay = board.isBarrierAt(newX, newY); auto futBla = board.getFutureBlasts(); bool blastAtWay = (std::find(futBla.begin(), futBla.end(), Point(newX, newY)) != futBla.end()); bool meatChopperNearWay = board.isNear(newX, newY, Element(LL("MEAT_CHOPPER"))); if (blastAtWay && board.countNear(pt.getX(), pt.getY(), Element(LL("SPACE"))) == 1 && !board.isAt(pt.getX(), pt.getY(), Element(LL("BOMB_BOMBERMAN")))) { result = Direction(LL("STOP")); return result; } again = bombAtWay || barrierAtWay || meatChopperNearWay; bool deadEndAtWay = (board.countNear(newX, newY, Element(LL("SPACE"))) == 0 && !bomb.isNull()); if (deadEndAtWay) { bomb.setNull(true); } if (result == Direction(LL("NULL"))) { again == true; } } while (count++ < 20 && again); if (count >= 20) { result = Direction(LL("ACT")); } return result; }
static bool f14h_mc1_mce(u16 ec, u8 xec) { u8 r4 = R4(ec); bool ret = true; if (MEM_ERROR(ec)) { if (TT(ec) != 0 || LL(ec) != 1) ret = false; if (r4 == R4_IRD) pr_cont("Data/tag array parity error for a tag hit.\n"); else if (r4 == R4_SNOOP) pr_cont("Tag error during snoop/victimization.\n"); else ret = false; } return ret; }
void caldate_frommjd(struct caldate *cd, int64_t day, int *pwday, int *pyday) { long year; long month; int yday; year = (long)(day / LL(146097)); day %= LL(146097); day += LL(678881); while (day >= LL(146097)) { day -= LL(146097); ++year; } /* year * 146097 + day - 678881 is MJD; 0 <= day < 146097 */ /* 2000-03-01, MJD 51604, is year 5, day 0 */ if (pwday) *pwday = (int)((day + 3) % 7); year *= 4; if (day == LL(146096)) { year += 3; day = 36524L; } else { year += (long)(day / LL(36524)); day %= LL(36524); } year *= 25; year += (long)(day / 1461); day %= 1461; year *= 4; yday = (day < 306); if (day == 1460) { year += 3; day = 365; } else { year += (long)(day / 365); day %= 365; } yday += (int)day; day *= 10; month = (long)((day + 5) / 306); day = (day + 5) % 306; day /= 10; if (month >= 10) { yday -= 306; ++year; month -= 10; } else { yday += 59; month += 2; } cd->year = year; cd->month = (int)month + 1; cd->day = (int)(day + 1); if (pyday) *pyday = yday; }
Node NodeInsert(Node rootnode , int data){ if (rootnode == NULL){ rootnode = CreatNode(NULL , NULL , data); return rootnode; } if (data == rootnode -> data){ printf("Insert Node %d Failed !\n" , data); } if (data < rootnode -> data){ rootnode -> left = NodeInsert(rootnode -> left , data); rootnode -> height = MAX(Height(rootnode -> left) , Height(rootnode -> right)) + 1; //lose balance int rightheight = 0; if (rootnode -> right != NULL){ rightheight = rootnode -> right ->height; } if (Height(rootnode -> left) >= rightheight + 2){ if (data < rootnode -> left -> data){ rootnode = LL(rootnode); }else{ rootnode = LR(rootnode); } } }else{ if (data > rootnode -> data){ rootnode -> right = NodeInsert(rootnode -> right , data); rootnode -> height = MAX(Height(rootnode -> left) , Height(rootnode -> right)) + 1; //lose balance int leftheight = 0; if (rootnode -> left != NULL){ leftheight = rootnode -> left -> height; } if (Height(rootnode -> right) >= leftheight + 2){ if (data > rootnode -> right -> data){ rootnode = RR(rootnode); }else{ rootnode = RL(rootnode); } } } } rootnode -> height = MAX(Height(rootnode -> left) , Height(rootnode -> right)) + 1; return rootnode; }
void diff2PDF_u_tCopula_new(double* u, double* v, int* n, double* param, int* copula, double* out) { double x1, x2; int j=0, k=1; double t1, t2, t4, t5, t6, t7, t8, t9, t11, t12, t13, M, c=0, diffPDF=0, diff_dt2=0; double t14, t15, t16; double rho = param[0]; double nu = param[1]; t1=nu+2.0; t14=rho*rho; t4=1.0-t14; for(j=0;j<*n;j++) { LL(copula, &k, &u[j], &v[j], &rho, &nu, &c); c=exp(c); x1=qt(u[j],nu,1,0); x2=qt(v[j],nu,1,0); t15=x1*x1; t16=x2*x2; M = ( nu*t4 + t15 + t16 - 2.0*rho*x1*x2 ); t2=dt(x1,nu,0); diffPDF_u_tCopula_new(&u[j], &v[j], &k, param, copula, &diffPDF); diff_dt_u(&x1, &nu, &diff_dt2); t7=x1-rho*x2; t5=-diffPDF/t2 + diff_dt2/t2/t2*c; t6=t1*t7/M + diff_dt2; t11=c/t2; t8=1.0/t2; t9=t1/M - 2.0*t1*t7*t7/M/M; t13=1.0+t15/nu; t12=t8*( -(nu+1.0)/(nu+t15) + 2.0*t15* (nu+1.0)/nu/nu / t13/t13); out[j]=t5*t6 - t11*(t8*t9 + t12); } }
void diffPDF_nu_tCopula_new(double* u, double* v, int* n, double* param, int* copula, double* out) { double out1=0, out2=0, x1, x2; int j=0, k=1; double t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, M, c; double rho = param[0]; double nu = param[1]; t1=digamma((nu+1.0)/2.0); t2=digamma(nu/2.0); t14=rho*rho; t3=0.5*log(1.0-t14); t4=(nu-2.0)/(2.0*nu); t5=0.5*log(nu); t6=-t1+t2+t3-t4-t5; t10=(nu+2.0)/2.0; for(j=0;j<*n;j++) { LL(copula, &k, &u[j], &v[j], &rho, &nu, &c); c=exp(c); x1=qt(u[j],nu,1,0); x2=qt(v[j],nu,1,0); diffX_nu_tCopula(&x1, param, &out1); diffX_nu_tCopula(&x2, param, &out2); t7=1.0+2.0*x1*out1; t8=1.0+2.0*x2*out2; t15=x2*x2; t16=x1*x1; t9=(nu+1.0)/2.0*( t7/(nu+x1*x1) + t8/(nu+t15) ); M=nu*(1.0-t14) + t16 + t15 - 2.0*rho*x1*x2; t11=1.0 - t14 + 2.0*x1*out1 + 2.0*x2*out2 - 2.0*rho*(x1*out2+x2*out1); t12=0.5*log((nu+t16)*(nu+t15)); t13=0.5*log(M); out[j]=c*(t6 + t9 + t12 - t10*t11/M - t13); } }
Node* AvlTree::nodeInsert(Node* &rootNode , int data){ if (rootNode == NULL){ rootNode = new Node(NULL, NULL, data); return rootNode; } if (data == rootNode->data){ return NULL; } if (data < rootNode -> data){ rootNode -> left = nodeInsert(rootNode->left, data); rootNode -> height = MAX(Height(rootNode->left) , Height(rootNode -> right)) + 1; int rightHeight = 0; if (rootNode -> right != NULL){ rightHeight = rootNode -> right -> height; } if (Height(rootNode -> left) >= rightHeight + 2){ if (data < rootNode -> left -> data){ rootNode = LL(rootNode); }else{ rootNode = LR(rootNode); } } }else{ if (data > rootNode -> data){ rootNode -> right = nodeInsert(rootNode -> right, data); rootNode -> height = 1 + MAX(Height(rootNode -> left) , Height(rootNode -> right)); int leftHeight = 0; if (rootNode -> left != NULL){ leftHeight = rootNode -> left -> height; } if (Height(rootNode -> right) >= leftHeight + 2){ if (data > rootNode -> right -> data){ rootNode = RR(rootNode); }else{ rootNode = RL(rootNode); } } } } rootNode -> height = MAX(Height(rootNode -> left) , Height(rootNode -> right)) + 1; return rootNode; }
float Plane::angle(const Line &L) {// the return value should be between 0 and 90, if -1, means error. Vector v1 = getNVector(); Vector v2; fPoint p; Line LL(L); LL.getPara(p,v2); float t1 = v1.length(), t2 = v2.length(); if ((fabs(t1-0)<ZERO) ||(fabs(t2-0)<ZERO)){ printf("\n Error: Plane::angle(Line)"); return -1.0f; } float alpha = v1.dotProduct(v2)/t1/t2; //alpha = facos (fabs(alpha)); alpha = acos (fabs(alpha)); return alpha; }
static TLDNode *balance(TLDNode *node) { int nodeDiff; nodeDiff=checkDiff(node); if (nodeDiff>1){ int checkLeft=checkDiff(node->left); if (checkLeft>0){ node=LL(node); }else{ node=LR(node); } }else if(nodeDiff<-1){ int checkRight=checkDiff(node->right); if (checkRight>0){ node=RL(node); }else{ node=RR(node); } }; return node; }
uint transid_store_packed(MARIA_HA *info, uchar *to, ulonglong trid) { uchar *start; uint length; uchar buff[8]; DBUG_ASSERT(trid < (LL(1) << (MARIA_MAX_PACK_TRANSID_SIZE*8))); DBUG_ASSERT(trid >= info->s->state.create_trid); trid= (trid - info->s->state.create_trid) << 1; /* Mark that key contains transid */ to[-1]|= 1; if (trid < MARIA_MIN_TRANSID_PACK_OFFSET) { to[0]= (uchar) trid; return 1; } start= to; /* store things in low-byte-first-order in buff */ to= buff; do { *to++= (uchar) trid; trid= trid>>8; } while (trid); length= (uint) (to - buff); /* Store length prefix */ start[0]= (uchar) (length + MARIA_TRANSID_PACK_OFFSET); start++; /* Copy things in high-byte-first order to output buffer */ do { *start++= *--to; } while (to != buff); return length+1; }
void diff2PDF_u_v_tCopula_new(double* u, double* v, int* n, double* param, int* copula, double* out) { double x1, x2; int j=0, k=1; double t1, t2, t4, t5, t6, t7, t8, t9, t10, t11, t12, M, c=0, diff_dt1=0, diff_dt2=0; double rho = param[0]; double nu = param[1]; t1=nu+2.0; t4=1.0-rho*rho; for(j=0;j<*n;j++) { LL(copula, &k, &u[j], &v[j], &rho, &nu, &c); c=exp(c); x1=qt(u[j],nu,1,0); x2=qt(v[j],nu,1,0); M = ( nu*t4 + x1*x1 + x2*x2 - 2.0*rho*x1*x2 ); t2=dt(x1,nu,0); t5=dt(x2,nu,0); t6=x1-rho*x2; t7=x2-rho*x1; diff_dt_u(&x1, &nu, &diff_dt1); diff_dt_u(&x2, &nu, &diff_dt2); t8=c/t2/t5; t9=t1*t6/M + diff_dt1; t10=t1*t7/M + diff_dt2; t11=t1*rho/M; t12=2.0*t1*t6*t7/M/M; out[j]=t8*(t9*t10 + t11 + t12); } }
void diff2PDF_rho_nu_tCopula_new(double* u, double* v, int* n, double* param, int* copula, double* out) { double out1=0, out2=0, x1, x2; int j=0, k=1; double t3, t4, t5, t6, t7, t8, t9, t10, t11, M_rho, M_nu, M, c; double rho = param[0]; double nu = param[1]; t4=1.0-rho*rho; t3=rho/t4; t5=nu+2.0; for(j=0;j<*n;j++) { LL(copula, &k, &u[j], &v[j], &rho, &nu, &c); c=exp(c); x1=qt(u[j],nu,1,0); x2=qt(v[j],nu,1,0); diffX_nu_tCopula(&x1, param, &out1); diffX_nu_tCopula(&x2, param, &out2); t10=x1*x1; t11=x2*x2; M = ( nu*t4 + t10 + t11 - 2.0*rho*x1*x2 ); diffPDF_rho_tCopula(&u[j], &v[j], &k, param, copula, &t6); diffPDF_nu_tCopula_new(&u[j], &v[j], &k, param, copula, &t7); M_rho=-2.0*(nu*rho+x1*x2); t8=(x1*out2+out1*x2); M_nu=t4+2.0*x1*out1+2.0*x2*out2-2.0*rho*t8; t9=-t3+t5/M*(rho+t8+0.5*M_nu*M_rho/M)-0.5*M_rho/M; out[j]=c*t9+t6*t7/c; } }
function tradeOneNightStand() { vars Price = series(price()); vars SMA10 = series(SMA(Price, 10)); vars SMA40 = series(SMA(Price, 40)); //Stop = 3 * 90 * PIP; var BuyStop,SellStop; BuyStop = HH(10) + 1*PIP; SellStop = LL(10) - 1*PIP; if (dow() == 5 && NumOpenLong == 0 && NumPendingLong == 0 && SMA10[0] > SMA40[0]) enterLong(0,BuyStop); else if (dow() == 5 && NumOpenShort == 0 && NumPendingShort == 0 && SMA10[0] < SMA40[0]) enterShort(0,SellStop); if (dow() != 5 && dow() != 6 && dow() != 7) { exitLong(); exitShort(); } }
void main() { int m; printf("1:复利计算\n"); printf("2:单利计算\n"); printf("3:求本金\n"); printf("4:求时间\n"); printf("5:求利率\n"); printf("请输入序号"); scanf("%d",&m); if(m==1) FL(); else if(m==2) DL(); else if(m==3) BJ(); else if(m==4) Time(); else if(m==5) LL(); }
void ktapc_chunkid(char *out, const char *source, size_t bufflen) { size_t l = strlen(source); if (*source == '=') { /* 'literal' source */ if (l <= bufflen) /* small enough? */ memcpy(out, source + 1, l * sizeof(char)); else { /* truncate it */ addstr(out, source + 1, bufflen - 1); *out = '\0'; } } else if (*source == '@') { /* file name */ if (l <= bufflen) /* small enough? */ memcpy(out, source + 1, l * sizeof(char)); else { /* add '...' before rest of name */ addstr(out, RETS, LL(RETS)); bufflen -= LL(RETS); memcpy(out, source + 1 + l - bufflen, bufflen * sizeof(char)); } } else { /* string; format as [string "source"] */ const char *nl = strchr(source, '\n'); /* find first new line (if any) */ addstr(out, PRE, LL(PRE)); /* add prefix */ bufflen -= LL(PRE RETS POS) + 1; /* save space for prefix+suffix+'\0' */ if (l < bufflen && nl == NULL) { /* small one-line source? */ addstr(out, source, l); /* keep it */ } else { if (nl != NULL) l = nl - source; /* stop at first newline */ if (l > bufflen) l = bufflen; addstr(out, source, l); addstr(out, RETS, LL(RETS)); } memcpy(out, POS, (LL(POS) + 1) * sizeof(char)); } }
static qboolean R_LoadMDX( model_t *mod, void *buffer, const char *mod_name ) { int i, j; mdxHeader_t *pinmodel, *mdx; mdxFrame_t *frame; short *bframe; mdxBoneInfo_t *bi; int version; int size; int frameSize; pinmodel = ( mdxHeader_t * ) buffer; version = LittleLong( pinmodel->version ); if ( version != MDX_VERSION ) { ri.Printf( PRINT_WARNING, "R_LoadMDX: %s has wrong version (%i should be %i)\n", mod_name, version, MDX_VERSION ); return qfalse; } mod->type = MOD_MDX; size = LittleLong( pinmodel->ofsEnd ); mod->dataSize += size; mdx = mod->mdx = ri.Hunk_Alloc( size, h_low ); memcpy( mdx, buffer, LittleLong( pinmodel->ofsEnd ) ); LL( mdx->ident ); LL( mdx->version ); LL( mdx->numFrames ); LL( mdx->numBones ); LL( mdx->ofsFrames ); LL( mdx->ofsBones ); LL( mdx->ofsEnd ); LL( mdx->torsoParent ); if ( LittleLong( 1 ) != 1 ) { // swap all the frames frameSize = ( int )( sizeof( mdxBoneFrameCompressed_t ) ) * mdx->numBones; for ( i = 0; i < mdx->numFrames; i++ ) { frame = ( mdxFrame_t * )( ( byte * ) mdx + mdx->ofsFrames + i * frameSize + i * sizeof( mdxFrame_t ) ); frame->radius = LittleFloat( frame->radius ); for ( j = 0; j < 3; j++ ) { frame->bounds[ 0 ][ j ] = LittleFloat( frame->bounds[ 0 ][ j ] ); frame->bounds[ 1 ][ j ] = LittleFloat( frame->bounds[ 1 ][ j ] ); frame->localOrigin[ j ] = LittleFloat( frame->localOrigin[ j ] ); frame->parentOffset[ j ] = LittleFloat( frame->parentOffset[ j ] ); } bframe = ( short * )( ( byte * ) mdx + mdx->ofsFrames + i * frameSize + ( ( i + 1 ) * sizeof( mdxFrame_t ) ) ); for ( j = 0; j < mdx->numBones * sizeof( mdxBoneFrameCompressed_t ) / sizeof( short ); j++ ) { ( ( short * ) bframe ) [ j ] = LittleShort( ( ( short * ) bframe ) [ j ] ); } } // swap all the bones for ( i = 0; i < mdx->numBones; i++ ) { bi = ( mdxBoneInfo_t * )( ( byte * ) mdx + mdx->ofsBones + i * sizeof( mdxBoneInfo_t ) ); LL( bi->parent ); bi->torsoWeight = LittleFloat( bi->torsoWeight ); bi->parentDist = LittleFloat( bi->parentDist ); LL( bi->flags ); } } return qtrue; }
void OrthoBuilder::LUsolve( vector<vector<PL_NUM>>& AA, vector<PL_NUM>& ff, vector<PL_NUM>* xx ) { if( AA.size() < 1 ) { cout << "ERROR in LUsolve: AA.size() is less than 1\n"; return; } int AAsize = AA.size(); vector<PL_NUM> storage( AAsize, 0.0 ); PL_NUM tmpNum = 0; int nzRow = 0; if( fabs( AA[0][0] ) < ALMOST_ZERO ) //TODO may be I can join this and the next block. I mean the checks on AA[i][j] != 0 { //make AA[0][0] nonzero by changing the order of rows int nzFound = false; for( nzRow; nzRow < AAsize; ++nzRow ) { if( fabs( AA[nzRow][0] ) > ALMOST_ZERO ) //CHECK, may be it is better to put != 0 here { nzFound = true; break; } } if( nzFound == false ) { cout << "ERROR in LUsolve: no nonzero elements found\n"; return; } for( int col = 0; col < AAsize; ++col ) { storage[col] = AA[nzRow][col]; AA[nzRow][col] = AA[0][col]; AA[0][col] = storage[col]; } tmpNum = ff[nzRow]; ff[nzRow] = ff[0]; ff[0] = tmpNum; } for( int i = 0; i < AAsize; ++i ) { if( fabs( AA[i][i] ) < ALMOST_ZERO ) //TODO may be there should be fabs( ) < DELTA? { for( int row = i + 1; row < AAsize; ++row ) { if( fabs( AA[row][i] ) > ALMOST_ZERO ) //TODO may be there should be fabs( ) > DELTA? { for( int col = 0; col < AAsize; ++col ) { storage[col] = AA[row][col]; //TODO may be we don't need a whole vector here, just single number. (I mean storage) AA[row][col] = AA[i][col]; AA[i][col] = storage[col]; } tmpNum = ff[row]; ff[row] = ff[i]; ff[i] = tmpNum; break; } } } } for( int i = 0; i < AAsize; ++i ) { if( fabs( AA[i][i] ) < ALMOST_ZERO ) { cout << "alert! UFO detected!\n"; } } vector<vector<PL_NUM>> LL( AAsize, vector<PL_NUM>( AAsize, 0.0 ) ); //TODO here we can use less memory, UU and LL are trialgular vector<vector<PL_NUM>> UU( AAsize, vector<PL_NUM>( AAsize, 0.0 ) ); //TODO initialization of arrays is slow //Crout's algorithm, theory is in book: Kincaid, Cheney - Numerical analysis: mathematics of scientific computing for( int k = 0; k < AAsize; ++k ) { UU[k][k] = 1; for( int i = k; i < AAsize; ++i ) { LL[i][k] = AA[i][k]; for( int s = 0; s <= k - 1; ++s ) { LL[i][k] -= LL[i][s] * UU[s][k]; } } for( int j = k + 1; j < AAsize; ++j ) { UU[k][j] = AA[k][j]; for( int s = 0; s <= k - 1; ++s ) { UU[k][j] -= LL[k][s] * UU[s][j]; } UU[k][j] /= LL[k][k]; } } //now we can find xx, by solving LL * zz = ff and then UU * x = zz; for theory look at the same book as for LU decomposition for( int i = 0; i < AAsize; ++i ) { (*xx)[i] = ff[i]; for( int j = 0; j <= i - 1; ++j ) { (*xx)[i] -= LL[i][j] * (*xx)[j]; } (*xx)[i] /= LL[i][i]; } for( int i = AAsize - 1; i >= 0; --i ) { for( int j = i + 1; j < AAsize; ++j ) { (*xx)[i] -= UU[i][j] * (*xx)[j]; } } }
void UNavMeshRenderingComponent::GatherData(struct FNavMeshSceneProxyData* CurrentData) const { #if WITH_RECAST const ARecastNavMesh* NavMesh = Cast<ARecastNavMesh>(GetOwner()); CurrentData->Reset(); CurrentData->bEnableDrawing = NavMesh->bEnableDrawing; CurrentData->bNeedsNewData = false; if (CurrentData && NavMesh && NavMesh->bEnableDrawing) { FHitProxyId HitProxyId = FHitProxyId(); CurrentData->bDrawPathCollidingGeometry = NavMesh->bDrawPathCollidingGeometry; CurrentData->NavMeshDrawOffset.Z = NavMesh->DrawOffset; CurrentData->NavMeshGeometry.bGatherPolyEdges = NavMesh->bDrawPolyEdges; CurrentData->NavMeshGeometry.bGatherNavMeshEdges = NavMesh->bDrawNavMeshEdges; const FNavDataConfig& NavConfig = NavMesh->GetConfig(); CurrentData->NavMeshColors[RECAST_DEFAULT_AREA] = NavConfig.Color.DWColor() > 0 ? NavConfig.Color : NavMeshRenderColor_RecastMesh; for (uint8 i = 0; i < RECAST_DEFAULT_AREA; ++i) { CurrentData->NavMeshColors[i] = NavMesh->GetAreaIDColor(i); } // just a little trick to make sure navmeshes with different sized are not drawn with same offset CurrentData->NavMeshDrawOffset.Z += NavMesh->GetConfig().AgentRadius / 10.f; NavMesh->BeginBatchQuery(); if (NavMesh->bDrawOctree) { const UNavigationSystem* NavSys = UNavigationSystem::GetCurrent(GetWorld()); const FNavigationOctree* NavOctree = NavSys ? NavSys->GetNavOctree() : NULL; if (NavOctree) { for (FNavigationOctree::TConstIterator<> NodeIt(*NavOctree); NodeIt.HasPendingNodes(); NodeIt.Advance()) { const FNavigationOctree::FNode& CurrentNode = NodeIt.GetCurrentNode(); const FOctreeNodeContext& CorrentContext = NodeIt.GetCurrentContext(); CurrentData->OctreeBounds.Add(CorrentContext.Bounds); FOREACH_OCTREE_CHILD_NODE(ChildRef) { if (CurrentNode.HasChild(ChildRef)) { NodeIt.PushChild(ChildRef); } } } } } NavMesh->GetDebugGeometry(CurrentData->NavMeshGeometry); const TArray<FVector>& MeshVerts = CurrentData->NavMeshGeometry.MeshVerts; // @fixme, this is going to double up on lots of interior lines if (NavMesh->bDrawTriangleEdges) { for (int32 AreaIdx = 0; AreaIdx < RECAST_MAX_AREAS; ++AreaIdx) { const TArray<int32>& MeshIndices = CurrentData->NavMeshGeometry.AreaIndices[AreaIdx]; for (int32 Idx=0; Idx<MeshIndices.Num(); Idx += 3) { CurrentData->ThickLineItems.Add(FNavMeshSceneProxyData::FDebugThickLine(MeshVerts[MeshIndices[Idx + 0]] + CurrentData->NavMeshDrawOffset, MeshVerts[MeshIndices[Idx + 1]] + CurrentData->NavMeshDrawOffset, NavMeshRenderColor_Recast_TriangleEdges, DefaultEdges_LineThickness)); CurrentData->ThickLineItems.Add(FNavMeshSceneProxyData::FDebugThickLine(MeshVerts[MeshIndices[Idx + 1]] + CurrentData->NavMeshDrawOffset, MeshVerts[MeshIndices[Idx + 2]] + CurrentData->NavMeshDrawOffset, NavMeshRenderColor_Recast_TriangleEdges, DefaultEdges_LineThickness)); CurrentData->ThickLineItems.Add(FNavMeshSceneProxyData::FDebugThickLine(MeshVerts[MeshIndices[Idx + 2]] + CurrentData->NavMeshDrawOffset, MeshVerts[MeshIndices[Idx + 0]] + CurrentData->NavMeshDrawOffset, NavMeshRenderColor_Recast_TriangleEdges, DefaultEdges_LineThickness)); } } } // make lines for tile edges if (NavMesh->bDrawPolyEdges) { const TArray<FVector>& TileEdgeVerts = CurrentData->NavMeshGeometry.PolyEdges; for (int32 Idx=0; Idx < TileEdgeVerts.Num(); Idx += 2) { CurrentData->TileEdgeLines.Add( FDebugRenderSceneProxy::FDebugLine(TileEdgeVerts[Idx] + CurrentData->NavMeshDrawOffset, TileEdgeVerts[Idx+1] + CurrentData->NavMeshDrawOffset, NavMeshRenderColor_Recast_TileEdges)); } } // make lines for navmesh edges if (NavMesh->bDrawNavMeshEdges) { const FColor EdgesColor = DarkenColor(CurrentData->NavMeshColors[RECAST_DEFAULT_AREA]); const TArray<FVector>& NavMeshEdgeVerts = CurrentData->NavMeshGeometry.NavMeshEdges; for (int32 Idx=0; Idx < NavMeshEdgeVerts.Num(); Idx += 2) { CurrentData->NavMeshEdgeLines.Add( FDebugRenderSceneProxy::FDebugLine(NavMeshEdgeVerts[Idx] + CurrentData->NavMeshDrawOffset, NavMeshEdgeVerts[Idx+1] + CurrentData->NavMeshDrawOffset, EdgesColor)); } } // offset all navigation-link positions if (!NavMesh->bDrawClusters) { for (int32 OffMeshLineIndex = 0; OffMeshLineIndex < CurrentData->NavMeshGeometry.OffMeshLinks.Num(); ++OffMeshLineIndex) { FRecastDebugGeometry::FOffMeshLink& Link = CurrentData->NavMeshGeometry.OffMeshLinks[OffMeshLineIndex]; const bool bLinkValid = (Link.ValidEnds & FRecastDebugGeometry::OMLE_Left) && (Link.ValidEnds & FRecastDebugGeometry::OMLE_Right); if (NavMesh->bDrawFailedNavLinks || (NavMesh->bDrawNavLinks && bLinkValid)) { const FVector V0 = Link.Left + CurrentData->NavMeshDrawOffset; const FVector V1 = Link.Right + CurrentData->NavMeshDrawOffset; const FColor LinkColor = ((Link.Direction && Link.ValidEnds) || (Link.ValidEnds & FRecastDebugGeometry::OMLE_Left)) ? DarkenColor(CurrentData->NavMeshColors[Link.AreaID]) : NavMeshRenderColor_OffMeshConnectionInvalid; CacheArc(CurrentData->NavLinkLines, V0, V1, 0.4f, 4, LinkColor, LinkLines_LineThickness); const FVector VOffset(0, 0, FVector::Dist(V0, V1) * 1.333f); CacheArrowHead(CurrentData->NavLinkLines, V1, V0+VOffset, 30.f, LinkColor, LinkLines_LineThickness); if (Link.Direction) { CacheArrowHead(CurrentData->NavLinkLines, V0, V1+VOffset, 30.f, LinkColor, LinkLines_LineThickness); } // if the connection as a whole is valid check if there are any of ends is invalid if (LinkColor != NavMeshRenderColor_OffMeshConnectionInvalid) { if (Link.Direction && (Link.ValidEnds & FRecastDebugGeometry::OMLE_Left) == 0) { // left end invalid - mark it DrawWireCylinder(CurrentData->NavLinkLines, V0, FVector(1,0,0), FVector(0,1,0), FVector(0,0,1), NavMeshRenderColor_OffMeshConnectionInvalid, Link.Radius, NavMesh->AgentMaxStepHeight, 16, 0, DefaultEdges_LineThickness); } if ((Link.ValidEnds & FRecastDebugGeometry::OMLE_Right) == 0) { DrawWireCylinder(CurrentData->NavLinkLines, V1, FVector(1,0,0), FVector(0,1,0), FVector(0,0,1), NavMeshRenderColor_OffMeshConnectionInvalid, Link.Radius, NavMesh->AgentMaxStepHeight, 16, 0, DefaultEdges_LineThickness); } } } } } if (NavMesh->bDrawTileLabels || NavMesh->bDrawPolygonLabels || NavMesh->bDrawDefaultPolygonCost || NavMesh->bDrawTileBounds) { // calculate appropriate points for displaying debug labels const int32 TilesCount = NavMesh->GetNavMeshTilesCount(); CurrentData->DebugLabels.Reserve(TilesCount); for (int32 TileIndex = 0; TileIndex < TilesCount; ++TileIndex) { int32 X, Y, Layer; if (NavMesh->GetNavMeshTileXY(TileIndex, X, Y, Layer)) { const FBox TileBoundingBox = NavMesh->GetNavMeshTileBounds(TileIndex); FVector TileLabelLocation = TileBoundingBox.GetCenter(); TileLabelLocation.Z = TileBoundingBox.Max.Z; FNavLocation NavLocation(TileLabelLocation); if (!NavMesh->ProjectPoint(TileLabelLocation, NavLocation, FVector(NavMesh->TileSizeUU/100, NavMesh->TileSizeUU/100, TileBoundingBox.Max.Z-TileBoundingBox.Min.Z))) { NavMesh->ProjectPoint(TileLabelLocation, NavLocation, FVector(NavMesh->TileSizeUU/2, NavMesh->TileSizeUU/2, TileBoundingBox.Max.Z-TileBoundingBox.Min.Z)); } if (NavMesh->bDrawTileLabels) { CurrentData->DebugLabels.Add(FNavMeshSceneProxyData::FDebugText( /*Location*/NavLocation.Location + CurrentData->NavMeshDrawOffset , /*Text*/FString::Printf(TEXT("(%d,%d:%d)"), X, Y, Layer) )); } if (NavMesh->bDrawPolygonLabels || NavMesh->bDrawDefaultPolygonCost) { TArray<FNavPoly> Polys; NavMesh->GetPolysInTile(TileIndex, Polys); if (NavMesh->bDrawDefaultPolygonCost) { float DefaultCosts[RECAST_MAX_AREAS]; float FixedCosts[RECAST_MAX_AREAS]; NavMesh->GetDefaultQueryFilter()->GetAllAreaCosts(DefaultCosts, FixedCosts, RECAST_MAX_AREAS); for(int k = 0; k < Polys.Num(); ++k) { uint32 AreaID = NavMesh->GetPolyAreaID(Polys[k].Ref); CurrentData->DebugLabels.Add(FNavMeshSceneProxyData::FDebugText( /*Location*/Polys[k].Center + CurrentData->NavMeshDrawOffset , /*Text*/FString::Printf(TEXT("\\%.3f; %.3f\\"), DefaultCosts[AreaID], FixedCosts[AreaID]) )); } } else { for(int k = 0; k < Polys.Num(); ++k) { uint32 NavPolyIndex = 0; uint32 NavTileIndex = 0; NavMesh->GetPolyTileIndex(Polys[k].Ref, NavPolyIndex, NavTileIndex); CurrentData->DebugLabels.Add(FNavMeshSceneProxyData::FDebugText( /*Location*/Polys[k].Center + CurrentData->NavMeshDrawOffset , /*Text*/FString::Printf(TEXT("[%X:%X]"), NavTileIndex, NavPolyIndex) )); } } } if (NavMesh->bDrawTileBounds) { FBox TileBox = NavMesh->GetNavMeshTileBounds(TileIndex); float DrawZ = (TileBox.Min.Z + TileBox.Max.Z) * 0.5f; // @hack average FVector LL(TileBox.Min.X, TileBox.Min.Y, DrawZ); FVector UR(TileBox.Max.X, TileBox.Max.Y, DrawZ); FVector UL(LL.X, UR.Y, DrawZ); FVector LR(UR.X, LL.Y, DrawZ); CurrentData->ThickLineItems.Add(FNavMeshSceneProxyData::FDebugThickLine(LL, UL, NavMeshRenderColor_TileBounds, DefaultEdges_LineThickness)); CurrentData->ThickLineItems.Add(FNavMeshSceneProxyData::FDebugThickLine(UL, UR, NavMeshRenderColor_TileBounds, DefaultEdges_LineThickness)); CurrentData->ThickLineItems.Add(FNavMeshSceneProxyData::FDebugThickLine(UR, LR, NavMeshRenderColor_TileBounds, DefaultEdges_LineThickness)); CurrentData->ThickLineItems.Add(FNavMeshSceneProxyData::FDebugThickLine(LR, LL, NavMeshRenderColor_TileBounds, DefaultEdges_LineThickness)); } } } } CurrentData->bSkipDistanceCheck = GIsEditor && (GEngine->GetDebugLocalPlayer() == NULL); CurrentData->bDrawClusters = NavMesh->bDrawClusters; NavMesh->FinishBatchQuery(); // Draw Mesh if (NavMesh->bDrawClusters) { for (int32 Idx = 0; Idx < CurrentData->NavMeshGeometry.Clusters.Num(); ++Idx) { const TArray<int32>& MeshIndices = CurrentData->NavMeshGeometry.Clusters[Idx].MeshIndices; if (MeshIndices.Num() == 0) { continue; } FNavMeshSceneProxyData::FDebugMeshData DebugMeshData; DebugMeshData.ClusterColor = GetClusterColor(Idx); for (int32 VertIdx=0; VertIdx < MeshVerts.Num(); ++VertIdx) { AddVertexHelper(DebugMeshData, MeshVerts[VertIdx] + CurrentData->NavMeshDrawOffset, DebugMeshData.ClusterColor); } for (int32 TriIdx=0; TriIdx < MeshIndices.Num(); TriIdx+=3) { AddTriangleHelper(DebugMeshData, MeshIndices[TriIdx], MeshIndices[TriIdx+1], MeshIndices[TriIdx+2]); } CurrentData->MeshBuilders.Add(DebugMeshData); } } else if (NavMesh->bDrawNavMesh) { for (int32 AreaType = 0; AreaType < RECAST_MAX_AREAS; ++AreaType) { const TArray<int32>& MeshIndices = CurrentData->NavMeshGeometry.AreaIndices[AreaType]; if (MeshIndices.Num() == 0) { continue; } FNavMeshSceneProxyData::FDebugMeshData DebugMeshData; for (int32 VertIdx=0; VertIdx < MeshVerts.Num(); ++VertIdx) { AddVertexHelper(DebugMeshData, MeshVerts[VertIdx] + CurrentData->NavMeshDrawOffset, CurrentData->NavMeshColors[AreaType]); } for (int32 TriIdx=0; TriIdx < MeshIndices.Num(); TriIdx+=3) { AddTriangleHelper(DebugMeshData, MeshIndices[TriIdx], MeshIndices[TriIdx+1], MeshIndices[TriIdx+2]); } DebugMeshData.ClusterColor = CurrentData->NavMeshColors[AreaType]; CurrentData->MeshBuilders.Add(DebugMeshData); } } if (NavMesh->bDrawPathCollidingGeometry) { // draw all geometry gathered in navoctree const FNavigationOctree* NavOctree = NavMesh->GetWorld()->GetNavigationSystem()->GetNavOctree(); TArray<FVector> PathCollidingGeomVerts; TArray <int32> PathCollidingGeomIndices; for (FNavigationOctree::TConstIterator<> It(*NavOctree); It.HasPendingNodes(); It.Advance()) { const FNavigationOctree::FNode& Node = It.GetCurrentNode(); for (FNavigationOctree::ElementConstIt ElementIt(Node.GetElementIt()); ElementIt; ElementIt++) { const FNavigationOctreeElement& Element = *ElementIt; if (Element.ShouldUseGeometry(&NavMesh->NavDataConfig) && Element.Data.CollisionData.Num()) { const FRecastGeometryCache CachedGeometry(Element.Data.CollisionData.GetData()); AppendGeometry(PathCollidingGeomVerts, PathCollidingGeomIndices, CachedGeometry.Verts, CachedGeometry.Header.NumVerts, CachedGeometry.Indices, CachedGeometry.Header.NumFaces); } } FOREACH_OCTREE_CHILD_NODE(ChildRef) { if (Node.HasChild(ChildRef)) { It.PushChild(ChildRef); } } } CurrentData->PathCollidingGeomIndices = PathCollidingGeomIndices; for (const auto& Vertex : PathCollidingGeomVerts) { CurrentData->PathCollidingGeomVerts.Add(FDynamicMeshVertex(Vertex)); } } if (CurrentData->NavMeshGeometry.BuiltMeshIndices.Num() > 0) { FNavMeshSceneProxyData::FDebugMeshData DebugMeshData; for (int32 VertIdx=0; VertIdx < MeshVerts.Num(); ++VertIdx) { AddVertexHelper(DebugMeshData, MeshVerts[VertIdx] + CurrentData->NavMeshDrawOffset, NavMeshRenderColor_RecastTileBeingRebuilt); } DebugMeshData.Indices.Append(CurrentData->NavMeshGeometry.BuiltMeshIndices); DebugMeshData.ClusterColor = NavMeshRenderColor_RecastTileBeingRebuilt; CurrentData->MeshBuilders.Add(DebugMeshData); // updates should be requested by FRecastNavMeshGenerator::TickAsyncBuild after tiles were refreshed } if (NavMesh->bDrawClusters) { for (int i = 0; i < CurrentData->NavMeshGeometry.ClusterLinks.Num(); i++) { const FRecastDebugGeometry::FClusterLink& CLink = CurrentData->NavMeshGeometry.ClusterLinks[i]; const FVector V0 = CLink.FromCluster + CurrentData->NavMeshDrawOffset; const FVector V1 = CLink.ToCluster + CurrentData->NavMeshDrawOffset + FVector(0,0,20.0f); CacheArc(CurrentData->ClusterLinkLines, V0, V1, 0.4f, 4, FColor::Black, ClusterLinkLines_LineThickness); const FVector VOffset(0, 0, FVector::Dist(V0, V1) * 1.333f); CacheArrowHead(CurrentData->ClusterLinkLines, V1, V0+VOffset, 30.f, FColor::Black, ClusterLinkLines_LineThickness); } } // cache segment links if (NavMesh->bDrawNavLinks) { for (int32 iArea = 0; iArea < RECAST_MAX_AREAS; iArea++) { const TArray<int32>& Indices = CurrentData->NavMeshGeometry.OffMeshSegmentAreas[iArea]; FNavMeshSceneProxyData::FDebugMeshData DebugMeshData; int32 VertBase = 0; for (int32 i = 0; i < Indices.Num(); i++) { FRecastDebugGeometry::FOffMeshSegment& SegInfo = CurrentData->NavMeshGeometry.OffMeshSegments[Indices[i]]; const FVector A0 = SegInfo.LeftStart + CurrentData->NavMeshDrawOffset; const FVector A1 = SegInfo.LeftEnd + CurrentData->NavMeshDrawOffset; const FVector B0 = SegInfo.RightStart + CurrentData->NavMeshDrawOffset; const FVector B1 = SegInfo.RightEnd + CurrentData->NavMeshDrawOffset; const FVector Edge0 = B0 - A0; const FVector Edge1 = B1 - A1; const float Len0 = Edge0.Size(); const float Len1 = Edge1.Size(); const FColor SegColor = DarkenColor(CurrentData->NavMeshColors[SegInfo.AreaID]); const FColor ColA = (SegInfo.ValidEnds & FRecastDebugGeometry::OMLE_Left) ? FColor::White : FColor::Black; const FColor ColB = (SegInfo.ValidEnds & FRecastDebugGeometry::OMLE_Right) ? FColor::White : FColor::Black; const int32 NumArcPoints = 8; const float ArcPtsScale = 1.0f / NumArcPoints; FVector Prev0 = EvalArc(A0, Edge0, Len0*0.25f, 0); FVector Prev1 = EvalArc(A1, Edge1, Len1*0.25f, 0); AddVertexHelper(DebugMeshData, Prev0, ColA); AddVertexHelper(DebugMeshData, Prev1, ColA); for (int32 j = 1; j <= NumArcPoints; j++) { const float u = j * ArcPtsScale; FVector Pt0 = EvalArc(A0, Edge0, Len0*0.25f, u); FVector Pt1 = EvalArc(A1, Edge1, Len1*0.25f, u); AddVertexHelper(DebugMeshData, Pt0, (j == NumArcPoints) ? ColB : FColor::White); AddVertexHelper(DebugMeshData, Pt1, (j == NumArcPoints) ? ColB : FColor::White); AddTriangleHelper(DebugMeshData, VertBase+0, VertBase+2, VertBase+1); AddTriangleHelper(DebugMeshData, VertBase+2, VertBase+3, VertBase+1); AddTriangleHelper(DebugMeshData, VertBase+0, VertBase+1, VertBase+2); AddTriangleHelper(DebugMeshData, VertBase+2, VertBase+1, VertBase+3); VertBase += 2; Prev0 = Pt0; Prev1 = Pt1; } VertBase += 2; DebugMeshData.ClusterColor = SegColor; } if (DebugMeshData.Indices.Num()) { CurrentData->MeshBuilders.Add(DebugMeshData); } } } CurrentData->NavMeshGeometry.PolyEdges.Empty(); CurrentData->NavMeshGeometry.NavMeshEdges.Empty(); }
static qboolean R_LoadMD4( model_t *mod, void *buffer, const char *mod_name ) { int i, j, k, lodindex; md4Header_t *pinmodel, *md4; md4Frame_t *frame; md4LOD_t *lod; md4Surface_t *surf; md4Triangle_t *tri; md4Vertex_t *v; int version; int size; shader_t *sh; int frameSize; pinmodel = (md4Header_t *)buffer; version = LittleLong (pinmodel->version); if (version != MD4_VERSION) { ri.Printf( PRINT_WARNING, "R_LoadMD4: %s has wrong version (%i should be %i)\n", mod_name, version, MD4_VERSION); return qfalse; } mod->type = MOD_MD4; size = LittleLong(pinmodel->ofsEnd); mod->dataSize += size; md4 = mod->md4 = ri.Hunk_Alloc( size, h_low ); memcpy(md4, buffer, size); LL(md4->ident); LL(md4->version); LL(md4->numFrames); LL(md4->numBones); LL(md4->numLODs); LL(md4->ofsFrames); LL(md4->ofsLODs); md4->ofsEnd = size; if ( md4->numFrames < 1 ) { ri.Printf( PRINT_WARNING, "R_LoadMD4: %s has no frames\n", mod_name ); return qfalse; } // we don't need to swap tags in the renderer, they aren't used // swap all the frames frameSize = (size_t)( &((md4Frame_t *)0)->bones[ md4->numBones ] ); for ( i = 0 ; i < md4->numFrames ; i++, frame++) { frame = (md4Frame_t *) ( (byte *)md4 + md4->ofsFrames + i * frameSize ); frame->radius = LittleFloat( frame->radius ); for ( j = 0 ; j < 3 ; j++ ) { frame->bounds[0][j] = LittleFloat( frame->bounds[0][j] ); frame->bounds[1][j] = LittleFloat( frame->bounds[1][j] ); frame->localOrigin[j] = LittleFloat( frame->localOrigin[j] ); } for ( j = 0 ; j < md4->numBones * sizeof( md4Bone_t ) / 4 ; j++ ) { ((float *)frame->bones)[j] = LittleFloat( ((float *)frame->bones)[j] ); } } // swap all the LOD's lod = (md4LOD_t *) ( (byte *)md4 + md4->ofsLODs ); for ( lodindex = 0 ; lodindex < md4->numLODs ; lodindex++ ) { // swap all the surfaces surf = (md4Surface_t *) ( (byte *)lod + lod->ofsSurfaces ); for ( i = 0 ; i < lod->numSurfaces ; i++) { LL(surf->ident); LL(surf->numTriangles); LL(surf->ofsTriangles); LL(surf->numVerts); LL(surf->ofsVerts); LL(surf->ofsEnd); if ( surf->numVerts > SHADER_MAX_VERTEXES ) { ri.Error (ERR_DROP, "R_LoadMD3: %s has more than %i verts on a surface (%i)", mod_name, SHADER_MAX_VERTEXES, surf->numVerts ); } if ( surf->numTriangles*3 > SHADER_MAX_INDEXES ) { ri.Error (ERR_DROP, "R_LoadMD3: %s has more than %i triangles on a surface (%i)", mod_name, SHADER_MAX_INDEXES / 3, surf->numTriangles ); } // change to surface identifier surf->ident = SF_MD4; // lowercase the surface name so skin compares are faster Q_strlwr( surf->name ); // register the shaders sh = R_FindShader( surf->shader, LIGHTMAP_NONE, qtrue ); if ( sh->defaultShader ) { surf->shaderIndex = 0; } else { surf->shaderIndex = sh->index; } // swap all the triangles tri = (md4Triangle_t *) ( (byte *)surf + surf->ofsTriangles ); for ( j = 0 ; j < surf->numTriangles ; j++, tri++ ) { LL(tri->indexes[0]); LL(tri->indexes[1]); LL(tri->indexes[2]); } // swap all the vertexes // FIXME // This makes TFC's skeletons work. Shouldn't be necessary anymore, but left // in for reference. //v = (md4Vertex_t *) ( (byte *)surf + surf->ofsVerts + 12); v = (md4Vertex_t *) ( (byte *)surf + surf->ofsVerts); for ( j = 0 ; j < surf->numVerts ; j++ ) { v->normal[0] = LittleFloat( v->normal[0] ); v->normal[1] = LittleFloat( v->normal[1] ); v->normal[2] = LittleFloat( v->normal[2] ); v->texCoords[0] = LittleFloat( v->texCoords[0] ); v->texCoords[1] = LittleFloat( v->texCoords[1] ); v->numWeights = LittleLong( v->numWeights ); for ( k = 0 ; k < v->numWeights ; k++ ) { v->weights[k].boneIndex = LittleLong( v->weights[k].boneIndex ); v->weights[k].boneWeight = LittleFloat( v->weights[k].boneWeight ); v->weights[k].offset[0] = LittleFloat( v->weights[k].offset[0] ); v->weights[k].offset[1] = LittleFloat( v->weights[k].offset[1] ); v->weights[k].offset[2] = LittleFloat( v->weights[k].offset[2] ); } // FIXME // This makes TFC's skeletons work. Shouldn't be necessary anymore, but left // in for reference. //v = (md4Vertex_t *)( ( byte * )&v->weights[v->numWeights] + 12 ); v = (md4Vertex_t *)( ( byte * )&v->weights[v->numWeights]); } // find the next surface surf = (md4Surface_t *)( (byte *)surf + surf->ofsEnd ); } // find the next LOD lod = (md4LOD_t *)( (byte *)lod + lod->ofsEnd ); } return qtrue; }
/* ================= R_LoadMD3 ================= */ static qboolean R_LoadMD3 (model_t *mod, int lod, void *buffer, const char *mod_name ) { int i, j; md3Header_t *pinmodel; md3Frame_t *frame; md3Surface_t *surf; md3Shader_t *shader; md3Triangle_t *tri; md3St_t *st; md3XyzNormal_t *xyz; md3Tag_t *tag; int version; int size; pinmodel = (md3Header_t *)buffer; version = LittleLong (pinmodel->version); if (version != MD3_VERSION) { ri.Printf( PRINT_WARNING, "R_LoadMD3: %s has wrong version (%i should be %i)\n", mod_name, version, MD3_VERSION); return qfalse; } mod->type = MOD_MESH; size = LittleLong(pinmodel->ofsEnd); mod->dataSize += size; mod->md3[lod] = ri.Hunk_Alloc( size, h_low ); memcpy (mod->md3[lod], buffer, LittleLong(pinmodel->ofsEnd) ); LL(mod->md3[lod]->ident); LL(mod->md3[lod]->version); LL(mod->md3[lod]->numFrames); LL(mod->md3[lod]->numTags); LL(mod->md3[lod]->numSurfaces); LL(mod->md3[lod]->ofsFrames); LL(mod->md3[lod]->ofsTags); LL(mod->md3[lod]->ofsSurfaces); LL(mod->md3[lod]->ofsEnd); if ( mod->md3[lod]->numFrames < 1 ) { ri.Printf( PRINT_WARNING, "R_LoadMD3: %s has no frames\n", mod_name ); return qfalse; } // swap all the frames frame = (md3Frame_t *) ( (byte *)mod->md3[lod] + mod->md3[lod]->ofsFrames ); for ( i = 0 ; i < mod->md3[lod]->numFrames ; i++, frame++) { frame->radius = LittleFloat( frame->radius ); for ( j = 0 ; j < 3 ; j++ ) { frame->bounds[0][j] = LittleFloat( frame->bounds[0][j] ); frame->bounds[1][j] = LittleFloat( frame->bounds[1][j] ); frame->localOrigin[j] = LittleFloat( frame->localOrigin[j] ); } } // swap all the tags tag = (md3Tag_t *) ( (byte *)mod->md3[lod] + mod->md3[lod]->ofsTags ); for ( i = 0 ; i < mod->md3[lod]->numTags * mod->md3[lod]->numFrames ; i++, tag++) { for ( j = 0 ; j < 3 ; j++ ) { tag->origin[j] = LittleFloat( tag->origin[j] ); tag->axis[0][j] = LittleFloat( tag->axis[0][j] ); tag->axis[1][j] = LittleFloat( tag->axis[1][j] ); tag->axis[2][j] = LittleFloat( tag->axis[2][j] ); } } // swap all the surfaces surf = (md3Surface_t *) ( (byte *)mod->md3[lod] + mod->md3[lod]->ofsSurfaces ); for ( i = 0 ; i < mod->md3[lod]->numSurfaces ; i++) { LL(surf->ident); LL(surf->flags); LL(surf->numFrames); LL(surf->numShaders); LL(surf->numTriangles); LL(surf->ofsTriangles); LL(surf->numVerts); LL(surf->ofsShaders); LL(surf->ofsSt); LL(surf->ofsXyzNormals); LL(surf->ofsEnd); if ( surf->numVerts > SHADER_MAX_VERTEXES ) { ri.Error (ERR_DROP, "R_LoadMD3: %s has more than %i verts on a surface (%i)", mod_name, SHADER_MAX_VERTEXES, surf->numVerts ); } if ( surf->numTriangles*3 > SHADER_MAX_INDEXES ) { ri.Error (ERR_DROP, "R_LoadMD3: %s has more than %i triangles on a surface (%i)", mod_name, SHADER_MAX_INDEXES / 3, surf->numTriangles ); } // change to surface identifier surf->ident = SF_MD3; // lowercase the surface name so skin compares are faster Q_strlwr( surf->name ); // strip off a trailing _1 or _2 // this is a crutch for q3data being a mess j = strlen( surf->name ); if ( j > 2 && surf->name[j-2] == '_' ) { surf->name[j-2] = 0; } // register the shaders shader = (md3Shader_t *) ( (byte *)surf + surf->ofsShaders ); for ( j = 0 ; j < surf->numShaders ; j++, shader++ ) { shader_t *sh; sh = R_FindShader( shader->name, LIGHTMAP_NONE, qtrue ); if ( sh->defaultShader ) { shader->shaderIndex = 0; } else { shader->shaderIndex = sh->index; } } // swap all the triangles tri = (md3Triangle_t *) ( (byte *)surf + surf->ofsTriangles ); for ( j = 0 ; j < surf->numTriangles ; j++, tri++ ) { LL(tri->indexes[0]); LL(tri->indexes[1]); LL(tri->indexes[2]); } // swap all the ST st = (md3St_t *) ( (byte *)surf + surf->ofsSt ); for ( j = 0 ; j < surf->numVerts ; j++, st++ ) { st->st[0] = LittleFloat( st->st[0] ); st->st[1] = LittleFloat( st->st[1] ); } // swap all the XyzNormals xyz = (md3XyzNormal_t *) ( (byte *)surf + surf->ofsXyzNormals ); for ( j = 0 ; j < surf->numVerts * surf->numFrames ; j++, xyz++ ) { xyz->xyz[0] = LittleShort( xyz->xyz[0] ); xyz->xyz[1] = LittleShort( xyz->xyz[1] ); xyz->xyz[2] = LittleShort( xyz->xyz[2] ); xyz->normal = LittleShort( xyz->normal ); } // find the next surface surf = (md3Surface_t *)( (byte *)surf + surf->ofsEnd ); } return qtrue; }
# define C1(K,i) (((u64*)(Cx.c+7))[2*K.c[(i)*8+1]]) # define C2(K,i) (((u64*)(Cx.c+6))[2*K.c[(i)*8+2]]) # define C3(K,i) (((u64*)(Cx.c+5))[2*K.c[(i)*8+3]]) # define C4(K,i) (((u64*)(Cx.c+4))[2*K.c[(i)*8+4]]) # define C5(K,i) (((u64*)(Cx.c+3))[2*K.c[(i)*8+5]]) # define C6(K,i) (((u64*)(Cx.c+2))[2*K.c[(i)*8+6]]) # define C7(K,i) (((u64*)(Cx.c+1))[2*K.c[(i)*8+7]]) #endif static const union { u8 c[(256*N+ROUNDS)*sizeof(u64)]; u64 q[(256*N+ROUNDS)]; } Cx = { { /* Note endian-neutral representation:-) */ LL(0x18,0x18,0x60,0x18,0xc0,0x78,0x30,0xd8), LL(0x23,0x23,0x8c,0x23,0x05,0xaf,0x46,0x26), LL(0xc6,0xc6,0x3f,0xc6,0x7e,0xf9,0x91,0xb8), LL(0xe8,0xe8,0x87,0xe8,0x13,0x6f,0xcd,0xfb), LL(0x87,0x87,0x26,0x87,0x4c,0xa1,0x13,0xcb), LL(0xb8,0xb8,0xda,0xb8,0xa9,0x62,0x6d,0x11), LL(0x01,0x01,0x04,0x01,0x08,0x05,0x02,0x09), LL(0x4f,0x4f,0x21,0x4f,0x42,0x6e,0x9e,0x0d), LL(0x36,0x36,0xd8,0x36,0xad,0xee,0x6c,0x9b), LL(0xa6,0xa6,0xa2,0xa6,0x59,0x04,0x51,0xff), LL(0xd2,0xd2,0x6f,0xd2,0xde,0xbd,0xb9,0x0c), LL(0xf5,0xf5,0xf3,0xf5,0xfb,0x06,0xf7,0x0e), LL(0x79,0x79,0xf9,0x79,0xef,0x80,0xf2,0x96), LL(0x6f,0x6f,0xa1,0x6f,0x5f,0xce,0xde,0x30), LL(0x91,0x91,0x7e,0x91,0xfc,0xef,0x3f,0x6d), LL(0x52,0x52,0x55,0x52,0xaa,0x07,0xa4,0xf8),
/* ================= R_LoadMD3 ================= */ static qboolean R_LoadMD3 (model_t *mod, int lod, void *buffer, const char *mod_name, qboolean &bAlreadyCached ) { int i, j; md3Header_t *pinmodel; md3Surface_t *surf; md3Shader_t *shader; int version; int size; #ifdef Q3_BIG_ENDIAN md3Frame_t *frame; md3Triangle_t *tri; md3St_t *st; md3XyzNormal_t *xyz; md3Tag_t *tag; #endif pinmodel= (md3Header_t *)buffer; // // read some fields from the binary, but only LittleLong() them when we know this wasn't an already-cached model... // version = pinmodel->version; size = pinmodel->ofsEnd; if (!bAlreadyCached) { version = LittleLong(version); size = LittleLong(size); } if (version != MD3_VERSION) { ri.Printf( PRINT_WARNING, "R_LoadMD3: %s has wrong version (%i should be %i)\n", mod_name, version, MD3_VERSION); return qfalse; } mod->type = MOD_MESH; mod->dataSize += size; qboolean bAlreadyFound = qfalse; mod->md3[lod] = (md3Header_t *) RE_RegisterModels_Malloc(size, buffer, mod_name, &bAlreadyFound, TAG_MODEL_MD3); assert(bAlreadyCached == bAlreadyFound); if (!bAlreadyFound) { // horrible new hackery, if !bAlreadyFound then we've just done a tag-morph, so we need to set the // bool reference passed into this function to true, to tell the caller NOT to do an FS_Freefile since // we've hijacked that memory block... // // Aaaargh. Kill me now... // bAlreadyCached = qtrue; assert( mod->md3[lod] == buffer ); // memcpy( mod->md3[lod], buffer, size ); // and don't do this now, since it's the same thing LL(mod->md3[lod]->ident); LL(mod->md3[lod]->version); LL(mod->md3[lod]->numFrames); LL(mod->md3[lod]->numTags); LL(mod->md3[lod]->numSurfaces); LL(mod->md3[lod]->ofsFrames); LL(mod->md3[lod]->ofsTags); LL(mod->md3[lod]->ofsSurfaces); LL(mod->md3[lod]->ofsEnd); } if ( mod->md3[lod]->numFrames < 1 ) { ri.Printf( PRINT_WARNING, "R_LoadMD3: %s has no frames\n", mod_name ); return qfalse; } if (bAlreadyFound) { return qtrue; // All done. Stop, go no further, do not pass Go... } #ifdef Q3_BIG_ENDIAN // swap all the frames frame = (md3Frame_t *) ( (byte *)mod->md3[lod] + mod->md3[lod]->ofsFrames ); for ( i = 0 ; i < mod->md3[lod]->numFrames ; i++, frame++) { LF(frame->radius); for ( j = 0 ; j < 3 ; j++ ) { LF(frame->bounds[0][j]); LF(frame->bounds[1][j]); LF(frame->localOrigin[j]); } } // swap all the tags tag = (md3Tag_t *) ( (byte *)mod->md3[lod] + mod->md3[lod]->ofsTags ); for ( i = 0 ; i < mod->md3[lod]->numTags * mod->md3[lod]->numFrames ; i++, tag++) { for ( j = 0 ; j < 3 ; j++ ) { LF(tag->origin[j]); LF(tag->axis[0][j]); LF(tag->axis[1][j]); LF(tag->axis[2][j]); } } #endif // swap all the surfaces surf = (md3Surface_t *) ( (byte *)mod->md3[lod] + mod->md3[lod]->ofsSurfaces ); for ( i = 0 ; i < mod->md3[lod]->numSurfaces ; i++) { LL(surf->flags); LL(surf->numFrames); LL(surf->numShaders); LL(surf->numTriangles); LL(surf->ofsTriangles); LL(surf->numVerts); LL(surf->ofsShaders); LL(surf->ofsSt); LL(surf->ofsXyzNormals); LL(surf->ofsEnd); if ( surf->numVerts > SHADER_MAX_VERTEXES ) { Com_Error (ERR_DROP, "R_LoadMD3: %s has more than %i verts on a surface (%i)", mod_name, SHADER_MAX_VERTEXES, surf->numVerts ); } if ( surf->numTriangles*3 > SHADER_MAX_INDEXES ) { Com_Error (ERR_DROP, "R_LoadMD3: %s has more than %i triangles on a surface (%i)", mod_name, SHADER_MAX_INDEXES / 3, surf->numTriangles ); } // change to surface identifier surf->ident = SF_MD3; // lowercase the surface name so skin compares are faster Q_strlwr( surf->name ); // strip off a trailing _1 or _2 // this is a crutch for q3data being a mess j = strlen( surf->name ); if ( j > 2 && surf->name[j-2] == '_' ) { surf->name[j-2] = 0; } // register the shaders shader = (md3Shader_t *) ( (byte *)surf + surf->ofsShaders ); for ( j = 0 ; j < surf->numShaders ; j++, shader++ ) { shader_t *sh; sh = R_FindShader( shader->name, lightmapsNone, stylesDefault, qtrue ); if ( sh->defaultShader ) { shader->shaderIndex = 0; } else { shader->shaderIndex = sh->index; } RE_RegisterModels_StoreShaderRequest(mod_name, &shader->name[0], &shader->shaderIndex); } #ifdef Q3_BIG_ENDIAN // swap all the triangles tri = (md3Triangle_t *) ( (byte *)surf + surf->ofsTriangles ); for ( j = 0 ; j < surf->numTriangles ; j++, tri++ ) { LL(tri->indexes[0]); LL(tri->indexes[1]); LL(tri->indexes[2]); } // swap all the ST st = (md3St_t *) ( (byte *)surf + surf->ofsSt ); for ( j = 0 ; j < surf->numVerts ; j++, st++ ) { LF(st->st[0]); LF(st->st[1]); } // swap all the XyzNormals xyz = (md3XyzNormal_t *) ( (byte *)surf + surf->ofsXyzNormals ); for ( j = 0 ; j < surf->numVerts * surf->numFrames ; j++, xyz++ ) { LS(xyz->xyz[0]); LS(xyz->xyz[1]); LS(xyz->xyz[2]); LS(xyz->normal); } #endif // find the next surface surf = (md3Surface_t *)( (byte *)surf + surf->ofsEnd ); } return qtrue; }
/* ================= R_LoadMDR ================= */ static qboolean R_LoadMDR( model_t *mod, void *buffer, int filesize, const char *mod_name ) { int i, j, k, l; mdrHeader_t *pinmodel, *mdr; mdrFrame_t *frame; mdrLOD_t *lod, *curlod; mdrSurface_t *surf, *cursurf; mdrTriangle_t *tri, *curtri; mdrVertex_t *v, *curv; mdrWeight_t *weight, *curweight; mdrTag_t *tag, *curtag; int size; shader_t *sh; pinmodel = (mdrHeader_t *)buffer; pinmodel->version = LittleLong(pinmodel->version); if (pinmodel->version != MDR_VERSION) { ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has wrong version (%i should be %i)\n", mod_name, pinmodel->version, MDR_VERSION); return qfalse; } size = LittleLong(pinmodel->ofsEnd); if(size > filesize) { ri.Printf(PRINT_WARNING, "R_LoadMDR: Header of %s is broken. Wrong filesize declared!\n", mod_name); return qfalse; } mod->type = MOD_MDR; LL(pinmodel->numFrames); LL(pinmodel->numBones); LL(pinmodel->ofsFrames); // This is a model that uses some type of compressed Bones. We don't want to uncompress every bone for each rendered frame // over and over again, we'll uncompress it in this function already, so we must adjust the size of the target md4. if(pinmodel->ofsFrames < 0) { // mdrFrame_t is larger than mdrCompFrame_t: size += pinmodel->numFrames * sizeof(frame->name); // now add enough space for the uncompressed bones. size += pinmodel->numFrames * pinmodel->numBones * ((sizeof(mdrBone_t) - sizeof(mdrCompBone_t))); } // simple bounds check if(pinmodel->numBones < 0 || sizeof(*mdr) + pinmodel->numFrames * (sizeof(*frame) + (pinmodel->numBones - 1) * sizeof(*frame->bones)) > size) { ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has broken structure.\n", mod_name); return qfalse; } mod->dataSize += size; mod->modelData = mdr = ri.Hunk_Alloc( size, h_low ); // Copy all the values over from the file and fix endian issues in the process, if necessary. mdr->ident = LittleLong(pinmodel->ident); mdr->version = pinmodel->version; // Don't need to swap byte order on this one, we already did above. Q_strncpyz(mdr->name, pinmodel->name, sizeof(mdr->name)); mdr->numFrames = pinmodel->numFrames; mdr->numBones = pinmodel->numBones; mdr->numLODs = LittleLong(pinmodel->numLODs); mdr->numTags = LittleLong(pinmodel->numTags); // We don't care about the other offset values, we'll generate them ourselves while loading. mod->numLods = mdr->numLODs; if ( mdr->numFrames < 1 ) { ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has no frames\n", mod_name); return qfalse; } /* The first frame will be put into the first free space after the header */ frame = (mdrFrame_t *)(mdr + 1); mdr->ofsFrames = (int)((byte *) frame - (byte *) mdr); if (pinmodel->ofsFrames < 0) { mdrCompFrame_t *cframe; // compressed model... cframe = (mdrCompFrame_t *)((byte *) pinmodel - pinmodel->ofsFrames); for(i = 0; i < mdr->numFrames; i++) { for(j = 0; j < 3; j++) { frame->bounds[0][j] = LittleFloat(cframe->bounds[0][j]); frame->bounds[1][j] = LittleFloat(cframe->bounds[1][j]); frame->localOrigin[j] = LittleFloat(cframe->localOrigin[j]); } frame->radius = LittleFloat(cframe->radius); frame->name[0] = '\0'; // No name supplied in the compressed version. for(j = 0; j < mdr->numBones; j++) { for(k = 0; k < (sizeof(cframe->bones[j].Comp) / 2); k++) { // Do swapping for the uncompressing functions. They seem to use shorts // values only, so I assume this will work. Never tested it on other // platforms, though. ((unsigned short *)(cframe->bones[j].Comp))[k] = LittleShort( ((unsigned short *)(cframe->bones[j].Comp))[k] ); } /* Now do the actual uncompressing */ MC_UnCompress(frame->bones[j].matrix, cframe->bones[j].Comp); } // Next Frame... cframe = (mdrCompFrame_t *) &cframe->bones[j]; frame = (mdrFrame_t *) &frame->bones[j]; } } else { mdrFrame_t *curframe; // uncompressed model... // curframe = (mdrFrame_t *)((byte *) pinmodel + pinmodel->ofsFrames); // swap all the frames for ( i = 0 ; i < mdr->numFrames ; i++) { for(j = 0; j < 3; j++) { frame->bounds[0][j] = LittleFloat(curframe->bounds[0][j]); frame->bounds[1][j] = LittleFloat(curframe->bounds[1][j]); frame->localOrigin[j] = LittleFloat(curframe->localOrigin[j]); } frame->radius = LittleFloat(curframe->radius); Q_strncpyz(frame->name, curframe->name, sizeof(frame->name)); for (j = 0; j < (int) (mdr->numBones * sizeof(mdrBone_t) / 4); j++) { ((float *)frame->bones)[j] = LittleFloat( ((float *)curframe->bones)[j] ); } curframe = (mdrFrame_t *) &curframe->bones[mdr->numBones]; frame = (mdrFrame_t *) &frame->bones[mdr->numBones]; } } // frame should now point to the first free address after all frames. lod = (mdrLOD_t *) frame; mdr->ofsLODs = (int) ((byte *) lod - (byte *)mdr); curlod = (mdrLOD_t *)((byte *) pinmodel + LittleLong(pinmodel->ofsLODs)); // swap all the LOD's for ( l = 0 ; l < mdr->numLODs ; l++) { // simple bounds check if((byte *) (lod + 1) > (byte *) mdr + size) { ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has broken structure.\n", mod_name); return qfalse; } lod->numSurfaces = LittleLong(curlod->numSurfaces); // swap all the surfaces surf = (mdrSurface_t *) (lod + 1); lod->ofsSurfaces = (int)((byte *) surf - (byte *) lod); cursurf = (mdrSurface_t *) ((byte *)curlod + LittleLong(curlod->ofsSurfaces)); for ( i = 0 ; i < lod->numSurfaces ; i++) { // simple bounds check if((byte *) (surf + 1) > (byte *) mdr + size) { ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has broken structure.\n", mod_name); return qfalse; } // first do some copying stuff surf->ident = SF_MDR; Q_strncpyz(surf->name, cursurf->name, sizeof(surf->name)); Q_strncpyz(surf->shader, cursurf->shader, sizeof(surf->shader)); surf->ofsHeader = (byte *) mdr - (byte *) surf; surf->numVerts = LittleLong(cursurf->numVerts); surf->numTriangles = LittleLong(cursurf->numTriangles); // numBoneReferences and BoneReferences generally seem to be unused // now do the checks that may fail. if ( surf->numVerts > SHADER_MAX_VERTEXES ) { ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has more than %i verts on %s (%i).\n", mod_name, SHADER_MAX_VERTEXES, surf->name[0] ? surf->name : "a surface", surf->numVerts ); return qfalse; } if ( surf->numTriangles*3 > SHADER_MAX_INDEXES ) { ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has more than %i triangles on %s (%i).\n", mod_name, SHADER_MAX_INDEXES / 3, surf->name[0] ? surf->name : "a surface", surf->numTriangles ); return qfalse; } // lowercase the surface name so skin compares are faster Q_strlwr( surf->name ); // register the shaders sh = R_FindShader(surf->shader, LIGHTMAP_NONE, qtrue); if ( sh->defaultShader ) { surf->shaderIndex = 0; } else { surf->shaderIndex = sh->index; } // now copy the vertexes. v = (mdrVertex_t *) (surf + 1); surf->ofsVerts = (int)((byte *) v - (byte *) surf); curv = (mdrVertex_t *) ((byte *)cursurf + LittleLong(cursurf->ofsVerts)); for(j = 0; j < surf->numVerts; j++) { LL(curv->numWeights); // simple bounds check if(curv->numWeights < 0 || (byte *) (v + 1) + (curv->numWeights - 1) * sizeof(*weight) > (byte *) mdr + size) { ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has broken structure.\n", mod_name); return qfalse; } v->normal[0] = LittleFloat(curv->normal[0]); v->normal[1] = LittleFloat(curv->normal[1]); v->normal[2] = LittleFloat(curv->normal[2]); v->texCoords[0] = LittleFloat(curv->texCoords[0]); v->texCoords[1] = LittleFloat(curv->texCoords[1]); v->numWeights = curv->numWeights; weight = &v->weights[0]; curweight = &curv->weights[0]; // Now copy all the weights for(k = 0; k < v->numWeights; k++) { weight->boneIndex = LittleLong(curweight->boneIndex); weight->boneWeight = LittleFloat(curweight->boneWeight); weight->offset[0] = LittleFloat(curweight->offset[0]); weight->offset[1] = LittleFloat(curweight->offset[1]); weight->offset[2] = LittleFloat(curweight->offset[2]); weight++; curweight++; } v = (mdrVertex_t *) weight; curv = (mdrVertex_t *) curweight; } // we know the offset to the triangles now: tri = (mdrTriangle_t *) v; surf->ofsTriangles = (int)((byte *) tri - (byte *) surf); curtri = (mdrTriangle_t *)((byte *) cursurf + LittleLong(cursurf->ofsTriangles)); // simple bounds check if(surf->numTriangles < 0 || (byte *) (tri + surf->numTriangles) > (byte *) mdr + size) { ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has broken structure.\n", mod_name); return qfalse; } for(j = 0; j < surf->numTriangles; j++) { tri->indexes[0] = LittleLong(curtri->indexes[0]); tri->indexes[1] = LittleLong(curtri->indexes[1]); tri->indexes[2] = LittleLong(curtri->indexes[2]); tri++; curtri++; } // tri now points to the end of the surface. surf->ofsEnd = (byte *) tri - (byte *) surf; surf = (mdrSurface_t *) tri; // find the next surface. cursurf = (mdrSurface_t *) ((byte *) cursurf + LittleLong(cursurf->ofsEnd)); } // surf points to the next lod now. lod->ofsEnd = (int)((byte *) surf - (byte *) lod); lod = (mdrLOD_t *) surf; // find the next LOD. curlod = (mdrLOD_t *)((byte *) curlod + LittleLong(curlod->ofsEnd)); } // lod points to the first tag now, so update the offset too. tag = (mdrTag_t *) lod; mdr->ofsTags = (int)((byte *) tag - (byte *) mdr); curtag = (mdrTag_t *) ((byte *)pinmodel + LittleLong(pinmodel->ofsTags)); // simple bounds check if(mdr->numTags < 0 || (byte *) (tag + mdr->numTags) > (byte *) mdr + size) { ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has broken structure.\n", mod_name); return qfalse; } for (i = 0 ; i < mdr->numTags ; i++) { tag->boneIndex = LittleLong(curtag->boneIndex); Q_strncpyz(tag->name, curtag->name, sizeof(tag->name)); tag++; curtag++; } // And finally we know the real offset to the end. mdr->ofsEnd = (int)((byte *) tag - (byte *) mdr); // phew! we're done. return qtrue; }
/* ================= R_LoadMDC ================= */ qboolean R_LoadMDC(model_t *mod, int lod, void *buffer, int bufferSize, const char *modName) { int i, j, k; mdcHeader_t *mdcModel = ( mdcHeader_t * ) buffer; md3Frame_t *mdcFrame; mdcSurface_t *mdcSurf; md3Shader_t *mdcShader; md3Triangle_t *mdcTri; md3St_t *mdcst; md3XyzNormal_t *mdcxyz; mdcXyzCompressed_t *mdcxyzComp; mdcTag_t *mdcTag; mdcTagName_t *mdcTagName; mdvModel_t *mdvModel; mdvFrame_t *frame; mdvSurface_t *surf; //, *surface; //unused srfTriangle_t *tri; mdvXyz_t *v; mdvSt_t *st; mdvTag_t *tag; mdvTagName_t *tagName; short *ps; int version; int size; version = LittleLong(mdcModel->version); if (version != MDC_VERSION) { Ren_Warning("R_LoadMD3: %s has wrong version (%i should be %i)\n", modName, version, MDC_VERSION); return qfalse; } mod->type = MOD_MESH; size = LittleLong(mdcModel->ofsEnd); mod->dataSize += size; mdvModel = mod->mdv[lod] = ri.Hunk_Alloc(sizeof(mdvModel_t), h_low); LL(mdcModel->ident); LL(mdcModel->version); LL(mdcModel->numFrames); LL(mdcModel->numTags); LL(mdcModel->numSurfaces); LL(mdcModel->ofsFrames); LL(mdcModel->ofsTags); LL(mdcModel->ofsSurfaces); LL(mdcModel->ofsEnd); LL(mdcModel->ofsEnd); LL(mdcModel->flags); LL(mdcModel->numSkins); if (mdcModel->numFrames < 1) { Ren_Warning("R_LoadMDC: '%s' has no frames\n", modName); return qfalse; } // swap all the frames mdvModel->numFrames = mdcModel->numFrames; mdvModel->frames = frame = ri.Hunk_Alloc(sizeof(*frame) * mdcModel->numFrames, h_low); mdcFrame = ( md3Frame_t * )(( byte * ) mdcModel + mdcModel->ofsFrames); for (i = 0; i < mdcModel->numFrames; i++, frame++, mdcFrame++) { #if 1 // ET HACK if (strstr(mod->name, "sherman") || strstr(mod->name, "mg42")) { frame->radius = 256; for (j = 0; j < 3; j++) { frame->bounds[0][j] = 128; frame->bounds[1][j] = -128; frame->localOrigin[j] = LittleFloat(mdcFrame->localOrigin[j]); } } else #endif { frame->radius = LittleFloat(mdcFrame->radius); for (j = 0; j < 3; j++) { frame->bounds[0][j] = LittleFloat(mdcFrame->bounds[0][j]); frame->bounds[1][j] = LittleFloat(mdcFrame->bounds[1][j]); frame->localOrigin[j] = LittleFloat(mdcFrame->localOrigin[j]); } } } // swap all the tags mdvModel->numTags = mdcModel->numTags; mdvModel->tags = tag = ri.Hunk_Alloc(sizeof(*tag) * (mdcModel->numTags * mdcModel->numFrames), h_low); mdcTag = ( mdcTag_t * )(( byte * ) mdcModel + mdcModel->ofsTags); for (i = 0; i < mdcModel->numTags * mdcModel->numFrames; i++, tag++, mdcTag++) { vec3_t angles; for (j = 0; j < 3; j++) { tag->origin[j] = ( float ) LittleShort(mdcTag->xyz[j]) * MD3_XYZ_SCALE; angles[j] = ( float ) LittleShort(mdcTag->angles[j]) * MDC_TAG_ANGLE_SCALE; } AnglesToAxis(angles, tag->axis); } mdvModel->tagNames = tagName = ri.Hunk_Alloc(sizeof(*tagName) * (mdcModel->numTags), h_low); mdcTagName = ( mdcTagName_t * )(( byte * ) mdcModel + mdcModel->ofsTagNames); for (i = 0; i < mdcModel->numTags; i++, tagName++, mdcTagName++) { Q_strncpyz(tagName->name, mdcTagName->name, sizeof(tagName->name)); } // swap all the surfaces mdvModel->numSurfaces = mdcModel->numSurfaces; mdvModel->surfaces = surf = ri.Hunk_Alloc(sizeof(*surf) * mdcModel->numSurfaces, h_low); mdcSurf = ( mdcSurface_t * )(( byte * ) mdcModel + mdcModel->ofsSurfaces); for (i = 0; i < mdcModel->numSurfaces; i++) { LL(mdcSurf->ident); LL(mdcSurf->flags); LL(mdcSurf->numBaseFrames); LL(mdcSurf->numCompFrames); LL(mdcSurf->numShaders); LL(mdcSurf->numTriangles); LL(mdcSurf->ofsTriangles); LL(mdcSurf->numVerts); LL(mdcSurf->ofsShaders); LL(mdcSurf->ofsSt); LL(mdcSurf->ofsXyzNormals); LL(mdcSurf->ofsXyzNormals); LL(mdcSurf->ofsXyzCompressed); LL(mdcSurf->ofsFrameBaseFrames); LL(mdcSurf->ofsFrameCompFrames); LL(mdcSurf->ofsEnd); if (mdcSurf->numVerts > SHADER_MAX_VERTEXES) { Ren_Drop("R_LoadMDC: %s has more than %i verts on a surface (%i)", modName, SHADER_MAX_VERTEXES, mdcSurf->numVerts); } if (mdcSurf->numTriangles > SHADER_MAX_TRIANGLES) { Ren_Drop("R_LoadMDC: %s has more than %i triangles on a surface (%i)", modName, SHADER_MAX_TRIANGLES, mdcSurf->numTriangles); } // change to surface identifier surf->surfaceType = SF_MDV; // give pointer to model for Tess_SurfaceMDX surf->model = mdvModel; // copy surface name Q_strncpyz(surf->name, mdcSurf->name, sizeof(surf->name)); // lowercase the surface name so skin compares are faster Q_strlwr(surf->name); // strip off a trailing _1 or _2 // this is a crutch for q3data being a mess j = strlen(surf->name); if (j > 2 && surf->name[j - 2] == '_') { surf->name[j - 2] = 0; } // register the shaders /* surf->numShaders = md3Surf->numShaders; surf->shaders = shader = ri.Hunk_Alloc(sizeof(*shader) * md3Surf->numShaders, h_low); md3Shader = (md3Shader_t *) ((byte *) md3Surf + md3Surf->ofsShaders); for(j = 0; j < md3Surf->numShaders; j++, shader++, md3Shader++) { shader_t *sh; sh = R_FindShader(md3Shader->name, SHADER_3D_DYNAMIC, RSF_DEFAULT); if(sh->defaultShader) { shader->shaderIndex = 0; } else { shader->shaderIndex = sh->index; } } */ // only consider the first shader mdcShader = ( md3Shader_t * )(( byte * ) mdcSurf + mdcSurf->ofsShaders); surf->shader = R_FindShader(mdcShader->name, SHADER_3D_DYNAMIC, qtrue); // swap all the triangles surf->numTriangles = mdcSurf->numTriangles; surf->triangles = tri = ri.Hunk_Alloc(sizeof(*tri) * mdcSurf->numTriangles, h_low); mdcTri = ( md3Triangle_t * )(( byte * ) mdcSurf + mdcSurf->ofsTriangles); for (j = 0; j < mdcSurf->numTriangles; j++, tri++, mdcTri++) { tri->indexes[0] = LittleLong(mdcTri->indexes[0]); tri->indexes[1] = LittleLong(mdcTri->indexes[1]); tri->indexes[2] = LittleLong(mdcTri->indexes[2]); } // swap all the XyzNormals mdcxyz = ( md3XyzNormal_t * )(( byte * ) mdcSurf + mdcSurf->ofsXyzNormals); for (j = 0; j < mdcSurf->numVerts * mdcSurf->numBaseFrames; j++, mdcxyz++) { mdcxyz->xyz[0] = LittleShort(mdcxyz->xyz[0]); mdcxyz->xyz[1] = LittleShort(mdcxyz->xyz[1]); mdcxyz->xyz[2] = LittleShort(mdcxyz->xyz[2]); mdcxyz->normal = LittleShort(mdcxyz->normal); } // swap all the XyzCompressed mdcxyzComp = ( mdcXyzCompressed_t * )(( byte * ) mdcSurf + mdcSurf->ofsXyzCompressed); for (j = 0; j < mdcSurf->numVerts * mdcSurf->numCompFrames; j++, mdcxyzComp++) { LL(mdcxyzComp->ofsVec); } // swap the frameBaseFrames ps = ( short * )(( byte * ) mdcSurf + mdcSurf->ofsFrameBaseFrames); for (j = 0; j < mdcModel->numFrames; j++, ps++) { *ps = LittleShort(*ps); } // swap the frameCompFrames ps = ( short * )(( byte * ) mdcSurf + mdcSurf->ofsFrameCompFrames); for (j = 0; j < mdcModel->numFrames; j++, ps++) { *ps = LittleShort(*ps); } surf->numVerts = mdcSurf->numVerts; surf->verts = v = ri.Hunk_Alloc(sizeof(*v) * (mdcSurf->numVerts * mdcModel->numFrames), h_low); for (j = 0; j < mdcModel->numFrames; j++) { int baseFrame; int compFrame = 0; baseFrame = ( int ) *(( short * )(( byte * ) mdcSurf + mdcSurf->ofsFrameBaseFrames) + j); mdcxyz = ( md3XyzNormal_t * )(( byte * ) mdcSurf + mdcSurf->ofsXyzNormals + baseFrame * mdcSurf->numVerts * sizeof(md3XyzNormal_t)); if (mdcSurf->numCompFrames > 0) { compFrame = ( int ) *(( short * )(( byte * ) mdcSurf + mdcSurf->ofsFrameCompFrames) + j); if (compFrame >= 0) { mdcxyzComp = ( mdcXyzCompressed_t * )(( byte * ) mdcSurf + mdcSurf->ofsXyzCompressed + compFrame * mdcSurf->numVerts * sizeof(mdcXyzCompressed_t)); } } for (k = 0; k < mdcSurf->numVerts; k++, v++, mdcxyz++) { v->xyz[0] = LittleShort(mdcxyz->xyz[0]) * MD3_XYZ_SCALE; v->xyz[1] = LittleShort(mdcxyz->xyz[1]) * MD3_XYZ_SCALE; v->xyz[2] = LittleShort(mdcxyz->xyz[2]) * MD3_XYZ_SCALE; if (mdcSurf->numCompFrames > 0 && compFrame >= 0) { vec3_t ofsVec; R_MDC_DecodeXyzCompressed2(LittleShort(mdcxyzComp->ofsVec), ofsVec); VectorAdd(v->xyz, ofsVec, v->xyz); mdcxyzComp++; } } } // swap all the ST surf->st = st = ri.Hunk_Alloc(sizeof(*st) * mdcSurf->numVerts, h_low); mdcst = ( md3St_t * )(( byte * ) mdcSurf + mdcSurf->ofsSt); for (j = 0; j < mdcSurf->numVerts; j++, mdcst++, st++) { st->st[0] = LittleFloat(mdcst->st[0]); st->st[1] = LittleFloat(mdcst->st[1]); } // find the next surface mdcSurf = ( mdcSurface_t * )(( byte * ) mdcSurf + mdcSurf->ofsEnd); surf++; } #if 1 // create VBO surfaces from md3 surfaces { mdvNormTanBi_t *vertexes; mdvNormTanBi_t *vert; growList_t vboSurfaces; srfVBOMDVMesh_t *vboSurf; byte *data; int dataSize; int dataOfs; vec4_t tmp; GLuint ofsTexCoords; GLuint ofsTangents; GLuint ofsBinormals; GLuint ofsNormals; GLuint sizeXYZ = 0; GLuint sizeTangents = 0; GLuint sizeBinormals = 0; GLuint sizeNormals = 0; int vertexesNum; int f; Com_InitGrowList(&vboSurfaces, 10); for (i = 0, surf = mdvModel->surfaces; i < mdvModel->numSurfaces; i++, surf++) { //allocate temp memory for vertex data vertexes = (mdvNormTanBi_t *)ri.Hunk_AllocateTempMemory(sizeof(*vertexes) * surf->numVerts * mdvModel->numFrames); // calc tangent spaces { const float *v0, *v1, *v2; const float *t0, *t1, *t2; vec3_t tangent; vec3_t binormal; vec3_t normal; for (j = 0, vert = vertexes; j < (surf->numVerts * mdvModel->numFrames); j++, vert++) { VectorClear(vert->tangent); VectorClear(vert->binormal); VectorClear(vert->normal); } for (f = 0; f < mdvModel->numFrames; f++) { for (j = 0, tri = surf->triangles; j < surf->numTriangles; j++, tri++) { v0 = surf->verts[surf->numVerts * f + tri->indexes[0]].xyz; v1 = surf->verts[surf->numVerts * f + tri->indexes[1]].xyz; v2 = surf->verts[surf->numVerts * f + tri->indexes[2]].xyz; t0 = surf->st[tri->indexes[0]].st; t1 = surf->st[tri->indexes[1]].st; t2 = surf->st[tri->indexes[2]].st; #if 1 R_CalcTangentSpace(tangent, binormal, normal, v0, v1, v2, t0, t1, t2); #else R_CalcNormalForTriangle(normal, v0, v1, v2); R_CalcTangentsForTriangle(tangent, binormal, v0, v1, v2, t0, t1, t2); #endif for (k = 0; k < 3; k++) { float *v; v = vertexes[surf->numVerts * f + tri->indexes[k]].tangent; VectorAdd(v, tangent, v); v = vertexes[surf->numVerts * f + tri->indexes[k]].binormal; VectorAdd(v, binormal, v); v = vertexes[surf->numVerts * f + tri->indexes[k]].normal; VectorAdd(v, normal, v); } } } for (j = 0, vert = vertexes; j < (surf->numVerts * mdvModel->numFrames); j++, vert++) { VectorNormalize(vert->tangent); VectorNormalize(vert->binormal); VectorNormalize(vert->normal); } } //Ren_Print("...calculating MDC mesh VBOs ( '%s', %i verts %i tris )\n", surf->name, surf->numVerts, surf->numTriangles); // create surface vboSurf = ri.Hunk_Alloc(sizeof(*vboSurf), h_low); Com_AddToGrowList(&vboSurfaces, vboSurf); vboSurf->surfaceType = SF_VBO_MDVMESH; vboSurf->mdvModel = mdvModel; vboSurf->mdvSurface = surf; vboSurf->numIndexes = surf->numTriangles * 3; vboSurf->numVerts = surf->numVerts; /* vboSurf->vbo = R_CreateVBO2(va("staticWorldMesh_vertices %i", vboSurfaces.currentElements), numVerts, optimizedVerts, ATTR_POSITION | ATTR_TEXCOORD | ATTR_LIGHTCOORD | ATTR_TANGENT | ATTR_BINORMAL | ATTR_NORMAL | ATTR_COLOR); */ vboSurf->ibo = R_CreateIBO2(va("staticMDCMesh_IBO %s", surf->name), surf->numTriangles, surf->triangles, VBO_USAGE_STATIC); // create VBO vertexesNum = surf->numVerts; dataSize = (surf->numVerts * mdvModel->numFrames * sizeof(vec4_t) * 4) + // xyz, tangent, binormal, normal (surf->numVerts * sizeof(vec4_t)); // texcoords data = ri.Hunk_AllocateTempMemory(dataSize); dataOfs = 0; // feed vertex XYZ for (f = 0; f < mdvModel->numFrames; f++) { for (j = 0; j < vertexesNum; j++) { for (k = 0; k < 3; k++) { tmp[k] = surf->verts[f * vertexesNum + j].xyz[k]; } tmp[3] = 1; Com_Memcpy(data + dataOfs, ( vec_t * ) tmp, sizeof(vec4_t)); dataOfs += sizeof(vec4_t); } if (f == 0) { sizeXYZ = dataOfs; } } // feed vertex texcoords ofsTexCoords = dataOfs; for (j = 0; j < vertexesNum; j++) { for (k = 0; k < 2; k++) { tmp[k] = surf->st[j].st[k]; } tmp[2] = 0; tmp[3] = 1; Com_Memcpy(data + dataOfs, ( vec_t * ) tmp, sizeof(vec4_t)); dataOfs += sizeof(vec4_t); } // feed vertex tangents ofsTangents = dataOfs; for (f = 0; f < mdvModel->numFrames; f++) { for (j = 0; j < vertexesNum; j++) { for (k = 0; k < 3; k++) { tmp[k] = vertexes[f * vertexesNum + j].tangent[k]; } tmp[3] = 1; Com_Memcpy(data + dataOfs, ( vec_t * ) tmp, sizeof(vec4_t)); dataOfs += sizeof(vec4_t); } if (f == 0) { sizeTangents = dataOfs - ofsTangents; } } // feed vertex binormals ofsBinormals = dataOfs; for (f = 0; f < mdvModel->numFrames; f++) { for (j = 0; j < vertexesNum; j++) { for (k = 0; k < 3; k++) { tmp[k] = vertexes[f * vertexesNum + j].binormal[k]; } tmp[3] = 1; Com_Memcpy(data + dataOfs, ( vec_t * ) tmp, sizeof(vec4_t)); dataOfs += sizeof(vec4_t); } if (f == 0) { sizeBinormals = dataOfs - ofsBinormals; } } // feed vertex normals ofsNormals = dataOfs; for (f = 0; f < mdvModel->numFrames; f++) { for (j = 0; j < vertexesNum; j++) { for (k = 0; k < 3; k++) { tmp[k] = vertexes[f * vertexesNum + j].normal[k]; } tmp[3] = 1; Com_Memcpy(data + dataOfs, ( vec_t * ) tmp, sizeof(vec4_t)); dataOfs += sizeof(vec4_t); } if (f == 0) { sizeNormals = dataOfs - ofsNormals; } } vboSurf->vbo = R_CreateVBO(va("staticMDCMesh_VBO '%s'", surf->name), data, dataSize, VBO_USAGE_STATIC); vboSurf->vbo->ofsXYZ = 0; vboSurf->vbo->ofsTexCoords = ofsTexCoords; vboSurf->vbo->ofsLightCoords = ofsTexCoords; vboSurf->vbo->ofsTangents = ofsTangents; vboSurf->vbo->ofsBinormals = ofsBinormals; vboSurf->vbo->ofsNormals = ofsNormals; vboSurf->vbo->sizeXYZ = sizeXYZ; vboSurf->vbo->sizeTangents = sizeTangents; vboSurf->vbo->sizeBinormals = sizeBinormals; vboSurf->vbo->sizeNormals = sizeNormals; ri.Hunk_FreeTempMemory(data); ri.Hunk_FreeTempMemory(vertexes); } // move VBO surfaces list to hunk mdvModel->numVBOSurfaces = vboSurfaces.currentElements; mdvModel->vboSurfaces = ri.Hunk_Alloc(mdvModel->numVBOSurfaces * sizeof(*mdvModel->vboSurfaces), h_low); for (i = 0; i < mdvModel->numVBOSurfaces; i++) { mdvModel->vboSurfaces[i] = ( srfVBOMDVMesh_t * ) Com_GrowListElement(&vboSurfaces, i); } Com_DestroyGrowList(&vboSurfaces); } #endif return qtrue; }
node * insert(node *T,int x) { if(T==NULL) { T=(node*)malloc(sizeof(node)); T->data=x; T->left=NULL; T->right=NULL; } else if(x > T->data) // insert in right subtree { T->right=insert(T->right,x); if(BF(T)==-2) if(x>T->right->data) T=RR(T); else T=RL(T); } else if(x<T->data) { T->left=insert(T->left,x); if(BF(T)==2) if(x < T->left->data) T=LL(T); else T=LR(T); } T->ht=height(T); return(T); }