Paste #BmC -- näytä pelkkänä tekstinä -- uusi tämän pohjalta
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | void inventorycube(video::IImage *top, video::IImage *left, video::IImage *right, video::IImage *dst) { TimeTaker timetaker("inventorycube"); if(top == NULL || left == NULL || right == NULL || dst == NULL) return; core::dimension2d<u32> topdim = top->getDimension(); core::dimension2d<u32> leftdim = left->getDimension(); core::dimension2d<u32> rightdim = right->getDimension(); core::dimension2d<u32> dstdim = dst->getDimension(); assert(dst->getColorFormat() == video::ECF_A8R8G8B8); u32 *data = (u32*) dst->lock(); if(data == NULL) return; u32 w = dstdim.Width; u32 h = dstdim.Height; // Set destination image to fully transparent memset(data, 0, w*h*sizeof(u32)); // Calculate projection-to-view transformation // (orthogonal, left-handed) f32 pw = 1.65; // width of view volume f32 ph = 1.65; // height of view volume v2f pscale(pw / w, -ph / h); v2f ptrans(-pw / 2, ph / 2); // Calculate view-to-world transformation (left-handed) v3f position(0, 1.0, -1.5); // camera position position.rotateXZBy(45); // ^ v3f target(0, 0, 0); // camera look-at point v3f upVector(0, 1, 0); // camera up vector v3f zaxis = target - position; zaxis.normalize(); v3f xaxis = upVector.crossProduct(zaxis); xaxis.normalize(); v3f yaxis = zaxis.crossProduct(xaxis); // Calculate projection-to-world transformation core::matrix4 pt; // (part of a) matrix pt[0] = pscale.X*xaxis.X; pt[1] = pscale.X*xaxis.Y; pt[2] = pscale.X*xaxis.Z; pt[4] = pscale.Y*yaxis.X; pt[5] = pscale.Y*yaxis.Y; pt[6] = pscale.Y*yaxis.Z; pt[8] = zaxis.X; pt[9] = zaxis.Y; pt[10] = zaxis.Z; pt[12] = ptrans.X * xaxis.X + ptrans.Y * yaxis.X + position.X; pt[13] = ptrans.X * xaxis.Y + ptrans.Y * yaxis.Y + position.Y; pt[14] = ptrans.X * xaxis.Z + ptrans.Y * yaxis.Z + position.Z; // Calculate coefficients needed to calculate pz // (z in projection space) // This works because the shape of the unit cube is known assert(fabs(pt[8]) > 1e-6); assert(fabs(pt[9]) > 1e-6); assert(fabs(pt[10]) > 1e-6); // world coordinates: (wx, wy, wz) // top face: wy = 0.5 v3f pzcoeff_top = v3f(-pt[1], -pt[5], 0.5 - pt[13]) / pt[9]; // left face: wz = -0.5 v3f pzcoeff_left = v3f(-pt[2], -pt[6], -0.5 - pt[14]) / pt[10]; // right face: wx = 0.5 v3f pzcoeff_right = v3f(-pt[0], -pt[4], 0.5 - pt[12]) / pt[8]; u32 *ptr = data; for(u32 py = 0; py < h; ++py) for(u32 px = 0; px < w; ++px) { v3f projectionPos(px, py, 1); f32 pz, wx, wy, wz; pz = projectionPos.dotProduct(pzcoeff_top); wx = px*pt[0] + py*pt[4] + pz*pt[8] + pt[12]; wz = px*pt[2] + py*pt[6] + pz*pt[10] + pt[14]; if(wx*wx < 0.25 && wz*wz < 0.25){ // |wx|, |wz| < 0.5? s32 top_px = topdim.Width * (wx+0.5); s32 top_py = topdim.Height * (wz+0.5); video::SColor pixel = top->getPixel(top_px, top_py); *ptr++ = pixel.color; continue; } pz = projectionPos.dotProduct(pzcoeff_left); wx = px*pt[0] + py*pt[4] + pz*pt[8] + pt[12]; wy = px*pt[1] + py*pt[5] + pz*pt[9] + pt[13]; if(wx*wx < 0.25 && wy*wy < 0.25){ // |wx|, |wy| < 0.5? s32 left_px = leftdim.Width * (wx+0.5); s32 left_py = leftdim.Height * (wy+0.5); video::SColor pixel = left->getPixel(left_px, left_py); *ptr++ = pixel.color; continue; } pz = projectionPos.dotProduct(pzcoeff_right); wy = px*pt[1] + py*pt[5] + pz*pt[9] + pt[13]; wz = px*pt[2] + py*pt[6] + pz*pt[10] + pt[14]; if(wy*wy < 0.25 && wz*wz < 0.25){ // |wy|, |wz| < 0.5? s32 right_px = rightdim.Width * (wy+0.5); s32 right_py = rightdim.Height * (wz+0.5); video::SColor pixel = right->getPixel(right_px, right_py); *ptr++ = pixel.color; continue; } ptr++; } timetaker.stop(); } |